Aller au contenu
ecdsa.com

ECDSA déterministe vs aléatoire : RFC 6979, nonces hedged

Chaque signature ECDSA exige un nonce secret, unique et non biaisé. Les trois façons de le produire échouent de manières différentes, et les vérificateurs ne peuvent pas les distinguer.

Le choix entre ECDSA déterministe et ECDSA aléatoire porte sur une seule valeur : le nonce k propre à chaque signature. Sa qualité détermine si la clé privée reste privée, car un seul nonce répété, ou un léger biais sur de nombreuses signatures, suffit à calculer la clé. FIPS 186-5 autorise deux façons de le produire, et une troisième, la signature hedged, combine les deux.

Vue d’ensemble

AléatoireDéterministe (RFC 6979)Hedged
Source du nonceNouvelle sortie du CSPRNG pour chaque signatureHMAC-DRBG appliqué à la clé privée et au condensat du messageDérivation déterministe mêlée à un aléa frais
NormeFIPS 186-5 §6.3.1, annexes A.3.1 et A.3.2RFC 6979 §3.2 ; FIPS 186-5 §6.3.2 et annexe A.3.3Option de la RFC 6979 §3.6 ; Internet-Draft du CFRG expiré ; aléa auxiliaire de BIP-340
Même message signé deux foisSignatures différentesSignatures identiquesSignatures différentes
RNG faible ou défaillantFuite possible de la cléNon concernéNon concerné
Injection de fautes lors de signatures répétéesDifficile à exploiterPeut révéler la cléDifficile à exploiter
Vecteurs de test reproductiblesNonOui (RFC 6979, annexe A.2)Seulement avec une entrée supplémentaire fixe
Modifications côté vérificateurAucuneAucuneAucune
Par défaut dansOpenSSL, Node.js, Java, Python cryptographylibsecp256k1, @noble/curvesSur option : @noble/curves extraEntropy: true, signature BIP-340

Comment chaque approche échoue

Les nonces aléatoires dépendent entièrement du générateur de nombres aléatoires. S’il répète une valeur (la PlayStation 3 de Sony utilisait une constante), un peu d’algèbre élémentaire suffit à obtenir la clé. S’il est seulement biaisé, par exemple parce que les bits de poids fort sont toujours nuls ou qu’un canal auxiliaire temporel laisse fuir la longueur du nonce, des techniques fondées sur les réseaux euclidiens, qui résolvent le problème du nombre caché, retrouvent la clé à partir de quelques centaines à quelques milliers de signatures ; Minerva et TPM-Fail (2019) ont fait exactement cela contre des cartes à puce et des TPM. Les appareils embarqués qui signent peu après le démarrage, les machines virtuelles clonées et les processus dupliqués par fork sont les environnements à risque classiques.

Les nonces déterministes sortent le générateur de l’équation : k est dérivé par HMAC de la clé privée et du condensat du message, si bien qu’une même entrée donne toujours le même nonce et que des messages différents donnent des nonces sans rapport entre eux. Le risque se déplace vers les attaques physiques. Si un attaquant peut perturber l’appareil (glitch) pendant qu’il signe deux fois le même message, une signature correcte et une signature erronée produites avec le même nonce peuvent révéler la clé ; Poddebniak et ses coauteurs ont démontré de telles attaques par injection de fautes contre ECDSA et EdDSA déterministes en 2018. La signature déterministe rend aussi les signatures reproductibles, ce que certains protocoles recherchent et que d’autres ne doivent pas laisser transparaître.

Les nonces hedged injectent à la fois les entrées déterministes et un aléa frais dans la dérivation. Avec un générateur défaillant, le schéma se ramène à une signature déterministe, et une attaque par injection de fautes se heurte à un nonce différent à chaque fois. La RFC 6979 §3.6 autorise déjà une entrée supplémentaire, BIP-340 recommande 32 octets d’aléa auxiliaire, ML-DSA (FIPS 204 §3.4) est hedged par défaut, et un Internet-Draft de l’IRTF visant à normaliser ECDSA et EdDSA hedged a expiré en 2025 sans devenir une RFC.

Les trois approches produisent des signatures ordinaires. Un vérificateur ne peut pas les distinguer, ce qui signifie aussi que vous ne pouvez pas auditer la stratégie de nonce d’un signataire à partir de ce qu’il produit, sauf en remarquant que des messages identiques donnent des signatures identiques.

Ce que font les bibliothèques

  • OpenSSL signe par défaut avec des nonces aléatoires. OpenSSL 3.2 (novembre 2023) a ajouté la prise en charge de la RFC 6979 via le paramètre de signature nonce-type réglé sur 1, ce qui exige de définir explicitement l’algorithme de condensat, et OpenSSL 3.6 a apporté ECDSA déterministe à son fournisseur FIPS. En ligne de commande : openssl pkeyutl -sign -pkeyopt nonce-type:1 -pkeyopt digest:sha256.
  • Python cryptography utilise par défaut des nonces aléatoires et propose ec.ECDSA(hashes.SHA256(), deterministic_signing=True) depuis la version 43.0 (juillet 2024).
  • Node.js crypto.sign() et WebCrypto utilisent des nonces aléatoires, sans option pour modifier ce comportement.
  • @noble/curves dérive k selon la RFC 6979 par défaut et passe en mode hedged lorsqu’il est appelé avec extraEntropy: true ou des octets supplémentaires.
  • libsecp256k1, utilisée par Bitcoin Core, applique la RFC 6979 avec des données supplémentaires facultatives.
  • EdDSA est déterministe par définition (RFC 8032) ; certaines implémentations de plateforme ajoutent malgré tout de l’aléa.

La différence se voit en quelques lignes de Python avec cryptography 46.0.3 :

Python : ECDSA aléatoire et déterministe avec une seule clé 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")
Sortie
randomized signatures equal:    False
deterministic signatures equal: True
all four verify with the same verifier

Tests et reproductibilité

La signature déterministe rend possibles les tests à réponse connue : l’annexe A.2 de la RFC 6979 donne les signatures attendues pour P-192 à P-521 et pour d’autres courbes, et l’outil de vecteurs de test comme le projet Wycheproof s’appuient sur de tels vecteurs. Avec une signature aléatoire ou hedged, vous pouvez seulement tester que les signatures se vérifient et que les signatures malformées ne se vérifient pas. Pour un audit, le mode déterministe permet aussi de contrôler un signataire suspect : signez deux fois le même message et regardez si la sortie se répète.

Pour détecter une réutilisation de nonce effective dans des signatures dont vous disposez déjà, comparez les valeurs r des signatures produites par une même clé ; un r répété signifie un nonce répété, et le vérificateur de réutilisation de nonce effectue cette comparaison sur tout un lot.

Quelle approche choisir

  • Serveurs et CI disposant d’un générateur du système d’exploitation fiable : les trois approches conviennent ; préférez la signature déterministe ou hedged pour supprimer une dépendance.
  • Appareils embarqués, code exécuté tôt au démarrage, VM clonées : déterministe ou hedged, jamais purement aléatoire.
  • Matériel exposé aux attaquants (portefeuilles matériels, cartes à puce, terminaux de paiement) : hedged, avec des contre-mesures contre les fautes, par exemple la vérification de chaque signature avant de la délivrer.
  • Suites de tests et travaux d’interopérabilité : déterministe, pour que les vecteurs soient reproductibles.
  • Protocoles où des signatures identiques répétées divulgueraient une information (par exemple, que le même message a de nouveau été signé) : aléatoire ou hedged.

Notes de migration

Changer de stratégie de nonce ne modifie que le signataire. Les clés, les formats de signature et les vérificateurs restent les mêmes.

  1. Vérifiez la prise en charge par votre bibliothèque et les versions : OpenSSL 3.2 ou ultérieur, cryptography 43 ou ultérieur, ou une bibliothèque qui intègre la RFC 6979.
  2. Assurez-vous que l’algorithme de condensat est défini explicitement lorsque vous activez la RFC 6979, car la dérivation en dépend.
  3. Ajoutez un test de non-régression qui signe deux fois un même message et contrôle le comportement attendu (signatures égales en mode déterministe, différentes en mode hedged).
  4. Gardez malgré tout une source d’aléa fiable : la signature hedged tire toujours profit d’un bon générateur, et la génération de clés en a toujours besoin.
  5. Passez en revue tous les endroits où des signatures sont comparées ou mises en cache, car les signatures déterministes rendent vraie, pour la première fois, la règle « même entrée, même sortie ».

Références

Tous les comparatifs