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 samek, so the same(r, s). Useful for test vectors and stateless signing. - Safe: as long as
dis secret,kis 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…