Assinaturas e certificados
A lição anterior deixou um buraco: Diffie-Hellman protege contra quem escuta, mas não contra quem se coloca no meio. Cifrar sem saber com quem se fala é trancar a porta sem olhar quem está dentro. Esta lição fecha esse buraco com duas ideias — assinar e atestar — e explica por que aquele cadeado no navegador promete menos do que a maioria das pessoas imagina.
Um selo que qualquer um confere e ninguém falsifica
Um selo de cera real cumpria duas funções ao mesmo tempo: só o rei tinha o anel que o produzia, e qualquer súdito reconhecia o desenho. Além disso, se alguém abrisse a carta, o selo quebrava. A assinatura digital faz as três coisas — autoria, verificação pública e detecção de adulteração — com uma vantagem decisiva: ela depende do conteúdo. Mudar uma vírgula invalida a assinatura.
Mas o selo só funciona porque o súdito já sabe qual é o desenho do anel do rei. Na internet você não conhece a chave pública de nenhum site de antemão. É por isso que a assinatura sozinha não basta: um impostor também assina, só que com a chave dele. Falta responder de quem é esta chave — e a resposta é uma cadeia de atestados que termina em alguém que você já confiava antes de a conexão existir.
Assinar, adulterar, e a cadeia quebrando
Na primeira aba, edite a mensagem depois de assinada e veja a verificação falhar imediatamente. Na segunda, percorra a cadeia de certificados e provoque cada tipo de erro que o navegador reporta — autoassinado, expirado, nome errado, CA desconhecida.
Uma assinatura digital é a criptografia de chave pública ao contrário: assina-se com a chave privada e qualquer um verifica com a pública. Isso não esconde nada — prova autoria e integridade.
assinatura = hashd mod n = 123103 mod 143 = 85
assinaturae mod n = 857 mod 143 = 123
Como assinar
# Assinatura digital: a chave pública ao contrário. # # CIFRAR: chave PÚBLICA fecha → chave PRIVADA abre # ASSINAR: chave PRIVADA assina → chave PÚBLICA verifica # # Assinar não esconde nada. Prova AUTORIA e INTEGRIDADE. # Assina-se o HASH, não o documento — por dois motivos: # 1. o documento pode ter gigabytes; o hash tem 32 bytes # 2. operações assimétricas só funcionam em blocos pequenos assinatura = assinar(chave_privada, sha256(documento)) # Verificar: recalcule o hash e confira contra a assinatura valida = verificar(chave_publica, sha256(documento), assinatura) # ⚠ Consequência direta de assinar o hash: a segurança da # assinatura NÃO PASSA da segurança da função hash. Se alguém # consegue produzir dois documentos com o mesmo hash, pode obter # sua assinatura num e colá-la no outro. Foi por isso que colisões # em MD5 e SHA-1 aposentaram esses algoritmos das assinaturas. from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey priv = Ed25519PrivateKey.generate() pub = priv.public_key() sig = priv.sign(b"transferir R$ 100") pub.verify(sig, b"transferir R$ 100") # exceção se não bater
HMAC ou assinatura?
# MAC ou ASSINATURA? A pergunta é: quem precisa verificar? # # HMAC — chave COMPARTILHADA # . rápido (só hash), chaves curtas # . os dois lados têm a mesma chave # . logo, cada lado poderia ter forjado a etiqueta do outro # . → não serve como prova perante terceiros tag = hmac.new(chave_compartilhada, mensagem, hashlib.sha256).digest() # ASSINATURA — par de chaves # . mais lenta, chaves maiores # . só o dono da privada pode gerar; o mundo todo verifica # . → NÃO-REPÚDIO: o autor não pode negar depois sig = chave_privada.sign(mensagem) # Use HMAC entre partes que já confiam uma na outra e já # compartilham um segredo: webhooks, cookies de sessão, tokens # internos. Use assinatura quando qualquer um precisa poder # verificar sem receber um segredo: certificados, atualizações # de software, documentos jurídicos, commits assinados. # ⚠ Compare tags em TEMPO CONSTANTE. Uma comparação comum para # no primeiro byte diferente, e essa diferença de microssegundos # permite ao atacante descobrir a tag byte a byte. hmac.compare_digest(tag_recebida, tag_esperada)
Certificados X.509
# O problema que sobrou: como saber que ESTA chave pública é do # meu banco, e não de um impostor? Assinatura não resolve sozinha — # o impostor também sabe assinar, com a chave DELE. # # Resposta: alguém em quem você JÁ confia atesta a chave. # Um certificado é isso: uma declaração assinada. # Conteúdo de um certificado X.509: # Subject: CN=exemplo.com.br ← de quem é # SAN: exemplo.com.br, www... ← domínios cobertos # Public Key: (a chave pública do site) # Issuer: CN=GlobalTrust TLS CA G3 ← quem atesta # Validade: 2026-05-01 a 2026-07-30 # Assinatura: (do issuer, sobre tudo acima) # A CADEIA DE CONFIANÇA: # certificado do site ← assinado pela CA intermediária # CA intermediária ← assinada pela CA raiz # CA raiz ← autoassinada, JÁ INSTALADA na sua máquina # # A confiança termina (e começa) nas ~150 raízes que vieram com o # seu sistema operacional e o seu navegador. Toda a segurança da # web repousa sobre esse conjunto — e sobre a premissa de que # nenhuma delas emitirá um certificado indevido. # Inspecionando na prática: openssl s_client -connect exemplo.com.br:443 -showcerts openssl x509 -in cert.pem -text -noout
O que o navegador realmente verifica
# O que o navegador confere, em ordem, antes de mostrar o cadeado: # # 1. a assinatura de cada certificado bate com a chave pública # do certificado acima na cadeia? # 2. a cadeia termina numa raiz que eu já tenho instalada? # 3. a data de hoje está dentro da validade? # 4. o domínio que pedi está na lista de nomes do certificado? # 5. o certificado foi revogado? (OCSP / CRL — na prática, frágil) # 6. ele aparece nos logs públicos de Certificate Transparency? # # Repare: NENHUMA dessas checagens, exceto a revogação, precisa de # rede. A raiz já estava na máquina antes de a conexão existir. # Os três níveis de validação, e o que eles realmente significam: # DV (Domain Validation) — provou controlar o domínio. # É o que o Let's Encrypt emite, # de graça e automaticamente. # OV / EV (Organization/Extended) — a CA verificou documentos # da empresa. Os navegadores # pararam de exibir a barra verde: # estudos mostraram que ninguém # reparava, e ela dava falsa segurança. # # ⚠ O cadeado NÃO significa "site confiável". Significa # "a conexão é cifrada e o domínio confere". Um site de phishing # em banco-do-brasi1.com tem cadeado — e é um domínio legítimo, # que ele de fato controla. O cadeado nunca prometeu honestidade. # CERTIFICATE TRANSPARENCY: como se detecta emissão indevida. # Toda CA precisa publicar cada certificado emitido num log público # e append-only (uma árvore de Merkle, feita de hashes). Assim o # dono de um domínio pode monitorar e descobrir se alguém emitiu # um certificado para o site dele. Foi assim que se pegou a # Symantec emitindo certificados de teste para domínios do Google.
Experimentando
Mini projeto: inspecione certificados de verdade. Rode
openssl s_client -connect site:443 -showcerts para três sites diferentes e monte a
cadeia de cada um: quem assinou quem, até qual raiz. Compare as validades — você vai notar que hoje
quase todos duram 90 dias. Depois olhe a sua própria loja de raízes confiáveis e conte quantas
autoridades, de quantos países, você está confiando sem nunca ter decidido isso.
Projeto principal: monte sua própria mini-PKI com OpenSSL. Crie uma CA raiz
autoassinada, uma CA intermediária assinada pela raiz, e um certificado de servidor assinado pela
intermediária. Suba um servidor HTTPS local com ele. Primeiro acesse sem instalar nada e veja o erro
ERR_CERT_AUTHORITY_INVALID; depois instale sua raiz no sistema e veja o cadeado
aparecer. Você acabou de executar, em miniatura, exatamente o que faz um proxy corporativo que
inspeciona TLS — e de entender por que ele consegue.
Desafio extra: implemente uma árvore de Merkle e use-a como log append-only. Cada
folha é o hash de uma entrada; cada nó interno é o hash dos dois filhos; a raiz resume tudo. Implemente
a prova de inclusão: dado um item, devolva os poucos hashes (log n deles) que permitem a
terceiros verificar que ele está no log, sem baixar o log inteiro. É exatamente o mecanismo do
Certificate Transparency — e também o de blockchains e do git.
Teste sua intuição
Onde você encontra isso
Assinatura de código
Todo aplicativo nas lojas da Apple e do Google é assinado, e o sistema recusa executar binários cuja assinatura não confere. Atualizações do Windows, pacotes do apt e imagens de container seguem o mesmo modelo. É a defesa central contra ataques à cadeia de suprimentos — e por isso a chave privada de assinatura de uma empresa é um dos ativos mais protegidos que ela tem, geralmente guardada num HSM que nunca a revela.
Let's Encrypt e a web cifrada por padrão
Em 2014, certificados custavam caro e exigiam processo manual; menos de 30% do tráfego web era HTTPS. O Let's Encrypt tornou a emissão gratuita e totalmente automática pelo protocolo ACME — seu servidor prova controlar o domínio respondendo a um desafio, e recebe o certificado em segundos. Hoje mais de 95% do tráfego é cifrado. É um dos casos mais claros de como remover atrito muda o comportamento de uma indústria inteira.
Quando uma CA falha
Em 2011 a DigiNotar, uma autoridade holandesa, foi invadida e emitiu certificados fraudulentos para domínios do Google, usados para interceptar o Gmail de usuários iranianos. A resposta foi remover a DigiNotar de todos os navegadores do mundo — e a empresa faliu em semanas. O episódio motivou diretamente a criação do Certificate Transparency, para que emissões indevidas passassem a ser detectáveis em vez de invisíveis.