ECDSA determinístico vs aleatorizado é uma questão sobre um único valor: o nonce k de cada assinatura. A qualidade dele decide se a chave privada continua privada, porque um único nonce repetido ou um leve viés ao longo de muitas assinaturas basta para calcular a chave. O FIPS 186-5 admite duas formas de produzi-lo, e uma terceira, a assinatura hedged, combina as duas.
Visão geral
| Aleatorizado | Determinístico (RFC 6979) | Hedged | |
|---|---|---|---|
| Origem do nonce | Saída nova do CSPRNG a cada assinatura | HMAC-DRBG sobre a chave privada e o hash da mensagem | Derivação determinística misturada com aleatoriedade nova |
| Norma | FIPS 186-5 §6.3.1, apêndices A.3.1 e A.3.2 | RFC 6979 §3.2; FIPS 186-5 §6.3.2 e apêndice A.3.3 | Opção da RFC 6979 §3.6; Internet-Draft expirado do CFRG; aleatoriedade auxiliar do BIP-340 |
| Mesma mensagem assinada duas vezes | Assinaturas diferentes | Assinaturas idênticas | Assinaturas diferentes |
| RNG fraco ou defeituoso | A chave pode vazar | Não é afetado | Não é afetado |
| Injeção de falhas em assinaturas repetidas | Difícil de explorar | Pode vazar a chave | Difícil de explorar |
| Vetores de teste reproduzíveis | Não | Sim (RFC 6979, apêndice A.2) | Só com entrada extra fixa |
| Mudanças no verificador | Nenhuma | Nenhuma | Nenhuma |
| Usado por padrão em | OpenSSL, Node.js, Java, cryptography (Python) | libsecp256k1 e @noble/curves | Opcional: @noble/curves extraEntropy: true, assinatura BIP-340 |
Como cada um falha
Nonces aleatórios dependem totalmente do gerador de números aleatórios. Se ele repete um valor (o PlayStation 3 da Sony usava uma constante), a chave é recuperada com álgebra simples. Se ele apenas tem um viés — por exemplo, porque os bits mais altos são sempre zero ou porque um canal lateral de temporização vaza o comprimento do nonce —, técnicas baseadas em reticulados que resolvem o problema do número oculto recuperam a chave a partir de algumas centenas a alguns milhares de assinaturas; o Minerva e o TPM-Fail (2019) fizeram exatamente isso contra cartões inteligentes e TPMs. Dispositivos embarcados que assinam logo após a inicialização, máquinas virtuais clonadas e processos duplicados com fork são os ambientes de risco clássicos.
Nonces determinísticos tiram o gerador de cena: k é derivado com HMAC a partir da chave privada e do hash da mensagem, então a mesma entrada sempre produz o mesmo nonce, e mensagens diferentes produzem nonces sem relação entre si. O risco passa para os ataques físicos. Se um atacante consegue provocar uma falha no dispositivo enquanto ele assina a mesma mensagem duas vezes, uma assinatura correta e uma defeituosa com o mesmo nonce podem revelar a chave; Poddebniak e colegas demonstraram esses ataques por injeção de falhas contra ECDSA e EdDSA determinísticos em 2018. A assinatura determinística também torna as assinaturas repetíveis, algo que alguns protocolos querem e outros não podem deixar vazar.
Nonces hedged alimentam a derivação tanto com as entradas determinísticas quanto com aleatoriedade nova. Um gerador defeituoso rebaixa o esquema a uma assinatura determinística, e um ataque por injeção de falhas encontra um nonce diferente a cada vez. A RFC 6979 §3.6 já permite uma entrada adicional, o BIP-340 recomenda 32 bytes de aleatoriedade auxiliar, o ML-DSA (FIPS 204 §3.4) é hedged por padrão, e um Internet-Draft do IRTF para padronizar ECDSA e EdDSA hedged expirou em 2025 sem se tornar RFC.
As três abordagens produzem assinaturas comuns. Um verificador não consegue diferenciá-las, o que também significa que não é possível auditar a estratégia de nonce de um signatário pela saída dele, a não ser percebendo que mensagens idênticas produzem assinaturas idênticas.
O que as bibliotecas fazem
- O OpenSSL assina com nonces aleatórios por padrão. O OpenSSL 3.2 (novembro de 2023) acrescentou a RFC 6979 por meio do parâmetro de assinatura
nonce-typecom valor 1, que exige um digest explícito, e o OpenSSL 3.6 levou o ECDSA determinístico ao seu provedor FIPS. Na linha de comando:openssl pkeyutl -sign -pkeyopt nonce-type:1 -pkeyopt digest:sha256. - A
cryptographydo Python é aleatorizada por padrão e ofereceec.ECDSA(hashes.SHA256(), deterministic_signing=True)desde a versão 43.0 (julho de 2024). - O
crypto.sign()do Node.js e a WebCrypto usam nonces aleatórios, sem opção para mudar isso. - A @noble/curves deriva
kcom a RFC 6979 por padrão e passa para o modo hedged quando chamada comextraEntropy: trueou com bytes extras. - A libsecp256k1, usada pelo Bitcoin Core, usa a RFC 6979 com dados extras opcionais.
- O EdDSA é determinístico por definição (RFC 8032); algumas implementações de plataforma acrescentam aleatoriedade mesmo assim.
A diferença aparece em poucas linhas de Python com a cryptography 46.0.3:
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
key = ec.generate_private_key(ec.SECP256R1())
message = b"invoice 2026-10-20 #4411"
randomized = [key.sign(message, ec.ECDSA(hashes.SHA256())) for _ in range(2)]
deterministic = [
key.sign(message, ec.ECDSA(hashes.SHA256(), deterministic_signing=True)) for _ in range(2)
]
print("randomized signatures equal: ", randomized[0] == randomized[1])
print("deterministic signatures equal:", deterministic[0] == deterministic[1])
for sig in randomized + deterministic:
key.public_key().verify(sig, message, ec.ECDSA(hashes.SHA256()))
print("all four verify with the same verifier")
randomized signatures equal: False
deterministic signatures equal: True
all four verify with the same verifier
Testes e reprodutibilidade
A assinatura determinística torna possíveis os testes de resposta conhecida (known-answer tests): o apêndice A.2 da RFC 6979 lista as assinaturas esperadas para as curvas de P-192 a P-521, entre outras, e a ferramenta de vetores de teste e o Project Wycheproof se baseiam em vetores desse tipo. Com assinatura aleatorizada ou hedged, só é possível testar se as assinaturas passam na verificação e se as malformadas não passam. Em auditorias, o modo determinístico também é a forma de checar um signatário suspeito: assine a mesma mensagem duas vezes e veja se a saída se repete.
Para detectar uma reutilização de nonce real em assinaturas que você já tem, compare os valores r das assinaturas de uma mesma chave; um r repetido significa um nonce repetido, e o verificador de reutilização de nonce faz isso para um lote inteiro.
Quando escolher cada um
- Servidores e CI com um gerador do sistema operacional saudável: qualquer uma das três abordagens é aceitável; prefira a determinística ou a hedged para eliminar uma dependência.
- Dispositivos embarcados, código executado no início do boot, VMs clonadas: determinística ou hedged, nunca puramente aleatória.
- Hardware exposto a atacantes (carteiras de hardware, cartões inteligentes, terminais de pagamento): hedged, junto com contramedidas contra falhas, como verificar cada assinatura antes de liberá-la.
- Suítes de teste e trabalho de interoperabilidade: determinística, para que os vetores sejam reproduzíveis.
- Protocolos em que assinaturas idênticas repetidas vazariam informação (por exemplo, que a mesma mensagem foi assinada de novo): aleatorizada ou hedged.
Notas de migração
Trocar a estratégia de nonce muda apenas o signatário. As chaves, os formatos de assinatura e os verificadores continuam os mesmos.
- Confira o suporte da biblioteca e as versões: OpenSSL 3.2 ou posterior,
cryptography43 ou posterior, ou uma biblioteca com a RFC 6979 integrada. - Garanta que o digest esteja definido explicitamente ao ativar a RFC 6979, já que a derivação depende dele.
- Adicione um teste de regressão que assine uma mensagem duas vezes e confirme o comportamento esperado (assinaturas iguais no modo determinístico, diferentes no hedged).
- Mantenha a aleatoriedade saudável mesmo assim: a assinatura hedged continua se beneficiando de um bom gerador, e a geração de chaves sempre precisa de um.
- Revise todos os pontos em que assinaturas são comparadas ou armazenadas em cache, porque as assinaturas determinísticas tornam verdadeiro, pela primeira vez, o princípio “mesma entrada, mesma saída”.
Referências
- RFC 6979, uso determinístico do DSA e do ECDSA (§3.2, §3.6, apêndice A.2)
- FIPS 186-5, §6.3, número secreto por mensagem
- FIPS 204, §3.4, assinatura hedged e determinística
- draft-irtf-cfrg-det-sigs-with-noise (Internet-Draft expirado)
- BIP-340, assinatura padrão com aleatoriedade auxiliar
- Minerva: ataques com reticulados explorando o vazamento de nonces do ECDSA
- CHANGES do OpenSSL (3.2.0: suporte à RFC 6979)
- Registro de alterações da pyca/cryptography (43.0.0: ECDSA determinístico)