Criptografia assimétrica (ou de chave pública) é a base prática para três necessidades recorrentes em sistemas modernos: (1) trocar chaves com segurança em canais inseguros, (2) assinar dados para garantir autoria e integridade verificável, e (3) estabelecer identidade de forma escalável por meio de certificados e infraestrutura de chaves públicas (PKI). Diferente do que acontece com chaves simétricas, aqui cada entidade possui um par de chaves matematicamente relacionadas: uma chave privada (mantida em segredo) e uma chave pública (distribuída). O ponto central é que operações feitas com uma chave podem ser verificadas ou revertidas (dependendo do esquema) com a outra, sem que a chave privada precise ser compartilhada.
1) Conceito e propriedades práticas
Na prática, você usa criptografia assimétrica para resolver o “problema de distribuição de chaves”: como duas partes que nunca se encontraram podem estabelecer um segredo compartilhado sem já ter um segredo prévio? A resposta usual é: elas não trocam diretamente o segredo; em vez disso, usam um mecanismo assimétrico para chegar a um segredo compartilhado (troca de chaves) ou para proteger uma chave simétrica recém-gerada (encapsulamento/criptografia de chave). Em seguida, usam criptografia simétrica para o tráfego de dados, porque é muito mais eficiente.
Além disso, a assimetria permite assinaturas digitais: um emissor usa sua chave privada para produzir uma assinatura sobre uma mensagem; qualquer verificador, com a chave pública correspondente, valida a assinatura. Isso cria um vínculo verificável entre identidade (quem controla a chave privada) e ações (o que foi assinado).
1.1 O que a chave pública realmente garante (e o que não garante)
Ter uma chave pública de alguém não significa automaticamente que você está falando com essa pessoa. Significa apenas que você tem um valor público que, se for realmente dela, permitirá verificar assinaturas ou estabelecer segredos com ela. O problema de “ser realmente dela” é o problema de identidade: como associar uma chave pública a uma entidade (pessoa, serviço, organização) de modo confiável? É aí que entram certificados, autoridades certificadoras (CAs), pinagem (pinning) e outros mecanismos de distribuição de chaves.
2) Troca de chaves: estabelecendo um segredo compartilhado
Existem duas famílias comuns de abordagem para chegar a um segredo compartilhado usando assimetria:
Continue em nosso aplicativo
Você poderá ouvir o audiobook com a tela desligada, ganhar gratuitamente o certificado deste curso e ainda ter acesso a outros 5.000 cursos online gratuitos.
ou continue lendo abaixo...Baixar o aplicativo
DH/ECDH (Diffie-Hellman e variantes elípticas): ambas as partes contribuem com material secreto e chegam ao mesmo segredo compartilhado. É o padrão moderno em protocolos como TLS.
Encapsulamento/criptografia de chave (ex.: RSA-OAEP ou KEMs): uma parte gera um segredo e o protege para a outra usando a chave pública do destinatário. Em designs modernos, isso aparece como KEM (Key Encapsulation Mechanism), inclusive em criptografia pós-quântica.
2.1 ECDH na prática (visão operacional)
No ECDH, cada lado gera um par de chaves efêmero (para aquela sessão) ou estático (de longo prazo). O segredo compartilhado é derivado combinando a chave privada de um lado com a chave pública do outro. O resultado bruto do ECDH não deve ser usado diretamente como chave de criptografia; ele deve passar por uma função de derivação de chaves (KDF) para produzir chaves com tamanho e propriedades adequadas e, geralmente, múltiplas chaves (por exemplo, uma para cifrar e outra para autenticar, ou chaves separadas por direção).
Na maioria dos sistemas, você quer chaves efêmeras (ECDHE) para obter sigilo futuro (forward secrecy): mesmo que uma chave privada de longo prazo vaze no futuro, sessões passadas permanecem protegidas porque usaram chaves efêmeras descartadas.
2.2 Passo a passo prático: troca de chaves ECDHE com autenticação por certificado
O cenário típico: um cliente quer falar com um servidor e precisa (a) estabelecer chaves de sessão e (b) ter certeza de que o servidor é quem diz ser. Um fluxo conceitual (simplificado) é:
Passo 1 — Cliente cria chave efêmera: o cliente gera um par ECDH efêmero (privC, pubC).
Passo 2 — Cliente envia pubC: o cliente envia pubC ao servidor, junto com parâmetros de negociação (curva, etc.).
Passo 3 — Servidor cria chave efêmera: o servidor gera (privS, pubS) efêmero.
Passo 4 — Servidor envia pubS + certificado + prova: o servidor envia pubS e seu certificado (contendo a chave pública de assinatura do servidor) e assina um transcript do handshake (incluindo pubC e pubS). Essa assinatura prova que quem enviou pubS controla a chave privada associada ao certificado.
Passo 5 — Cliente valida identidade: o cliente valida a cadeia do certificado (CA confiável, validade, nome/SAN, revogação conforme política) e verifica a assinatura do handshake.
Passo 6 — Ambos derivam o segredo compartilhado: cliente calcula ECDH(privC, pubS); servidor calcula ECDH(privS, pubC). Ambos obtêm o mesmo valor.
Passo 7 — KDF e chaves de sessão: ambos aplicam uma KDF ao segredo ECDH e ao transcript para derivar chaves de sessão. A inclusão do transcript na derivação ajuda a “amarrar” as chaves aos parâmetros negociados e reduzir riscos de downgrade/alteração.
Passo 8 — Confirmação de chaves: as partes trocam mensagens autenticadas (por exemplo, “Finished”) para confirmar que derivaram as mesmas chaves e que o handshake não foi adulterado.
Esse passo a passo descreve o que você precisa garantir ao implementar ou avaliar um protocolo: chaves efêmeras, autenticação do servidor (e opcionalmente do cliente), derivação correta via KDF e confirmação de chaves.
2.3 Erros comuns em troca de chaves (e como evitar)
Usar segredo ECDH bruto como chave: sempre use KDF (por exemplo, HKDF) com salt/contexto.
Não validar chaves públicas recebidas: em algumas curvas e bibliotecas, é necessário validar que a chave pública está no grupo correto para evitar ataques de subgrupo/invalid curve. Prefira APIs de alto nível que façam validação automaticamente.
Reutilizar chave efêmera: reutilização pode quebrar sigilo futuro e, em alguns cenários, expor segredos. Gere efêmeras por sessão.
Não autenticar o handshake: ECDH sem autenticação é vulnerável a ataque man-in-the-middle. Autentique com certificado, chave pré-compartilhada (PSK) ou assinatura.
3) Assinatura digital: integridade, autoria e não repúdio operacional
Assinatura digital é um mecanismo criptográfico que permite que qualquer pessoa verifique que um conteúdo foi assinado por quem controla uma chave privada específica e que o conteúdo não foi alterado desde a assinatura. Na prática, isso é usado para:
Assinar artefatos: pacotes, binários, imagens de container, scripts, documentos.
Assinar transações e comandos: aprovações, ordens de pagamento, mudanças de configuração.
Autenticar protocolos: assinar partes do handshake (como no exemplo de ECDHE autenticado).
Assinatura não é criptografia: ela não esconde o conteúdo. Ela cria uma prova verificável de integridade e vínculo com a chave privada.
3.1 Como uma assinatura funciona (modelo mental)
Em geral, você não assina a mensagem inteira diretamente; você assina um hash da mensagem (digest). Isso torna a operação eficiente e padroniza o tamanho da entrada. O verificador recalcula o hash e verifica a assinatura contra esse hash.
Algoritmos comuns incluem Ed25519 (EdDSA) e ECDSA (em curvas como P-256). Em muitos ambientes modernos, Ed25519 é preferido por simplicidade e robustez, enquanto ECDSA é amplamente suportado em ecossistemas legados e em TLS com certas configurações.
3.2 Passo a passo prático: assinando e verificando um documento
Suponha que você precise assinar um arquivo de configuração crítico que será aplicado em produção, e quer que o sistema valide a assinatura antes de aceitar o arquivo.
Passo 1 — Gere um par de chaves de assinatura: crie uma chave privada de assinatura e extraia a chave pública correspondente. Armazene a privada em local protegido (idealmente HSM/KMS ou, no mínimo, com criptografia e controle de acesso).
Passo 2 — Defina o formato do que será assinado: escolha uma serialização canônica. Exemplo: se for JSON, use uma forma canônica (ordem de chaves, sem espaços variáveis) para evitar que mudanças irrelevantes quebrem a verificação.
Passo 3 — Calcule o hash do conteúdo canônico: use um hash moderno (ex.: SHA-256). O resultado é o digest.
Passo 4 — Assine o digest: use a chave privada para gerar a assinatura. O resultado é um blob binário (geralmente codificado em base64 ao transportar).
Passo 5 — Distribua o conteúdo + assinatura + identificador de chave: o verificador precisa saber qual chave pública usar. Inclua um
key_id(por exemplo, fingerprint da chave pública) e, se aplicável, um certificado.Passo 6 — Verificação: o verificador (a) obtém a chave pública confiável correspondente ao
key_id, (b) recalcula o hash do conteúdo canônico, (c) verifica a assinatura. Se falhar, rejeita o arquivo.
Um detalhe operacional importante: a verificação só é útil se a distribuição da chave pública (ou certificado) for confiável. Se um atacante puder substituir a chave pública no verificador, ele pode assinar com a própria chave e “parecer válido”.
3.3 Cuidados críticos: nonce e determinismo
Alguns algoritmos (como ECDSA) dependem de um valor aleatório por assinatura (nonce). Se esse nonce for reutilizado ou gerado com baixa entropia, a chave privada pode ser recuperada. Por isso:
Prefira bibliotecas que implementem ECDSA com nonce determinístico (RFC 6979) ou use Ed25519, que evita essa classe de falhas por design.
Não implemente assinatura “na mão”. Use APIs consolidadas.
4) Identidade: associando chaves a entidades (PKI e certificados)
Identidade, no contexto de criptografia aplicada, é o processo de vincular uma chave pública a um nome/entidade de forma verificável. Em ambientes corporativos e na internet, isso é frequentemente feito com certificados X.509 e uma cadeia de confiança até uma autoridade certificadora (CA) que o cliente confia.
Um certificado, em termos práticos, é um objeto assinado por uma CA que declara: “a chave pública X pertence ao sujeito Y”, junto com metadados (período de validade, usos permitidos, nomes DNS/IP, etc.). O cliente valida a assinatura da CA e as regras de uso.
4.1 O que validar em um certificado (checklist operacional)
Cadeia de confiança: o certificado do servidor deve encadear até uma CA confiável no seu trust store.
Validade temporal:
notBefore/notAfterdentro do período atual (atenção a relógio do sistema).Nome do serviço: o hostname acessado deve estar no SAN (Subject Alternative Name). Evite depender de CN legado.
Key Usage / Extended Key Usage: a chave deve estar autorizada para o propósito (ex.:
serverAuth).Algoritmos e tamanhos: rejeite algoritmos obsoletos e chaves fracas conforme política (ex.: SHA-1, RSA muito pequeno).
Revogação (conforme risco): CRL/OCSP/OCSP stapling. Em muitos ambientes, a política é “soft-fail” por disponibilidade; em outros, “hard-fail” por segurança.
4.2 Passo a passo prático: emissão e uso de certificado para um serviço interno
Para um serviço interno (por exemplo, api.intra.exemplo), um fluxo típico com uma CA interna é:
Passo 1 — Gere a chave privada no local correto: idealmente no host do serviço ou em um módulo de segurança (HSM/KMS) que permita operação de assinatura sem exportar a chave.
Passo 2 — Crie um CSR (Certificate Signing Request): inclua o SAN com o DNS do serviço e, se necessário, IPs. Defina o algoritmo de chave (ex.: ECDSA P-256 ou Ed25519, conforme suporte do seu ecossistema).
Passo 3 — Validação pela CA: a CA verifica que você controla o nome (processo interno: aprovação, automação via ACME interno, ticket, etc.).
Passo 4 — Emissão do certificado: a CA assina o certificado com validade curta (boa prática operacional) e define EKU apropriado.
Passo 5 — Instalação no serviço: configure o servidor para apresentar o certificado e a cadeia intermediária correta. Garanta permissões restritas no arquivo da chave privada.
Passo 6 — Configuração de clientes: distribua o certificado raiz/intermediário da CA interna para o trust store dos clientes (ou use pinning controlado).
Passo 7 — Rotação: automatize renovação antes do vencimento e revogação/remoção em caso de comprometimento.
4.3 Pinning e trust stores: quando usar
Trust store (lista de CAs confiáveis) é o padrão para escalabilidade: você confia em CAs e aceita certificados emitidos por elas. Pinning é quando você fixa uma chave pública (ou hash) esperada para um serviço específico. Pinning reduz a superfície de ataque contra CAs, mas aumenta o risco operacional: se você precisar trocar a chave/certificado e esquecer de atualizar o pin, você derruba o acesso.
Uso típico de pinning: aplicativos controlados (mobile/desktop) falando com um backend específico, onde você consegue atualizar o aplicativo e gerenciar rotação com cuidado. Em ambientes com muitos clientes heterogêneos, trust store costuma ser mais viável.
5) Escolhas de algoritmos e parâmetros (visão aplicada)
Ao escolher algoritmos assimétricos, pense em três dimensões: (1) suporte no ecossistema (bibliotecas, TLS, HSM), (2) segurança e maturidade, (3) ergonomia e risco de implementação.
Troca de chaves: ECDHE é a escolha comum. Curvas amplamente usadas incluem X25519 e P-256. X25519 é popular por simplicidade e resistência a classes de erro; P-256 é onipresente em ambientes corporativos e hardware.
Assinatura: Ed25519 é uma escolha moderna e simples quando suportada; ECDSA P-256 é amplamente compatível; RSA ainda aparece, mas tende a ser mais pesado e sujeito a escolhas de padding/parametrização.
Certificados: X.509 é o padrão de interoperabilidade. A escolha do algoritmo de chave do certificado (RSA/ECDSA/EdDSA) deve considerar compatibilidade com clientes.
Evite “criptografia assimétrica para dados grandes”. O padrão é: assimetria para autenticar e estabelecer segredos; simetria para trafegar dados.
6) Padrões de uso em sistemas: exemplos práticos
6.1 API com mTLS (autenticação mútua)
Em mTLS, tanto servidor quanto cliente apresentam certificados. Isso resolve autenticação forte de serviço-a-serviço e reduz dependência de tokens em alguns cenários. Um desenho prático:
Uma CA interna emite certificados para workloads (serviços).
O servidor valida o certificado do cliente (cadeia, EKU
clientAuth, identidade no SAN/URI).O cliente valida o certificado do servidor (cadeia,
serverAuth, hostname).Autorização é feita mapeando identidade do certificado (ex.: SPIFFE ID, DNS, OU) para permissões.
Pontos de atenção: rotação automática, revogação/expiração curta e proteção das chaves privadas nos nós.
6.2 Assinatura de artefatos no pipeline
Para reduzir risco de supply chain, assine artefatos no momento de build/release e verifique antes de deploy:
O sistema de CI possui acesso controlado a uma chave de assinatura (idealmente em KMS/HSM).
Ao gerar um artefato, calcula-se o digest e assina-se.
O ambiente de deploy possui a chave pública (ou certificado) para verificação.
Política: “sem assinatura válida, não implanta”.
Esse padrão depende menos de confidencialidade e mais de integridade e identidade do produtor do artefato.
7) Armazenamento e ciclo de vida de chaves privadas
Em criptografia assimétrica, a chave privada é o ativo crítico. Se ela vazar, um atacante pode se passar pela entidade (assinando ou autenticando) e, dependendo do protocolo, pode comprometer sessões futuras. Boas práticas aplicadas:
Geração segura: use geradores de números aleatórios do sistema e bibliotecas confiáveis. Evite gerar chaves em ambientes com entropia insuficiente.
Isolamento: prefira HSM/KMS/TPM quando o impacto do vazamento é alto. Caso use arquivo, proteja com permissões mínimas e criptografia em repouso.
Rotação: defina validade curta para certificados e processos de rotação. Para chaves de assinatura de release, planeje rotação com múltiplas chaves confiáveis durante transição.
Separação de funções: chaves diferentes para propósitos diferentes (ex.: uma para TLS, outra para assinar artefatos). Evite reutilizar a mesma chave para múltiplos usos.
Auditoria: registre operações de assinatura/uso de chaves em KMS/HSM e monitore anomalias.
8) Exemplos de mensagens e estruturas (para evitar ambiguidades)
Ao assinar ou autenticar, ambiguidade de formato é uma fonte comum de falhas. Um exemplo simples de envelope de assinatura para um payload JSON:
{ "payload": { "env": "prod", "feature": "x", "enabled": true }, "payload_canonical": "{\"enabled\":true,\"env\":\"prod\",\"feature\":\"x\"}", "hash_alg": "SHA-256", "sig_alg": "Ed25519", "key_id": "sha256:...fingerprint...", "signature_b64": "..."}O campo payload_canonical deixa explícito o que foi assinado. Em sistemas reais, você pode omitir isso e padronizar a canonicalização, mas precisa garantir que produtor e verificador implementem a mesma regra.
Para troca de chaves autenticada, o “transcript” do handshake (o que é assinado e/ou entra na KDF) deve ser definido com precisão. Em vez de concatenar strings de forma ad-hoc, use uma codificação estruturada (ex.: TLV, CBOR) e inclua identificadores de contexto para evitar ataques de confusão entre protocolos.