ECDSA vs EdDSA normalmente quer dizer ECDSA na P-256 versus EdDSA no Ed25519: os dois esquemas de assinatura que cobrem quase todas as implantações modernas de curvas elípticas. Os dois são igualmente fortes e igualmente compactos, então o que decide a escolha é a segurança da implementação, de um lado, e o suporte do ecossistema, do outro.
Visão geral
| ECDSA (P-256) | EdDSA (Ed25519) | |
|---|---|---|
| Norma | FIPS 186-5 §6, SEC 1, ANSI X9.62 | RFC 8032, FIPS 186-5 §7 (aprovado desde 2023) |
| Forma da curva | Weierstrass curta, ordem prima (cofator 1) | Edwards torcida, cofator 8 |
| Segurança | cerca de 128 bits | cerca de 128 bits |
| Chave privada | escalar de 32 bytes | semente de 32 bytes |
| Chave pública | 65 bytes sem compressão, 33 com compressão, 91 em SPKI DER | 32 bytes, 44 em SPKI DER |
| Assinatura | 64 bytes em r‖s bruto, 70–72 bytes em DER | 64 bytes R‖S, uma única codificação |
| Nonce | Aleatório a cada assinatura, ou determinístico pela RFC 6979 | Derivado da chave e da mensagem por construção |
| Maleável | Sim: (r, n − s) também passa na verificação | Não, se o verificador conferir que S é menor que a ordem do grupo |
| Assinaturas / verificações por segundo, OpenSSL 3.6.5 | cerca de 87.000 / 29.000 | cerca de 60.000 / 25.000 |
| Assinaturas / verificações por segundo, @noble/curves 2.3 | cerca de 3.800 / 870 | cerca de 3.100 / 1.280 |
| JOSE / COSE | ES256 / −7 | Ed25519 (RFC 9864) / −19, o antigo EdDSA / −8 |
| Esquema no TLS 1.3 | ecdsa_secp256r1_sha256 (0x0403) | ed25519 (0x0807) |
| Certificados TLS de confiança pública | Sim | Não (os Baseline Requirements só permitem RSA e P-256/384/521) |
As velocidades foram medidas em um núcleo de um Apple M4 Max com o OpenSSL 3.6.5 (openssl speed) e, na linha de JavaScript puro, com a @noble/curves 2.3.0 no Node.js 26.10.
Diferenças de projeto
Os dois são assinaturas de curva elíptica baseadas no logaritmo discreto, mas foram projetados com cerca de vinte anos de diferença (o ECDSA em 1992 e o EdDSA em 2011), e isso se nota.
O nonce
Uma assinatura ECDSA consome um nonce k secreto, próprio de cada assinatura. Se k se repete em duas mensagens, ou apenas tem um viés de alguns bits ao longo de muitas assinaturas, a chave privada pode ser calculada; foi assim que a chave de assinatura do PlayStation 3 vazou e que muitas carteiras de criptomoedas foram esvaziadas. O FIPS 186-5 permite tanto um k aleatório vindo de um gerador aprovado quanto a derivação determinística da RFC 6979, e a maioria das bibliotecas modernas usa uma dessas duas opções por padrão, mas o modo de falha faz parte do próprio esquema.
O EdDSA elimina esse modo de falha: o nonce é o hash de uma metade secreta da chave e da mensagem (RFC 8032 §5.1.6). Assinar a mesma mensagem duas vezes produz a mesma assinatura, e mensagens diferentes sempre recebem nonces diferentes, sem nenhum gerador de números aleatórios envolvido. O preço são os ataques por injeção de falhas: uma falha provocada enquanto a mesma mensagem é assinada duas vezes pode vazar a chave, e é por isso que algumas carteiras de hardware e a norma pós-quântica ML-DSA preferem a assinatura hedged, que também mistura aleatoriedade nova.
Codificação e maleabilidade
O ECDSA tem duas codificações de assinatura: r‖s bruto (JOSE, WebCrypto, COSE, PKCS #11) e uma SEQUENCE ASN.1 DER (X.509, TLS, OpenSSL, Java, asserções WebAuthn). Confundir as duas é a causa mais comum de erros “invalid signature”, e o guia sobre DER e formato bruto trata disso em detalhes. O ECDSA também é maleável: qualquer pessoa pode transformar (r, s) na assinatura (r, n − s), igualmente válida, e é por isso que o Bitcoin e o Ethereum exigem low-S.
O Ed25519 tem uma única codificação de 64 bytes, e a RFC 8032 §5.1.7 exige que S seja menor que a ordem do grupo, o que elimina a maleabilidade óbvia.
Casos-limite da verificação
A verificação ECDSA é bem definida: confira se r e s estão no intervalo 1…n−1, calcule u₁·G + u₂·Q e compare a coordenada x do resultado com r. Pular a verificação de intervalo é fatal: o Java, das versões 15 a 18, aceitava uma assinatura toda em zeros para qualquer mensagem (CVE-2022-21449).
A verificação EdDSA tem um problema mais sutil. Como a curva Edwards25519 tem cofator 8, a RFC 8032 permite tanto uma verificação com cofator, [8][S]B = [8]R + [8][k]A, quanto a verificação sem cofator, [S]B = R + [k]A, e as bibliotecas também divergem quanto a pontos de ordem pequena e a codificações fora da forma canônica. Para assinaturas geradas honestamente, os resultados coincidem; para entradas maliciosas, não. Sistemas em que muitas partes precisam concordar sobre a validade, como as blockchains, fixam um único conjunto de regras; o ZIP 215 da Zcash é a escolha usual.
Onde cada um tem suporte
O ECDSA P-256 é o mínimo denominador comum do hardware e da plataforma web. A WebCrypto de todos os navegadores oferece suporte a ele; o Secure Enclave da Apple e a maioria dos TPMs, HSMs, cartões inteligentes e tipos de chave dos KMS na nuvem o oferecem (muitas vezes com exclusividade); as chaves de acesso o usam por padrão (COSE −7); e os Baseline Requirements do CA/Browser Forum (§6.1.5) só permitem RSA e ECDSA nas curvas P-256, P-384 e P-521 para certificados TLS de confiança pública.
O Ed25519 domina os ecossistemas definidos por software. O OpenSSH gera chaves Ed25519 por padrão desde a versão 9.5 (outubro de 2023); o Signal, o WireGuard, o Tor, o age e a maioria dos novos projetos de protocolo se baseiam nas curvas 25519 (X25519 para troca de chaves, Ed25519 para assinaturas); as chaves OpenPGP v6 têm suporte nativo a ele (RFC 9580); e a WebCrypto o aceita a partir do Firefox 129, do Safari 17 e do Chrome 137. No JOSE, a RFC 9864 substitui o identificador polimórfico EdDSA pelo Ed25519, totalmente especificado.
Em implantações com validação FIPS, os dois são aprovados pelo FIPS 186-5, embora módulos validados mais antigos possam ser anteriores ao suporte a EdDSA. A longo prazo, os dois são quebrados por um computador quântico, e o NIST IR 8547 (ainda em rascunho) propõe proibir ambos depois de 2035.
Desempenho
Reza a lenda que o Ed25519 é muito mais rápido que o ECDSA. Isso era verdade quando as implementações da P-256 eram genéricas; não é verdade no OpenSSL atual, que traz código da P-256 otimizado à mão. Em um núcleo do Apple M4 Max, o OpenSSL 3.6.5 produziu cerca de 87.000 assinaturas P-256 por segundo, contra cerca de 60.000 do Ed25519, e verificou cerca de 29.000 contra 25.000. Em JavaScript puro (@noble/curves 2.3.0), o Ed25519 verifica cerca de 50% mais rápido, enquanto a P-256 assina um pouco mais rápido. De qualquer forma, o custo é de microssegundos e raramente decide alguma coisa; o que importa é que os dois são de uma a duas ordens de grandeza mais rápidos que a assinatura RSA.
O script abaixo, executado com o Node.js 26.10, mostra as diferenças práticas em poucas linhas.
import { generateKeyPairSync, sign, verify } from "node:crypto";
const message = Buffer.from("transfer 100 to alice");
const ed = generateKeyPairSync("ed25519");
const ec = generateKeyPairSync("ec", { namedCurve: "P-256" });
// Ed25519: the algorithm argument is null because the hash is fixed (SHA-512).
const ed1 = sign(null, message, ed.privateKey);
const ed2 = sign(null, message, ed.privateKey);
// ECDSA P-256 with SHA-256, raw r||s output as used by JOSE and WebCrypto.
const ec1 = sign("sha256", message, { key: ec.privateKey, dsaEncoding: "ieee-p1363" });
const ec2 = sign("sha256", message, { key: ec.privateKey, dsaEncoding: "ieee-p1363" });
console.log("Ed25519 signature bytes:", ed1.length, "deterministic:", ed1.equals(ed2));
console.log("ECDSA P-256 signature bytes:", ec1.length, "deterministic:", ec1.equals(ec2));
console.log("Ed25519 public key (SPKI DER) bytes:", ed.publicKey.export({ type: "spki", format: "der" }).length);
console.log("P-256 public key (SPKI DER) bytes:", ec.publicKey.export({ type: "spki", format: "der" }).length);
console.log("both verify:", verify(null, message, ed.publicKey, ed1) && verify("sha256", message, { key: ec.publicKey, dsaEncoding: "ieee-p1363" }, ec1));
Ed25519 signature bytes: 64 deterministic: true
ECDSA P-256 signature bytes: 64 deterministic: false
Ed25519 public key (SPKI DER) bytes: 44
P-256 public key (SPKI DER) bytes: 91
both verify: true
O código de assinatura ECDSA do Node usa nonces aleatórios, então duas assinaturas da mesma mensagem são diferentes; mesmo assim, as duas passam na verificação. O verificador de assinaturas aceita os dois esquemas e mostra qual codificação detectou.
Quando escolher cada um
- Chaves SSH de usuário e de host: Ed25519, ou
ed25519-skcom uma chave de segurança FIDO. Use ECDSA apenas em servidores antigos ou em hardware que não ofereçam Ed25519. - Chaves de acesso e WebAuthn: aceite os dois (COSE −7 e −8 ou −19), mas espere ES256 dos autenticadores de plataforma.
- Certificados TLS de confiança pública: ECDSA P-256 (ou P-384); os Baseline Requirements não permitem Ed25519.
- JWT e tokens de API: ES256 para a máxima compatibilidade e para chaves mantidas em um KMS na nuvem; Ed25519 onde todos os consumidores aceitam a RFC 8037 ou a RFC 9864. A página ES256 vs EdDSA para JWT aprofunda o assunto.
- Chaves dentro do Secure Enclave, de TPMs, de cartões inteligentes ou da maioria dos HSMs: ECDSA P-256, porque é isso que o hardware oferece.
- Blockchains: a escolha não cabe a você; siga o que a cadeia usa (ECDSA secp256k1 ou Schnorr no Bitcoin e no Ethereum, Ed25519 na Solana).
- Protocolos novos em que a verificação é crítica para o consenso: Ed25519 com uma regra de verificação especificada explicitamente, como o ZIP 215.
Notas de migração
Não existe conversão entre uma chave P-256 e uma chave Ed25519: as curvas são diferentes, e os formatos de chave também. Passar de uma para a outra é uma rotação de chaves.
- Gere as chaves novas onde elas vão ficar. Com
openssl genpkey -algorithm ED25519oussh-keygen -t ed25519, ou dentro do HSM, se ele tiver suporte a Ed25519. Confira o suporte no firmware antes de planejar. - Publique as duas chaves durante o período de sobreposição. Em um JWKS, dê a cada chave seu próprio
kidealg; noauthorized_keys, adicione a linha nova antes de remover a antiga; no caso de certificados, solicite um novo para a chave nova. - Atualize os verificadores antes dos signatários. Os verificadores precisam aceitar o novo identificador de algoritmo (
Ed25519ouEdDSAno JOSE, o OID1.3.101.112no X.509,ssh-ed25519no SSH) sem deixar de fixar uma lista de algoritmos permitidos, e nunca devem deixar que o token ou a mensagem escolha. - Passe a assinar com a chave nova e depois aposente a antiga quando tudo o que foi assinado com ela tiver expirado.
- Atenção às codificações. O código ECDSA costuma converter assinaturas entre DER e o formato bruto; o código Ed25519 não deve fazer isso, e o tamanho da “chave privada” Ed25519 varia conforme a API (semente de 32 bytes ou 64 bytes com a semente mais a chave pública).
O caminho inverso, do Ed25519 para o ECDSA, acontece principalmente quando as chaves passam para o hardware. Use nonces determinísticos ou hedged, exija low-S se as assinaturas servirem como identificadores e teste o tratamento de DER e do formato bruto com o conversor DER ⇄ bruto.
Referências
- FIPS 186-5, padrão de assinatura digital (§6 ECDSA, §7 EdDSA)
- RFC 8032, algoritmo de assinatura digital em curvas de Edwards
- RFC 6979, uso determinístico do DSA e do ECDSA
- SEC 1 v2, criptografia de curvas elípticas
- RFC 9864, algoritmos totalmente especificados para JOSE e COSE
- RFC 8410, Ed25519 e Ed448 no X.509
- ZIP 215, definição explícita da validação do Ed25519
- Baseline Requirements do CA/Browser Forum, §6.1.5
- Notas de versão do OpenSSH 9.5