Pular para o conteúdo
ecdsa.com

ECDSA determinístico vs aleatorizado: RFC 6979, nonces aleatórios e hedged

Toda assinatura ECDSA precisa de um nonce secreto, único e sem viés. As três formas de produzi-lo falham de maneiras diferentes, e os verificadores não conseguem distingui-las.

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

AleatorizadoDeterminístico (RFC 6979)Hedged
Origem do nonceSaída nova do CSPRNG a cada assinaturaHMAC-DRBG sobre a chave privada e o hash da mensagemDerivação determinística misturada com aleatoriedade nova
NormaFIPS 186-5 §6.3.1, apêndices A.3.1 e A.3.2RFC 6979 §3.2; FIPS 186-5 §6.3.2 e apêndice A.3.3Opção da RFC 6979 §3.6; Internet-Draft expirado do CFRG; aleatoriedade auxiliar do BIP-340
Mesma mensagem assinada duas vezesAssinaturas diferentesAssinaturas idênticasAssinaturas diferentes
RNG fraco ou defeituosoA chave pode vazarNão é afetadoNão é afetado
Injeção de falhas em assinaturas repetidasDifícil de explorarPode vazar a chaveDifícil de explorar
Vetores de teste reproduzíveisNãoSim (RFC 6979, apêndice A.2)Só com entrada extra fixa
Mudanças no verificadorNenhumaNenhumaNenhuma
Usado por padrão emOpenSSL, Node.js, Java, cryptography (Python)libsecp256k1 e @noble/curvesOpcional: @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-type com 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 cryptography do Python é aleatorizada por padrão e oferece ec.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 k com a RFC 6979 por padrão e passa para o modo hedged quando chamada com extraEntropy: true ou 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:

Python: ECDSA aleatorizado e determinístico com uma única chave P-256
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")
Saída
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.

  1. Confira o suporte da biblioteca e as versões: OpenSSL 3.2 ou posterior, cryptography 43 ou posterior, ou uma biblioteca com a RFC 6979 integrada.
  2. Garanta que o digest esteja definido explicitamente ao ativar a RFC 6979, já que a derivação depende dele.
  3. 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).
  4. 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.
  5. 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

Todas as comparações