Uma vez tive que explicar para um colega, no meio de uma revisão de código, por que dois protocolos completamente diferentes — Diffie-Hellman e RSA — resolviam o mesmo problema (segredo compartilhado num canal inseguro) usando a mesma operação matemática por baixo dos panos. Ele sabia usar as bibliotecas. Não sabia o que elas faziam. E isso é comum: dá para trabalhar anos com TLS, HTTPS, SSH, sem nunca ter rodado a conta na mão.
Este artigo é essa conta na mão. Vamos ver como Diffie-Hellman e RSA realmente usam exponenciação modular, com números pequenos o suficiente para você acompanhar — e, no caso do RSA, conferir no seu próprio Python em trinta segundos.
Se você ainda não tem clareza sobre o que é exponenciação modular em si, vale ler antes “Exponenciação Modular: Fundamentos, Aplicações e Desafios de Segurança em Hardware” — aqui eu assumo que esse conceito básico já está redondo.
Diffie-Hellman: combinar uma chave sem nunca falar ela em voz alta
O problema que Diffie-Hellman resolve é este: Alice e Bob precisam concordar numa chave secreta, mas só têm um canal público — qualquer coisa que trafegar ali, um espião (a “Eve” clássica dos livros-texto) também vê.
A solução, em três passos:
1. Cada um escolhe um segredo próprio. Alice escolhe XA, Bob escolhe XB. Nenhum dos dois compartilha esse valor com ninguém.
2. Cada um calcula um valor público e envia para o outro.
- Alice calcula YA = aXA mod q e manda YA para Bob.
- Bob calcula YB = aXB mod q e manda YB para Alice.
3. Cada um usa o valor recebido para chegar na mesma chave.
- Alice calcula K = YBXA mod q.
- Bob calcula K = YAXB mod q.
Os dois caminhos chegam no mesmo K — isso não é coincidência, é a propriedade da própria exponenciação modular (elevar a XA e depois a XB dá o mesmo resultado que elevar a XB e depois a XA). O ponto de segurança é que quem intercepta a conversa só vê YA e YB — sem XA ou XB, reconstruir K exige resolver o logaritmo discreto, o que é inviável para os tamanhos de chave usados na prática.
A vantagem prática além da segurança: a conta em si é rápida o suficiente para rodar até em dispositivos com processamento limitado — o que é relevante se você trabalha com embarcados, IoT ou qualquer coisa que não tenha um servidor de sobra.
RSA: chaves diferentes para cifrar e decifrar
RSA resolve um problema um pouco diferente: em vez de combinar uma chave simétrica, cada usuário tem um par de chaves — uma pública, uma privada — e o que uma cifra, só a outra decifra.
Geração das chaves
- Escolha dois números primos, p e q, e calcule n = p × q.
- Calcule φ(n) = (p − 1) × (q − 1).
- Escolha e, relativamente primo a φ(n) — isso vira parte da chave pública.
- Determine d tal que e × d ≡ 1 (mod φ(n)) — isso vira a chave privada.
Cifrar e decifrar
- Para enviar a mensagem P, quem cifra usa a chave pública: C = Pe mod n.
- Quem recebe usa a chave privada para reverter: P = Cd mod n.
O motivo de isso funcionar não é mágica — é consequência direta de e × d ≡ 1 (mod φ(n)), garantida pela construção das chaves. Cifrar e decifrar são, matematicamente, a mesma operação (exponenciação modular) aplicada duas vezes com expoentes que se cancelam.
Um exemplo que você pode rodar agora
Vamos usar números pequenos — nada perto do tamanho real usado em produção (2048 bits ou mais), mas suficiente para ver a conta funcionando:
- p = 11, q = 17 → n = 187
- φ(n) = 10 × 16 = 160
- e = 7 (relativamente primo a 160)
- d = 23, porque 7 × 23 mod 160 = 1
Para cifrar a mensagem P = 88:
C = 88⁷ mod 187 = 11
Para decifrar, usando a chave privada:
P = 11²³ mod 187 = 88
Voltou o valor original. Se você tiver um Python à mão, confere em uma linha:
>>> pow(88, 7, 187)
11
>>> pow(11, 23, 187)
88
A função pow de três argumentos do Python já faz exponenciação modular eficiente internamente — é o mesmo princípio que RSA de verdade usa, só que com números de centenas de dígitos em vez de três.
Por que isso é relevante além do exercício de matemática
Com chaves de 1024, 2048 bits ou mais, a eficiência da exponenciação modular deixa de ser luxo e vira requisito: sem um algoritmo rápido por trás (square-and-multiply, Montgomery, ou uma combinação dos dois), operações de handshake TLS ou assinatura digital ficariam lentas demais para uso real. É por isso que esse tema aparece tanto em segurança de software quanto em segurança de hardware — a mesma conta que garante a confidencialidade também precisa rodar rápido o bastante para não travar o produto.
Vale reforçar: os exemplos aqui usam números pequenos de propósito, só para você acompanhar a conta na mão. Segurança real depende de escolher primos grandes o suficiente (e gerados corretamente) para que fatorar n seja inviável — isso é assunto para outro artigo, mas não deixe a simplicidade do exemplo te enganar sobre o tamanho das chaves usadas de verdade.
Próximo passo
Se você quer entender como essa conta roda rápido o suficiente para produção — e onde ela pode vazar informação se você não tomar cuidado — os próximos artigos da série cobrem isso direto: “Exponenciação Modular Rápida e Segura: Square-and-Multiply na Prática” entra no algoritmo e no código; “Redução de Montgomery: Otimizando a Multiplicação Modular em Hardware” e “Exponenciação Modular Randomizada: Como Blindar RSA Contra Ataques de Canal Lateral” tratam de otimização e blindagem contra side-channel, respectivamente. Comenta aqui embaixo se você já implementou RSA ou DH na mão alguma vez — e se rodou em cima de hardware com restrição de recursos, ainda melhor: quero saber o que você encontrou pela frente.



