Vamos começar com um experimento rápido.

Você tem uma rede de 3 computadores, usados ​​por Alice, Bob e Charlie. Todos os três participantes podem enviar mensagens, mas de maneira que todos os outros clientes conectados à rede possam lê-los. Este é o único formulário de comunicação possível entre os participantes.

Se Alice envia uma mensagem pelos fios, Bob e Charlie entendem. Em outras palavras, Alice não pode enviar uma mensagem direta para Bob sem Charlie também.

Mas Alice quer enviar uma mensagem confidencial para Bob e não quer que Charlie seja capaz de lê-la.

Parece impossível com essas regras estritas, certo? A coisa linda que esse problema foi resolvido em 1976 por Whitfield Diffie e Martin Hellman.

Esta é uma versão simplificada do mundo real, mas enfrentamos o mesmo problema ao nos comunicar através da maior rede que já existiu.

Normalmente, você não está diretamente conectado à Internet, mas faz parte de uma rede local menor, chamada Ethernet.

Essa rede menor pode ser cabeada ou sem fio (Wi-Fi), mas o conceito básico permanece. Se você enviar um sinal pela rede, esse sinal poderá ser lido por todos os outros clientes conectados à mesma rede.

network ethernet

Depois de emitir uma mensagem para o servidor do seu banco com as informações do cartão de crédito, todos os outros clientes da rede local receberão a mensagem, incluindo o roteador. Em seguida, ele será encaminhado para o servidor real do banco. Todos os outros clientes irão ignorar a mensagem.

Mas e se houver um cliente mal-intencionado na rede que não ignorará suas mensagens confidenciais, mas as lerá? Como é possível que você ainda tenha dinheiro na sua conta bancária?

Criptografia

É claro neste momento que precisamos usar algum tipo de criptografia para garantir que a mensagem seja legível para Alice e Bob, mas sem sentido para Charlie.

As informações de criptografia são feitas por um algoritmo de criptografia, que pega uma chave (por exemplo, uma string) e devolve um valor criptografado, chamado texto cifrado. O texto cifrado é apenas uma string completamente aleatória.

É importante que o valor criptografado (texto cifrado) possa ser descriptografado apenas com a chave original. Isso é chamado de algoritmo de chave simétrica, porque você precisa da mesma chave para descriptografar a mensagem com a qual ela foi criptografada. Também existem algoritmos de chave assimétrica, mas não precisamos deles no momento.

Para facilitar a compreensão disso, aqui está um algoritmo de criptografia fictício implementado em JavaScript:

function encrypt(message, key) {    return message.split("").map(character => {        const characterAsciiCode = character.charCodeAt(0)    	return String.fromCharCode(characterAsciiCode+key.length)    }).join("");}
Criptografando

Nesta função, mapeei cada caractere em outro caractere com base no comprimento da tecla especificada.

Cada caractere tem uma representação inteira, chamada código ASCII. Há um dicionário que contém todos os caracteres com seu código, chamado tabela ASCII. Então incrementamos esse número inteiro pelo comprimento da chave:

image 13
Mapeamento de caracteres

Descriptografar o texto cifrado é bastante semelhante. Mas, em vez de acrescentar, subtraímos o tamanho da chave de cada caractere no texto cifrado, para que retornemos a mensagem original.

function decrypt(cipher, key) {    return cipher.split("").map(character => {        const characterAsciiCode = character.charCodeAt(0)    	return String.fromCharCode(characterAsciiCode-key.length)    }).join("");}
Descriptografando

Finalmente, aqui está a criptografia fictícia em ação:

const message = "Hi Bob, here is a confidential message!";const key = "password";const cipher = encrypt(message, key);console.log("Encrypted message:", cipher);// Encrypted message: Pq(Jwj4(pmzm(q{(i(kwvnqlmv|qit(um{{iom)const decryptedMessage = decrypt(cipher, key);console.log("Decrypted message:", decryptedMessage);// Decrypted message: Hi Bob, here is a confidential message!
Usando nosso algoritmo

Aplicamos algum grau de criptografia à mensagem, mas esse algoritmo foi útil apenas para fins de demonstração, para entender como os algoritmos de criptografia de chave simétrica se comportam.

Existem alguns problemas com essa implementação, além de lidar mal com casos de canto e tipos de parâmetros.

Antes de tudo, cada chave de 8 caracteres pode descriptografar a mensagem que foi criptografada com a chave “senha”. Queremos que um algoritmo de criptografia só possa descriptografar uma mensagem se dermos a mesma chave com a qual a mensagem foi criptografada. Uma fechadura da porta que pode ser aberta por qualquer outra chave não é tão útil.

Em segundo lugar, a lógica é muito simples – cada caractere é alterado para a mesma quantidade na tabela ASCII, o que é previsível demais. Precisamos de algo mais complexo para tornar mais difícil descobrir a mensagem sem a chave.

Em terceiro lugar, não há um comprimento mínimo de chave. Os algoritmos modernos funcionam com pelo menos chaves de 128 bits (~ 16 caracteres). Isso aumenta significativamente o número de chaves possíveis e, com isso, a segurança da criptografia.

Por fim, leva muito pouco tempo para criptografar ou descriptografar a mensagem. Este é um problema porque não leva muito tempo para experimentar todas as chaves possíveis e quebrar a mensagem criptografada.

Isso está de mãos dadas com o comprimento da chave: um algoritmo é seguro se eu, como invasor, quiser encontrar a chave, preciso tentar um grande número de combinações de teclas e leva um tempo relativamente longo para tentar uma única combinação.

Existe uma grande variedade de algoritmos de criptografia simétrica que abordam todas essas reivindicações, geralmente usados ​​juntos para encontrar uma boa proporção de velocidade e segurança para todas as situações.

Os algoritmos de chave simétrica mais populares são Dois peixes, Serpente, AES (Rijndael), Blowfish, CAST5, RC4, TDESe IDÉIA.

Se você quiser saber mais sobre criptografia em geral, confira essa conversa.

Troca de chaves

Parece que reduzimos o espaço original do problema. Com a criptografia, podemos criar uma mensagem significativa para as partes qualificadas para ler as informações, mas ilegível para outras pessoas.

Quando Alice deseja escrever uma mensagem confidencial, ela pega uma chave e criptografa sua mensagem e envia o texto cifrado através dos fios. Bob e Charlie receberiam a mensagem criptografada, mas nenhum deles poderia interpretá-la sem a chave de Alice.

Agora, a única pergunta a ser respondida é como Alice e Bob podem encontrar uma chave comum apenas comunicando-se pela rede e impedir que Charlie descubra a mesma chave.

Se Alice enviar sua chave diretamente através dos fios, Charlie a interceptará e poderá descriptografar todas as mensagens de Alice. Portanto, isso não é uma solução. Isso é chamado de problema de troca de chaves na ciência da computação.

Troca de chaves Diffie – Hellman

Esse algoritmo interessante fornece uma maneira de gerar uma chave compartilhada entre duas pessoas, de forma que a chave não possa ser vista pela observação da comunicação.

Como primeiro passo, diremos que existe um número primo enorme, conhecido por todos os participantes, é informação pública. Nós chamamos isso “p” ou módulo.

Há também outro número público chamado “g” ou base, que é menor que p.

Não se preocupe com a forma como esses números são gerados. Por uma questão de simplicidade, digamos que Alice escolhe um número primo muito grande (p) e um número consideravelmente inferior a p. Ela então os envia pelos fios sem criptografia, para que todos os participantes conheçam esses números.

Exemplo: Para entender isso através de um exemplo, usaremos números pequenos. Digamos p = 23 e g = 5.

Como um segundo passo, Alice (uma) e Bob (b) escolherão um número secreto, que eles não contarão a ninguém, apenas moram localmente em seus computadores.

Exemplo: Digamos que Alice escolheu 4 (a = 4) e Bob escolheu 3 (b = 3)

Como próximo passo, eles farão algumas contas nos números secretos e calcularão:

  1. a base (g) no poder de seu número secreto,
  2. e leve o módulo do número calculado para p.
  3. Ligue para o resultado UMA (para Alice) e B (para Bob).

O módulo é uma declaração matemática simples, e a usamos para encontrar o restante depois de dividir um número por outro. Aqui está um exemplo: 23 mod 4 = 3, porque 23/4 é 5 e 3 permanece.

Talvez seja mais fácil ver tudo isso no código:

// baseconst g = 5;// modulusconst p = 23;// Alice's randomly picked numberconst a = 4;// Alice's calculated valueconst A = Math.pow(g, a)%p;// Do the same for Bobconst b = 3;const B = Math.pow(g, b)%p;console.log("Alice's calculated value (A):", A);// Alice's calculated value (A): 4console.log("Bob's calculated value (B):", B);// Bob's calculated value (B): 10

Agora, Alice e Bob enviarão seus valores calculados (UMA, B) através da rede, para que todos os participantes os conheçam.

Como um último passo, Alice e Bob terão os valores calculados um do outro e farão o seguinte:

  1. Alice assumirá o valor calculado de Bob (B) no poder de seu número secreto (uma),
  2. e calcule o módulo desse número para p e chamará o resultado s (segredo).
  3. Bob fará o mesmo, mas com o valor calculado de Alice (UMA) e seu número secreto (b)

Nesse ponto, eles geraram com sucesso um segredo comum (s), mesmo que seja difícil de ver no momento. Vamos explorar isso em mais detalhes em um segundo.

Em código:

// Alice calculate the common secretconst secretOfAlice = Math.pow(B, a)%p;console.log("Alice's calculated secret:", secretOfAlice);// Alice's calculated secret: 18// Bob will calculateconst secretOfBob = Math.pow(A, b)%p;console.log("Bob's calculated secret:", secretOfBob);// Bob's calculated secret: 18
Cálculo de segredo comum

Como você pode ver, Alice e Bob obtiveram o número 18, que eles podem usar como chave para criptografar mensagens. Parece mágico neste momento, mas é apenas um pouco de matemática.

Vamos ver por que eles obtiveram o mesmo número dividindo os cálculos em partes elementares:

Screenshot 2020 05 09 at 12.11.18
O processo como uma equação

Na última etapa, usamos um identidade aritmética do módulo e suas propriedades distributivas para simplificar instruções de módulo aninhadas.

Então, Alice e Bob têm a mesma chave, mas vamos ver o que Charlie viu disso tudo. Nós sabemos isso p e g são números públicos, disponíveis para todos.

Também sabemos que Alice e Bob enviaram seus valores calculados (UMA, B) através da rede, para que também possa ser capturado por Charlie.

Screenshot 2020 05 09 at 20.12.35
Perspectiva de Charlie

Charlie conhece quase todos os parâmetros dessa equação, apenas uma e b permaneça escondido. Para ficar com o exemplo, se ele sabe disso UMA é 4 e p é 23, g ao poder de uma pode ser 4, 27, 50, 73, … e infinitos outros números que resultam em 4 no espaço do módulo.

Ele também sabe que apenas o subconjunto desses números são opções possíveis, porque nem todos os números são um expoente de 5 (g), mas ainda é um número infinito de opções para tentar.

Isso não parece muito seguro com números pequenos. Mas no começo eu disse que p é um número realmente grande, geralmente com 2000 ou 4000 bits de comprimento. Isso torna quase impossível adivinhar o valor de uma ou b no mundo real.

A chave comum que Alice e Bob possuem apenas pode ser gerada sabendo uma ou b, além das informações que percorreram a rede.

Se você é mais visual, aqui está um ótimo diagrama que mostra todo esse processo misturando baldes de tinta em vez de números.

Diffie
fonte: Wikipedia

Aqui p e g constantes compartilhadas representadas pela “tinta comum” amarela. Números secretos de Alice e Bob (uma, b) é “cores secretas” e “segredo comum” é o que chamamos s.

Essa é uma ótima analogia porque representa a irreversibilidade da operação do módulo. Como as tintas mistas não podem ser desmembradas de seus componentes originais, o resultado de uma operação de módulo não pode ser revertido.

Sumário

Agora, o problema original pode ser resolvido criptografando as mensagens usando uma chave compartilhada, que foi trocada com o algoritmo Diffie-Hellman.

Com isso, Alice e Bob podem se comunicar com segurança, e Charlie não pode ler suas mensagens, mesmo que ele faça parte da mesma rede.

Obrigado por ler até aqui! Espero que você tenha valorizado este post e tenha entendido algumas partes desse interessante fluxo de comunicação.

Se foi difícil seguir a matemática desta explicação, aqui é um ótimo vídeo para ajudar você a entender o algoritmo sem matemática, de um nível superior.

Se você gostou deste post, pode me seguir no Twitter para encontrar alguns recursos mais interessantes sobre programação e desenvolvimento de software.





Fonte