Zum Inhalt springen
ecdsa.com

Deterministisches vs. randomisiertes ECDSA: RFC 6979, zufällige und Hedged-Nonces

Jede ECDSA-Signatur braucht eine geheime, einmalige und unverzerrte Nonce. Die drei Wege, sie zu erzeugen, scheitern auf unterschiedliche Weise, und für Verifizierer sind die Ergebnisse nicht zu unterscheiden.

Bei deterministischem vs. randomisiertem ECDSA geht es um einen einzigen Wert: die Nonce k, die für jede Signatur neu gebildet wird. Von ihrer Qualität hängt ab, ob der private Schlüssel geheim bleibt, denn eine einzige wiederholte Nonce oder eine leichte Verzerrung über viele Signaturen hinweg genügt, um den Schlüssel zu berechnen. FIPS 186-5 erlaubt zwei Wege, sie zu erzeugen, und ein dritter, die Hedged-Variante, kombiniert beide.

Auf einen Blick

RandomisiertDeterministisch (RFC 6979)Hedged
Quelle der NonceFrische CSPRNG-Ausgabe pro SignaturHMAC-DRBG über privaten Schlüssel und Hash der NachrichtDeterministische Ableitung, gemischt mit frischem Zufall
StandardFIPS 186-5 §6.3.1, Anhang A.3.1 und A.3.2RFC 6979 §3.2; FIPS 186-5 §6.3.2 und Anhang A.3.3Option in RFC 6979 §3.6; abgelaufener CFRG-Entwurf; zusätzlicher Zufall (aux) bei BIP-340
Dieselbe Nachricht zweimal signiertUnterschiedliche SignaturenIdentische SignaturenUnterschiedliche Signaturen
Schwacher oder defekter RNGSchlüssel kann offengelegt werdenNicht betroffenNicht betroffen
Fehlerinjektion bei wiederholtem SignierenSchwer auszunutzenKann den Schlüssel offenlegenSchwer auszunutzen
Reproduzierbare TestvektorenNeinJa (RFC 6979 Anhang A.2)Nur mit fester zusätzlicher Eingabe
Änderungen am VerifiziererKeineKeineKeine
Voreinstellung inOpenSSL, Node.js, Java, Python cryptographylibsecp256k1, @noble/curvesOptional: @noble/curves mit extraEntropy: true, Signieren nach BIP-340

Wie die einzelnen Varianten scheitern

Randomisierte Nonces hängen vollständig vom Zufallszahlengenerator ab. Wiederholt er einen Wert (Sonys PlayStation 3 verwendete eine Konstante), fällt der Schlüssel durch einfache Algebra. Liefert er nur verzerrte Werte, etwa weil die obersten Bits immer null sind oder ein Timing-Seitenkanal die Länge der Nonce verrät, gewinnen gitterbasierte Verfahren, die das Hidden Number Problem lösen, den Schlüssel aus einigen hundert bis einigen tausend Signaturen zurück; Minerva und TPM-Fail (2019) haben genau das bei Smartcards und TPMs getan. Eingebettete Geräte, die kurz nach dem Booten signieren, geklonte virtuelle Maschinen und geforkte Prozesse sind die klassischen Risikoumgebungen.

Deterministische Nonces nehmen den Generator aus dem Spiel: k wird per HMAC aus dem privaten Schlüssel und dem Hash der Nachricht abgeleitet, sodass dieselbe Eingabe immer dieselbe Nonce ergibt und verschiedene Nachrichten voneinander unabhängige Nonces. Das Risiko verlagert sich auf physische Angriffe. Kann ein Angreifer das Gerät per Glitch stören, während es dieselbe Nachricht zweimal signiert, können eine korrekte und eine fehlerhafte Signatur mit derselben Nonce den Schlüssel offenlegen; Poddebniak und Kollegen haben solche Fehlerangriffe 2018 gegen deterministisches ECDSA und EdDSA demonstriert. Deterministisches Signieren macht Signaturen außerdem wiederholbar – manche Protokolle wollen genau das, bei anderen darf diese Information nicht nach außen dringen.

Hedged-Nonces speisen sowohl die deterministischen Eingaben als auch frischen Zufall in die Ableitung ein. Ein defekter Generator lässt das Verfahren auf deterministisches Signieren zurückfallen, und ein Fehlerangriff trifft jedes Mal auf eine andere Nonce. RFC 6979 §3.6 erlaubt bereits zusätzliche Eingaben, BIP-340 empfiehlt 32 Byte zusätzlichen Zufall, ML-DSA (FIPS 204 §3.4) arbeitet standardmäßig in der Hedged-Variante, und ein IRTF-Entwurf zur Standardisierung von Hedged-ECDSA und Hedged-EdDSA ist 2025 abgelaufen, ohne zum RFC zu werden.

Alle drei erzeugen gewöhnliche Signaturen. Ein Verifizierer kann sie nicht unterscheiden; das heißt auch, dass du die Nonce-Strategie eines Signierers nicht anhand seiner Ausgabe prüfen kannst – außer, indem du bemerkst, dass identische Nachrichten identische Signaturen ergeben.

Wie sich Bibliotheken verhalten

  • OpenSSL signiert standardmäßig mit zufälligen Nonces. OpenSSL 3.2 (November 2023) hat RFC 6979 über den Signaturparameter nonce-type mit dem Wert 1 eingeführt, was einen explizit angegebenen Digest erfordert, und OpenSSL 3.6 brachte deterministisches ECDSA in seinen FIPS-Provider. Auf der Befehlszeile: openssl pkeyutl -sign -pkeyopt nonce-type:1 -pkeyopt digest:sha256.
  • Python cryptography signiert standardmäßig randomisiert und bietet seit Version 43.0 (Juli 2024) ec.ECDSA(hashes.SHA256(), deterministic_signing=True) an.
  • Node.js crypto.sign() und WebCrypto verwenden zufällige Nonces, ohne Möglichkeit, das zu ändern.
  • @noble/curves leitet k standardmäßig nach RFC 6979 ab und arbeitet in der Hedged-Variante, wenn es mit extraEntropy: true oder zusätzlichen Bytes aufgerufen wird.
  • libsecp256k1, von Bitcoin Core verwendet, nutzt RFC 6979 mit optionalen Zusatzdaten.
  • EdDSA ist per Definition deterministisch (RFC 8032); manche Plattformimplementierungen fügen trotzdem Zufall hinzu.

Der Unterschied zeigt sich in wenigen Zeilen Python mit cryptography 46.0.3:

Python: randomisiertes und deterministisches ECDSA mit einem P-256-Schlüssel
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")
Ausgabe
randomized signatures equal:    False
deterministic signatures equal: True
all four verify with the same verifier

Tests und Reproduzierbarkeit

Deterministisches Signieren macht Known-Answer-Tests möglich: RFC 6979 Anhang A.2 listet erwartete Signaturen für P-192 bis P-521 und weitere Kurven auf, und das Testvektor-Tool sowie Project Wycheproof bauen auf solchen Vektoren auf. Bei randomisiertem Signieren oder in der Hedged-Variante kannst du nur testen, dass Signaturen die Prüfung bestehen und fehlerhaft aufgebaute nicht. Bei Audits ist der deterministische Modus auch der Weg, einen verdächtigen Signierer zu prüfen: Signiere dieselbe Nachricht zweimal und sieh nach, ob sich die Ausgabe wiederholt.

Um tatsächliche Nonce-Wiederverwendung in vorhandenen Signaturen zu erkennen, vergleiche die Werte von r über die Signaturen eines Schlüssels hinweg; ein wiederholtes r bedeutet eine wiederholte Nonce, und der Nonce-Wiederverwendungs-Checker erledigt das für viele Signaturen auf einmal.

Wann welche Variante passt

  • Server und CI mit einem intakten Zufallsgenerator des Betriebssystems: Jede der drei Varianten ist akzeptabel; bevorzuge die deterministische oder die Hedged-Variante, um eine Abhängigkeit loszuwerden.
  • Eingebettete Geräte, Code in der frühen Bootphase, geklonte VMs: die deterministische oder die Hedged-Variante, nie rein zufällige Nonces.
  • Hardware, die Angreifern ausgesetzt ist (Hardware-Wallets, Smartcards, Zahlungsterminals): die Hedged-Variante, zusammen mit Gegenmaßnahmen gegen Fehlerangriffe, etwa jede Signatur vor der Herausgabe zu prüfen.
  • Testsuiten und Interoperabilitätsarbeit: die deterministische Variante, damit Vektoren reproduzierbar sind.
  • Protokolle, bei denen wiederholte identische Signaturen Informationen preisgeben würden (etwa, dass dieselbe Nachricht erneut signiert wurde): die randomisierte oder die Hedged-Variante.

Hinweise zur Migration

Ein Wechsel der Nonce-Strategie betrifft nur den Signierer. Schlüssel, Signaturformate und Verifizierer bleiben unverändert.

  1. Prüfe die Unterstützung in deiner Bibliothek und die Versionen: OpenSSL 3.2 oder neuer, cryptography 43 oder neuer oder eine Bibliothek mit eingebautem RFC 6979.
  2. Stelle sicher, dass der Digest explizit gesetzt ist, wenn du RFC 6979 aktivierst, denn die Ableitung hängt von ihm ab.
  3. Füge einen Regressionstest hinzu, der eine Nachricht zweimal signiert und das erwartete Verhalten prüft (gleiche Signaturen bei der deterministischen, verschiedene bei der Hedged-Variante).
  4. Sorge trotzdem für guten Zufall: Auch die Hedged-Variante profitiert von einem guten Generator, und die Schlüsselerzeugung braucht immer einen.
  5. Prüfe alle Stellen, an denen Signaturen verglichen oder zwischengespeichert werden, denn mit deterministischen Signaturen gilt „gleiche Eingabe, gleiche Ausgabe“ zum ersten Mal.

Quellen

Alle Vergleiche