Skip to content
ecdsa.com

Deterministic vs randomized ECDSA: RFC 6979, random and hedged nonces

Every ECDSA signature needs a secret, unique, unbiased nonce. The three ways to produce it fail in different ways, and verifiers cannot tell them apart.

Deterministic vs randomized ECDSA is about one value: the per-signature nonce k. Its quality decides whether the private key stays private, because one repeated nonce or a slight bias across many signatures is enough to compute the key. FIPS 186-5 allows two ways to produce it, and a third, hedged signing, combines them.

At a glance

RandomizedDeterministic (RFC 6979)Hedged
Nonce sourceFresh CSPRNG output per signatureHMAC-DRBG over private key and message hashDeterministic derivation mixed with fresh randomness
StandardFIPS 186-5 §6.3.1, Appendix A.3.1 and A.3.2RFC 6979 §3.2; FIPS 186-5 §6.3.2 and Appendix A.3.3RFC 6979 §3.6 option; expired CFRG draft; BIP-340 aux randomness
Same message signed twiceDifferent signaturesIdentical signaturesDifferent signatures
Weak or broken RNGKey can leakNot affectedNot affected
Fault injection on repeated signingHard to exploitCan leak the keyHard to exploit
Reproducible test vectorsNoYes (RFC 6979 Appendix A.2)Only with fixed extra input
Verifier changesNoneNoneNone
Default inOpenSSL, Node.js, Java, Python cryptographylibsecp256k1, @noble/curvesOpt-in: @noble/curves extraEntropy: true, BIP-340 signing

How each one fails

Randomized nonces depend completely on the random number generator. If it repeats a value (Sony's PlayStation 3 used a constant), the key falls to simple algebra. If it is merely biased, for example because the top bits are always zero or a timing side channel leaks the nonce length, lattice techniques solving the hidden number problem recover the key from a few hundred to a few thousand signatures; Minerva and TPM-Fail (2019) did exactly that against smart cards and TPMs. Embedded devices that sign shortly after boot, cloned virtual machines and forked processes are the classic risk environments.

Deterministic nonces remove the generator from the picture: k is derived with HMAC from the private key and the message hash, so the same input always yields the same nonce, and different messages yield unrelated nonces. The risk moves to physical attacks. If an attacker can glitch the device while it signs the same message twice, one correct and one faulty signature with the same nonce can reveal the key; Poddebniak and colleagues demonstrated such fault attacks against deterministic ECDSA and EdDSA in 2018. Deterministic signing also makes signatures repeatable, which some protocols want and others must not leak.

Hedged nonces feed both the deterministic inputs and fresh randomness into the derivation. A broken generator degrades the scheme to deterministic signing, and a fault attack faces a different nonce each time. RFC 6979 §3.6 already allows additional input, BIP-340 recommends 32 bytes of auxiliary randomness, ML-DSA (FIPS 204 §3.4) is hedged by default, and an IRTF draft to standardize hedged ECDSA and EdDSA expired in 2025 without becoming an RFC.

All three produce ordinary signatures. A verifier cannot distinguish them, which also means you cannot audit a signer's nonce strategy from its output, except by noticing that identical messages produce identical signatures.

What libraries do

  • OpenSSL signs with random nonces by default. OpenSSL 3.2 (November 2023) added RFC 6979 through the signature parameter nonce-type set to 1, which requires an explicit digest, and OpenSSL 3.6 brought deterministic ECDSA to its FIPS provider. On the command line: openssl pkeyutl -sign -pkeyopt nonce-type:1 -pkeyopt digest:sha256.
  • Python cryptography is randomized by default and has offered ec.ECDSA(hashes.SHA256(), deterministic_signing=True) since version 43.0 (July 2024).
  • Node.js crypto.sign() and WebCrypto use random nonces with no option to change it.
  • @noble/curves derives k with RFC 6979 by default and hedges when called with extraEntropy: true or extra bytes.
  • libsecp256k1, used by Bitcoin Core, uses RFC 6979 with optional extra data.
  • EdDSA is deterministic by definition (RFC 8032); some platform implementations add randomness anyway.

The difference is visible in a few lines of Python with cryptography 46.0.3:

Python: randomized and deterministic ECDSA with one P-256 key
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")
Output
randomized signatures equal:    False
deterministic signatures equal: True
all four verify with the same verifier

Testing and reproducibility

Deterministic signing makes known-answer tests possible: RFC 6979 Appendix A.2 lists expected signatures for P-192 through P-521 and other curves, and the test vectors tool and Project Wycheproof build on such vectors. With randomized or hedged signing you can only test that signatures verify and that malformed ones do not. For audits, deterministic mode is also how you check a suspicious signer: sign the same message twice and see whether the output repeats.

To detect actual nonce reuse in signatures you already have, compare r values across signatures from one key; a repeated r means a repeated nonce, and the nonce reuse checker does that for a batch.

When to choose which

  • Servers and CI with a healthy OS generator: any of the three is acceptable; prefer deterministic or hedged to remove a dependency.
  • Embedded devices, early-boot code, cloned VMs: deterministic or hedged, never purely random.
  • Hardware exposed to attackers (hardware wallets, smart cards, payment terminals): hedged, together with fault countermeasures such as verifying each signature before releasing it.
  • Test suites and interoperability work: deterministic, so vectors are reproducible.
  • Protocols where repeated identical signatures would leak information (for example that the same message was signed again): randomized or hedged.

Migration notes

Switching nonce strategy changes only the signer. Keys, signature formats and verifiers stay the same.

  1. Check library support and versions: OpenSSL 3.2 or later, cryptography 43 or later, or a library with RFC 6979 built in.
  2. Make sure the digest is set explicitly when enabling RFC 6979, since the derivation depends on it.
  3. Add a regression test that signs one message twice and asserts the expected behavior (equal for deterministic, different for hedged).
  4. Keep randomness healthy anyway: hedged signing still benefits from a good generator, and key generation always needs one.
  5. Review any place where signatures are compared or cached, because deterministic signatures make "same input, same output" true for the first time.

References

All comparisons