Skip to content
Lesson 10 of 13

Step 1 of 5 · Reading · ~1 min

Deterministic Nonces (RFC 6979)

ECDSA Algorithm

Why nonces are catastrophic to get wrong

Vanilla ECDSA signing chooses a fresh random integer k for every signature, then publishes r = (k*G).x mod n and s = k^{-1}(z + r*d) mod n.

If k is ever predictable, biased, or reused, the attacker can solve algebraically for the private key d — this is exactly how Sony's PS3 firmware-signing key was extracted in 2010.

RFC 6979: derive k from (d, message)

RFC 6979 replaces the RNG with HMAC-DRBG seeded by the private key and the message hash, eliminating randomness:

V = 0x01..01
K = 0x00..00
K = HMAC_K(V || 0x00 || int2octets(d) || bits2octets(h))
V = HMAC_K(V)
K = HMAC_K(V || 0x01 || int2octets(d) || bits2octets(h))
V = HMAC_K(V)
loop:
    T = ""
    while len(T) < rolen:
        V = HMAC_K(V); T += V
    k = bits2int(T)
    if 1 <= k < n: return k
    K = HMAC_K(V || 0x00); V = HMAC_K(V)

Properties:

  • Deterministic: same (d, msg) always yields the same k, so the same (r, s). Useful for test vectors and stateless signing.
  • Safe: as long as d is secret, k is computationally indistinguishable from random.
  • No RNG dependency: removes a giant class of footguns (embedded RNG starvation, fork-after-seed, VM snapshot replay).

Bitcoin Core uses RFC 6979 by default. So does libsecp256k1, OpenSSL ≥ 1.0.2, python-ecdsa, and the Go stdlib.

Caveats

  • Determinism does not protect against fault attacks (glitch a single bit during signing → still leaks d).
  • For privacy-preserving signing (e.g. CoinJoin), you may want fresh randomness mixed in (RFC 6979's "extra random data" extension).
Up nextImplementation PitfallsImplementation Pitfalls

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…