45 min read

One Number, Used Twice: How a Repeated Nonce Hands Over Your Private Key -- and How Determinism Takes It Back

A repeated ECDSA nonce leaks your private key with grade-school algebra; a reused AES-GCM IV forges ciphertext. Why -- and how determinism fixes both.

Permalink

1. One Number, Used Twice

In December 2010, on stage at the 27th Chaos Communication Congress in Berlin, three researchers working under the name fail0verflow explained how they had recovered the master private key that anchors the entire PlayStation 3 chain of trust [1]. There was no brute force, no exotic side channel, no supercomputer grinding for months. There were two signatures and the kind of algebra you learned before you were old enough to drive. Sony had signed its code with ECDSA, the elliptic-curve digital signature algorithm, and Sony had signed every firmware image with the same secret per-signature number. Two events that are often merged into one: fail0verflow disclosed the constant-nonce flaw at 27C3 in December 2010; George Hotz, known as geohot, separately published an extracted PS3 root key in January 2011 [9]. The talk revealed the mechanism; the key release came afterward. Keep them distinct.

Sit with how strange that is. The console's security rested on a signature scheme that most cryptographers would call sound. AES was not broken. The elliptic curve was not broken. The signature math was not broken. One input was reused, and the entire trust anchor fell out of a schoolbook manipulation that a motivated teenager could reproduce on paper.

Now the mirror image, in a completely different primitive. In 2016, a team scanning the live internet found 184 public HTTPS servers repeating a different one-time number -- the AES-GCM initialization vector -- and reported that this "fully breaks the authenticity of the connections" [3]. Not the confidentiality of a lab toy: the authenticity of real TLS sessions on the open web, letting an attacker forge messages the server would accept as genuine.

Same disease, entirely different organ. One is a signature that proves who you are; the other is the cipher that guards most of the web's traffic. Both staked everything on a number that was supposed to be used correctly exactly once.

That shared bet is the subject of this article. Both primitives depend, silently, on a value that must be unique and unpredictable -- once, per key. The precise question: what, exactly, does each stake on that number, and what is the exact cost of getting it wrong? For the repeat case, the answer is total and immediate -- and the algebra is short enough to print in full.

In cryptography, reusing one number can cost you everything.

That is the punchline, and by the end you will have earned it rather than taken it on faith -- the full key-recovery algebra, Antoine Joux's cipher attack, the statistical cousin that needs only a fraction of a leaked bit, and the deterministic designs that dissolve the whole failure family. But how can two signatures undo an entire console's chain of trust? To see it, we first have to meet the number both of these primitives are quietly betting everything on.

2. The Secret Number Both Primitives Depend On

Two algorithms, designed decades and a world apart -- a discrete-logarithm signature and a block-cipher mode of authenticated encryption -- turn out to share a single point of failure. Before we can watch it break, we need to know where the number comes from and why it has to exist at all.

The signature side is the older lineage. ElGamal's 1985 signature scheme introduced a per-signature secret exponent [10], and when the United States standardized the Digital Signature Algorithm as FIPS 186 in 1994 [11], that per-signature secret came along for the ride. Its elliptic-curve descendant, ECDSA, keeps it. The value is called the signing nonce, written kk, and it is regenerated fresh for every single signature.

Signing nonce (k)

The per-signature secret scalar in (EC)DSA. For each signature the signer draws a new kk in the range [1,n1][1, n-1], where nn is the order of the curve's base point. It must be unique, secret, and uniformly distributed -- exactly once per key. It is never transmitted, yet every signature is computed from it.

The cipher side is younger. When NIST standardized Galois/Counter Mode in SP 800-38D in 2007, the specification required that the initialization vector -- the IV\text{IV}, GCM's nonce -- be distinct for every message encrypted under a given key [12]. Same structural demand, opposite secrecy requirement: the signing nonce must be secret, while the GCM nonce may be completely public. What both must be is fresh.

Initialization vector / nonce (AES-GCM)

The per-message value GCM mixes in so that encrypting under a fixed key never repeats its keystream. Uniqueness under a given key -- not secrecy -- is the entire contract. A public counter is a perfectly good GCM nonce; a repeated one is a catastrophe.

Now put the two governing equations side by side. An ECDSA signature on a message whose hash (as an integer) is zz, under private key dd, is the pair (r,s)(r, s):

r=(kG)xmodn,s=k1(z+rd)modnr = (k \cdot G)_x \bmod n, \qquad s = k^{-1}\,(z + r\,d) \bmod n

Here GG is the fixed base point, nn its prime order, dd the private key, and rr is the x-coordinate of the curve point kGk \cdot G reduced modulo nn. The AES-GCM authentication tag on ciphertext CC with additional data AA is:

T=EK(J0)GHASHH(A,C),H=EK(0128)T = E_K(J_0) \oplus \mathrm{GHASH}_H(A, C), \qquad H = E_K(0^{128})

EKE_K is AES under key KK; J0J_0 is a pre-counter block derived from the IV; GHASHH\mathrm{GHASH}_H is a polynomial hash over the field GF(2128)\mathrm{GF}(2^{128}) keyed by the secret subkey HH, which is simply AES applied to the all-zero block.

Look at what both equations hide inside them. The signing equation multiplies the private key dd by the public rr and masks it behind kk. The tag equation masks the keyed hash behind the one-time pad EK(J0)E_K(J_0), which is a deterministic function of the nonce. In each case, one freshly chosen value is the only thing standing between a routine operation and a full disclosure. That gives us the single shared contract, short enough to fit on one line: the number must be unique and unpredictable, exactly once, per key.

None of this was a secret to the designers. Bellare, Goldwasser, and Micciancio analyzed the danger of a poorly generated DSA nonce as early as their 1997 CRYPTO paper, "The DSS case" [13], showing that a linear-congruential nonce generator breaks the scheme. Terminology drifts across modes, so fix it now: a nonce need only be unique (CTR, GCM); an IV for CBC must additionally be unpredictable; a salt is unique and public and feeds a KDF. The mode dictates which property is load-bearing. Part 2 and the block-cipher-modes installment work through the distinctions; here we only need "fresh, once, per key." The contract was understood from the beginning; nobody misunderstood the rule. They simply could not always keep it.

The contract says "never repeat." So begin with the crudest possible violation -- the same number, twice -- and watch precisely how much it costs.

3. Two Signatures, One k, and Your Private Key

This is the entire thesis compressed into one page of algebra -- no lattice, no side channel, no probability, just subtraction and one division. How little work does complete key recovery actually take?

Start from the fact that makes it possible. The first signature component, r=(kG)xmodnr = (k \cdot G)_x \bmod n, depends only on the nonce kk and the fixed public base point GG. It does not depend on the message. So if you sign two different messages under the same kk, both signatures carry the identical rr. That repeated rr is the visible tell -- a fingerprint an attacker can spot by scanning a signature log, with no secret knowledge at all. This is exactly what fail0verflow read off the PlayStation 3: every firmware signature carried the same rr, the public fingerprint of a constant kk. You do not need to break anything to notice it; you just look for two signatures with a matching first half.

Now write the two signing equations under that shared kk:

s1=k1(z1+rd)(modn),s2=k1(z2+rd)(modn)s_1 = k^{-1}(z_1 + r\,d) \pmod n, \qquad s_2 = k^{-1}(z_2 + r\,d) \pmod n

Subtract the second from the first. The private key appears only inside the identical rdr\,d term, so it cancels completely:

s1s2=k1((z1+rd)(z2+rd))=k1(z1z2)(modn)s_1 - s_2 = k^{-1}\big((z_1 + r\,d) - (z_2 + r\,d)\big) = k^{-1}(z_1 - z_2) \pmod n

Every quantity on the right except kk is public: the two message hashes z1,z2z_1, z_2 and the two signature halves s1,s2s_1, s_2. So solve for the nonce directly:

k=(z1z2)(s1s2)1modnk = (z_1 - z_2)\,(s_1 - s_2)^{-1} \bmod n

One subtraction on top, one modular inverse on the bottom. With kk in hand, substitute back into the first equation -- multiply through by kk, subtract z1z_1, and divide by the public rr:

s1k=z1+rd    d=(s1kz1)r1modns_1 k = z_1 + r\,d \implies d = (s_1 k - z_1)\,r^{-1} \bmod n

That is the private key. Count the cost to the attacker: two signatures, a handful of modular operations, Constant work here means a fixed number of field operations, independent of the key size. A 256-bit curve is no harder to break this way than a 160-bit one, because the attack never touches the key's length. and the recovery is certain -- not probable, not "on average," but exact, every time, the moment the repeat occurs. It solves a two-by-two linear system that the reuse handed over for free.

Ctrl + scroll to zoom
How two signatures sharing one nonce collapse to the private key

You do not have to take the algebra on faith -- here is the whole attack as runnable code over a toy curve order, recovering the private key from public values alone:

JavaScript Recover an ECDSA private key from two signatures that reused a nonce
// Recover the ECDSA private key d from two signatures sharing nonce k.
function egcd(a, b) {
if (b === 0n) return [a, 1n, 0n];
const [g, x, y] = egcd(b, a % b);
return [g, y, x - (a / b) * y];
}
function modInv(a, n) {
a = ((a % n) + n) % n;
const [g, x] = egcd(a, n);
if (g !== 1n) throw new Error('no inverse');
return ((x % n) + n) % n;
}

const n = 1103n;   // toy prime "curve order" (real curves use ~256-bit n)
const d = 937n;    // the SECRET key the attacker must not know
const k = 421n;    // the reused nonce (identical for both signatures)
const r = 668n;    // r = (k*G).x mod n -- SHARED because k is shared
const z1 = 123n, z2 = 456n;  // two different message hashes

// Victim signs both messages with the SAME k:
const s1 = (modInv(k, n) * (z1 + r * d)) % n;
const s2 = (modInv(k, n) * (z2 + r * d)) % n;

// Attacker sees only public (r, s1, z1, s2, z2). Recover k, then d:
const kRec = ((((z1 - z2) % n) + n) % n) * modInv((((s1 - s2) % n) + n) % n, n) % n;
const dRec = ((((s1 * kRec - z1) % n) + n) % n) * modInv(r, n) % n;

console.log('shared r    :', r.toString());
console.log('recovered k :', kRec.toString(), '(true k =', k.toString() + ')');
console.log('recovered d :', dRec.toString(), '(true d =', d.toString() + ')');
console.log(dRec === d ? 'PRIVATE KEY RECOVERED from two signatures.' : 'mismatch');

Press Run to execute.

Two signatures sharing one nonce equal certain, instant, total key recovery -- by hand, with pure algebra. Reuse is not a slope that gradually weakens security; it is a cliff. "Reuse one number equals everything" is a literal statement about ECDSA, not a rhetorical flourish.

This is not a museum piece. The PlayStation 3 fell to exactly this -- a constant kk across every firmware signature, two images sharing one rr, the master key recovered [1]. Section 5 catalogs the rest of the real-world chain, from that constant-nonce break down to biases of less than a single bit.

Certainty from a literal repeat is the easy case -- easy for an attacker to run, and, as we will see, easy for a defender to eliminate. So attackers asked a sharper and far more dangerous question. What if the nonces are never equal, only slightly, invisibly skewed?

4. From Repeat to Bias: The Hidden Number Problem

You do not need the nonces to be equal. You only need them to be a little bit predictable -- and then to collect enough of them. This is where the story turns, because it dismantles the comforting fix you probably just thought of. If a literal repeat is the danger, surely "make sure the nonces are always different" closes it? It does not come close.

Here is the shift in viewpoint. In Section 3, a repeat gave us an exact equation and we solved it. Now suppose each nonce is merely skewed -- say the top few bits are always zero, or the generator leans slightly toward small values. No two nonces are equal, so the certainty attack never triggers. But each signature is now a noisy linear equation relating the public data to the secret key dd modulo nn, with the unknown nonce constrained to a smaller range than it should occupy. One such equation tells you almost nothing.

Stack hundreds or thousands of them as the rows of a lattice, though, and the secret dd shows up as one unusually short vector hiding in that grid. A reduction algorithm hunts it down, and the key reads straight out.

Hidden Number Problem (HNP)

The problem of recovering a hidden integer -- here, the private key -- from many samples that each reveal only a few most-significant bits of a related product modulo nn. Dan Boneh and Ramarathnam Venkatesan introduced it in 1996, and it is the framework underneath every biased-nonce attack on (EC)DSA [14].

Lattice (conceptual)

An integer grid of points formed by adding and subtracting a fixed set of basis vectors. Biased-nonce recovery constructs a lattice whose unusually short vector encodes the secret key; a reduction algorithm finds that vector. We stay conceptual here -- the internals of LLL and the closest-vector problem belong to their own discussion.

The genealogy is worth knowing, because each step needed less leakage than the last. Boneh and Venkatesan framed the Hidden Number Problem in 1996 [14]. Around 2000, Daniel Bleichenbacher showed that even a tiny statistical bias in DSA nonces is exploitable through a Fourier-analytic version of the same idea. Bleichenbacher's seminal biased-nonce result was never published as a standalone paper. It survives as a 2000 IEEE P1363 presentation and a 2005 CRYPTO rump-session talk, "Experiments with DSA," and is reconstructed through the reference lists of later work such as Nguyen-Shparlinski and LadderLeak. A standalone Bleichenbacher paper on this would be a fabrication; the history genuinely has this shape.

Nick Howgrave-Graham and Nigel Smart made the lattice attack practical in 2001, recovering keys from partially known nonces [15]. Phong Nguyen and Igor Shparlinski then proved rigorous polynomial-time ECDSA key recovery from just a few leaked nonce bits per signature in 2003 [7]. Two decades on, LadderLeak pushed the frontier to its logical extreme, breaking ECDSA with less than one bit of nonce leakage per signature [8].

Now the distinction that everything downstream depends on. The biased case is not the repeat case with weaker numbers. It is a different kind of attack with a different cost profile, and conflating them is the single most common way this topic gets mistold.

Laid out side by side, the contrast is stark:

Repeated nonceBiased nonce
Leak per signatureThe entire nonce (matches another)A few bits, or a fraction of one
Signatures neededTwoMany (hundreds to millions, per bias)
MethodSubtraction and one modular inverseLattice reduction or Fourier analysis (HNP)
ResultCertain and exactStatistical, high-probability
WorkSchoolbook algebra by handSerious computation on aggregated data
Defeated only byDistinct noncesRemoving the bias, not just repeats
Ctrl + scroll to zoom
The biased-nonce attack: many weak equations become one short lattice vector

The lesson lands hard. If even a fraction of one bit of bias, harvested across enough signatures, surrenders the key, then "never literally repeat kk" is nowhere near enough of a rule, and "use a better random number generator" is a treadmill, not a fix. The only question left is how bad this got in real, shipped hardware -- devices built by careful engineers who knew all of this.

5. The Catastrophes in the Wild: ECDSA

The theory is alarming; the field results are worse. What follows is the evolution told as a body count, and the number to watch is the leak the attacker needed. It shrinks with almost every entry, from an entire repeated nonce down to a fraction of a single bit, and every generation still won.

The 2010 PlayStation 3 break sits at one end: a constant nonce across all firmware signatures, the maximum possible leak, two signatures sufficient [1]. In 2013 the Android SecureRandom defect produced repeated and predictable signing nonces on mobile devices; because Bitcoin wallets sign transactions with ECDSA, attackers drained the vulnerable ones [16]. Google's own writeup traced the root cause to improper initialization of the underlying PRNG in the Java Cryptography Architecture [17]. The often-repeated figure of roughly 55 BTC stolen in the 2013 Android incident comes from secondary news reporting [18]. The primary bitcoin.org advisory [16] names the flaw and the affected wallet apps but states no loss total. Treat the number as reported, not official.

Then the leak starts shrinking. Minerva (2020) attacked real smart cards and cryptographic libraries that leaked the bit-length of the nonce through timing -- a whisper of bias, not a repeat -- and recovered keys from "just 500 signatures for simulated leakage data, 1200 for real cryptographic library data, and 2100 for smartcard data" [19].

TPM-Fail (disclosed 2019, published at USENIX Security 2020) turned a timing side channel in Intel's firmware TPM (CVE-2019-11090) and an STMicroelectronics TPM (CVE-2019-16863) into nonce-bit leakage. It recovered an ECDSA key from the Intel fTPM in 4 to 20 minutes and, remotely, "the authentication key of a virtual private network (VPN) server in 5 hours" [20] [21].

LadderLeak (2020) then broke ECDSA with less than one bit of nonce leakage per signature, exploiting a Montgomery-ladder side channel in OpenSSL [8], a result published at ACM CCS 2020 [22]. And in 2024, PuTTY's use of P-521 exposed a structural bias so clean it needs almost no data at all (CVE-2024-31497) [23].

"The first 9 bits of each ECDSA nonce are zero. This allows for full secret key recovery in roughly 60 signatures." -- the PuTTY P-521 disclosure [23]

Sixty signatures. An attacker who had watched roughly sixty SSH handshakes, or collected sixty signed Git commits, could reconstruct the user's private key. The affected PuTTY versions ran from 0.68 through 0.80 (fixed in 0.81), and the same biased generator shipped in FileZilla, WinSCP, TortoiseGit, and TortoiseSVN [23]. Collect them into one table and the trend is impossible to miss:

YearTargetRepeat or biasLeak per signatureSignatures neededSource
2010Sony PS3 firmwareRepeat (constant k)The entire nonce2[1]
2013Android Bitcoin walletsRepeat / predictable kNonce reused or guessableA few[16] [17]
2020Minerva (cards, libraries)Bias (nonce bit-length)Timing reveals length500 to 2100[19]
2019-2020TPM-Fail (Intel, STMicro TPMs)Bias (timing)Nonce high bits via timingMany[20] [21]
2020LadderLeak (OpenSSL ladder)Bias (sub-bit)Less than one bitMany[8]
2024PuTTY P-521 (CVE-2024-31497)Bias (structural)First 9 bits fixed at zero~60[23]
Ctrl + scroll to zoom
The shrinking-leakage arc: each generation exploited less and still recovered the key

Every entry above is a signature scheme bleeding out its private key through the nonce. You would be forgiven for thinking this is an ECDSA problem. It is not. The exact same structural flaw -- one number that must be used once and is fatal on reuse -- was hiding inside a completely different primitive, the cipher that protects most of the traffic on the modern web.

6. The Other Primitive: AES-GCM's Forbidden Attack

Different math, a different decade, a different threat model -- and the exact same fatal dependency on one number used once. The puzzle here is sharper: AES-GCM's nonce is public, so how can reusing a value the attacker already knows leak a forgery key? The answer is Antoine Joux's forbidden attack, and it mirrors the signature story beat for beat.

Recall the tag from Section 2: T=EK(J0)GHASHH(A,C)T = E_K(J_0) \oplus \mathrm{GHASH}_H(A, C), where H=EK(0128)H = E_K(0^{128}). Two facts about that formula are load-bearing. First, HH depends only on the key, so it is fixed for the whole life of that key. Second, EK(J0)E_K(J_0) depends only on the key and the nonce, through the pre-counter block J0J_0. Reuse the nonce and EK(J0)E_K(J_0) comes back identical.

GHASH subkey (H)

The secret 128-bit value H=EK(0128)H = E_K(0^{128}) -- AES applied to the all-zero block -- that keys GCM's polynomial authenticator over GF(2128)\mathrm{GF}(2^{128}). It never changes for a given key, and recovering it lets an attacker forge authentication tags at will.

Now reuse one (key,IV)(\text{key}, \text{IV}) pair on two messages. Two things break, and they break separately.

The confidentiality break, from a single collision. GCM encrypts with counter mode: the ciphertext is the plaintext XORed with a keystream generated from J0J_0. Same key, same IV means the same J0J_0, means the same keystream. So for two messages encrypted under the reused pair, CC=PPC \oplus C' = P \oplus P'. The keystream cancels and the XOR of the two plaintexts falls out immediately, from just one collision, with no further work. If the attacker knows or guesses one plaintext, the other is fully revealed. Here is that leak as runnable code:

JavaScript A reused (key, IV) leaks the XOR of two plaintexts
// Reuse one (key, IV) in a keystream mode -> C XOR C' leaks P XOR P'.
// GCM encrypts with AES-CTR: same (key, IV) reproduces the SAME keystream.
function xor(a, b) { return a.map((x, i) => x ^ b[i]); }
const bytes = s => Array.from(new TextEncoder().encode(s));
const hex = a => a.map(x => x.toString(16).padStart(2, '0')).join('');

// A fixed keystream stands in for AES-CTR(key, IV): identical for both messages.
const keystream = [0x9e,0x37,0x5a,0xc1,0x02,0xbb,0x44,0xd0,0x71,0x6f,0x88,0x2a];

const P1 = bytes('transfer=10 ').slice(0, keystream.length);
const P2 = bytes('transfer=9999').slice(0, keystream.length);

const C1 = xor(P1, keystream);   // ciphertext 1
const C2 = xor(P2, keystream);   // ciphertext 2, SAME keystream

// Attacker never sees the key or keystream -- only C1 and C2:
const leak = xor(C1, C2);        // == P1 XOR P2, the keystream cancels
console.log('C1 XOR C2 :', hex(leak));
console.log('P1 XOR P2 :', hex(xor(P1, P2)), '(identical -> keystream is gone)');

// If the attacker also knows P1, then P2 falls out immediately:
console.log('recover P2:', new TextDecoder().decode(new Uint8Array(xor(leak, P1))));

Press Run to execute.

The authenticity break, from the tag difference. This is Joux's contribution. Write the two tags under the reused pair and XOR them. The identical blind EK(J0)E_K(J_0) cancels exactly:

TT=GHASHH(A,C)GHASHH(A,C)T \oplus T' = \mathrm{GHASH}_H(A, C) \oplus \mathrm{GHASH}_H(A', C')

Every block of A,C,A,CA, C, A', C' is observable on the wire, and GHASHH\mathrm{GHASH}_H is a polynomial in HH over GF(2128)\mathrm{GF}(2^{128}) with those blocks as coefficients. So the right-hand side is a known polynomial in the one unknown HH, and it equals the observed left-hand side. Move everything to one side and you have a polynomial equation whose roots are candidate values for HH; factoring it over GF(2128)\mathrm{GF}(2^{128}) yields that candidate set [2].

Recover HH and, since EK(J0)=TGHASHH(A,C)E_K(J_0) = T \oplus \mathrm{GHASH}_H(A, C) falls out too, the attacker can compute a valid tag for any ciphertext they like under that nonce. That is a universal forgery.

Forbidden attack

Antoine Joux's 2006 attack on GCM: reusing a (key,IV)(\text{key}, \text{IV}) pair cancels the tag's EK(J0)E_K(J_0) blind, turning the difference of two tags into a known polynomial over GF(2128)\mathrm{GF}(2^{128}) whose roots are candidates for the subkey HH. The name reflects that GCM's unique-IV rule is not a suggestion -- breaking it is forbidden [2].

Ctrl + scroll to zoom
How IV reuse cancels the tag blind and exposes the GHASH subkey

This is not confined to whiteboards. In 2016 the Nonce-Disrespecting Adversaries team scanned live TLS and "identified 184 HTTPS servers repeating nonces, which fully breaks the authenticity of the connections" [3]. Joux's result is his 2006 public comment to NIST, whose embedded document title reads "Authentication Failures in NIST version of GCM" [2]. It is sometimes miscited as IACR ePrint 2006/187 -- but that number is a different paper, on HMAC and NMAC, by Kim, Biryukov, Preneel, and Hong [24]. Cite the NIST comment, not the ePrint. These were production HTTPS endpoints, not lab toys, and their nonce reuse let anyone forge authenticated records against them. The canonical live-TLS evidence for GCM nonce reuse is that paper [3], not CVE-2016-0270, which concerns IBM Domino rather than OpenSSL. If you see that CVE cited as the OpenSSL GCM-reuse bug, it is a misattribution.

Two primitives, one disease: a once-per-operation number that is death on reuse. If the flaw is structural rather than a coding slip, then "be more careful with your randomness" cannot be the cure -- Section 5 already showed that treadmill has no end. The fix has to be architectural. What would that even look like?

7. Make the Number Deterministic

The cure for a randomness disaster turned out to be less randomness. That sentence should feel wrong -- we have spent five sections watching bad randomness destroy keys, so surely the answer is better randomness. It is not, and seeing why is the moment the whole subject clicks into place.

Go back to what actually failed. The signing equation needs a kk that is unique and unpredictable. Every real break came from the runtime source of that kk: a constant, a repeated PRNG output, a biased generator, a timing leak. So Thomas Pornin's RFC 6979 asks a disarming question -- what if we never draw kk from a runtime source at all? Instead, derive it, deterministically, from two things the signer already holds: the private key and the message [4].

Deterministic signature

A signature whose per-message nonce is computed as a pseudorandom function of the private key and the message, using no runtime randomness at all. The same (key,message)(\text{key}, \text{message}) pair always yields the same nonce, and therefore the same signature. RFC 6979 specifies this for (EC)DSA; EdDSA builds it into the scheme [4] [5].

Concretely, RFC 6979 runs an HMAC-based deterministic random bit generator, seeded from the private key xx and the message hash, and rejection-samples its output into the valid range [1,n1][1, n-1]. The two helper encodings simply turn the key and the hash into fixed-width byte strings so the HMAC has well-defined inputs:

h  = H(message)                              # hash the message
V  = 0x01 0x01 ... 0x01                       # hlen bytes of 0x01
K  = 0x00 0x00 ... 0x00                       # hlen bytes of 0x00
K  = HMAC(K, V || 0x00 || int2octets(x) || bits2octets(h))
V  = HMAC(K, V)
K  = HMAC(K, V || 0x01 || int2octets(x) || bits2octets(h))
V  = HMAC(K, V)
loop:
    T = ""                                     # accumulate qlen bits of output
    while bitlen(T) < qlen:                    # one HMAC block if qlen <= hlen; more if longer
        V = HMAC(K, V);  T = T || V
    k = bits2int(T)
    if 1 <= k <= n-1:  return k               # in range -> use it
    K = HMAC(K, V || 0x00);  V = HMAC(K, V)    # else reseed and retry

Look at what this buys. The generator is seeded by the private key and the message, and nothing else, and two consequences close the generation side of the Part-A attack surface.

The repeat case dies because two different messages produce two unrelated nonces, while the same message reproduces the same signature harmlessly -- there is no runtime generator whose collision could hand you a shared kk. The bias case dies wherever the bias was born in a generator: with no runtime generator in the loop, there is nothing to skew and no entropy pool to under-initialize. Every Section-5 break that lived in the generator -- the repeated kk on the PS3, the predictable kk from a weak SecureRandom -- has simply been removed from the design, because there is no generator left to fail.

Deterministic signers "do not need access to a source of high-quality randomness." -- RFC 6979 [4]

And the compatibility story is almost too good: a verifier cannot even tell. The verification equation is unchanged, because a signature is still just a valid (r,s)(r, s) pair; only the signer's method of choosing kk changed. Deployments can switch to deterministic signing unilaterally. You do not have to take the "same input, same output" claim on trust either:

JavaScript Deterministic k: same message gives the same nonce, a different message gives an unrelated one
// Deterministic nonce k = PRF(private key, message).
// Real RFC 6979 uses HMAC-DRBG; this toy uses a small deterministic mixer
// only to show the SHAPE: same (key,msg) => same k; different msg => unrelated k.
const MASK = (1n << 64n) - 1n;
const n = (1n << 61n) - 1n;              // toy prime modulus, k in [1, n-1]
function rotl(x, r) { return ((x << r) | (x >> (64n - r))) & MASK; }
function prf(key, msg) {                  // deterministic, consults no RNG
let h = 1469598103934665603n;           // 64-bit offset basis
for (const ch of (key + '|' + msg)) {
  h = (h ^ BigInt(ch.charCodeAt(0))) & MASK;
  h = (h * 1099511628211n) & MASK;       // FNV-style multiply
  h = rotl(h, 13n) ^ (h >> 7n);          // extra diffusion so 1 char avalanches
}
return (h % (n - 1n)) + 1n;              // map into [1, n-1]
}
const sk = 'private-key-0xA1B2';
console.log('k(pay Bob 10) :', prf(sk, 'pay Bob 10').toString());
console.log('k(pay Bob 10) :', prf(sk, 'pay Bob 10').toString(), '<- identical, no RNG consulted');
console.log('k(pay Bob 11) :', prf(sk, 'pay Bob 11').toString(), '<- unrelated');
console.log('No source of runtime randomness was consulted.');

Press Run to execute.

The same idea has a sibling that was born deterministic. EdDSA, and its popular instantiation Ed25519, does not bolt determinism on -- it designs the runtime randomness out from the start, computing its per-signature secret as a hash of a key-derived prefix and the message [5]. That is why Ed25519 has no separate "use RFC 6979" mode: there is no runtime nonce anywhere in the scheme to bias or repeat. Determinism is not an option you enable; it is the definition.

Standards bodies followed the evidence: FIPS 186-5, the current US signature standard, now approves deterministic ECDSA "as specified in IETF RFC 6979" [25] [26]. There is even a quiet operational bonus. A deterministic signer is testable: you can ship known-answer test vectors and check byte-for-byte that an implementation is correct, which a randomized signer can never offer.

The fix for a randomness failure was to remove the randomness. Derive the nonce from the private key and the message, and there is no runtime generator left to repeat or bias -- both failure modes vanish together.

Determinism looks like a clean, total victory. It is narrower than that, and the boundary matters. What it closes is the generation side of Part A. It does nothing for the usage side: recall that Minerva, TPM-Fail, and LadderLeak never touched a generator -- they read the nonce's leading bits out of the timing of the scalar multiplication kGk \cdot G, and that leak is present no matter how kk was chosen [19] [20] [8]. Determinism fixes generation, not usage; the defense against that class is a constant-time scalar multiplication, a separate discipline that RFC 6979 neither provides nor promises. Worse, determinism can even add exposure: by making signing perfectly repeatable, we hand a fault-injection attacker a perfectly repeatable target, a hazard RFC 6979's own security considerations acknowledge [4]. If Go's standard library knows this well enough to refuse pure determinism on purpose, we had better find out what it is afraid of.

8. The Catch, and the Hedge

Here is a fact that should stop you: Go's standard library signs ECDSA non-deterministically on purpose, and its source code says so in a comment. After seven sections arguing that runtime randomness is the enemy, one of the most widely used standard-library signers refuses to remove it. That is not carelessness. It is a second threat model.

Determinism closed the randomness door, but it opened a different one. A deterministic signer computes the same signature every time for a given input, which means an attacker who can run it twice on the same message gets two identical computations to compare -- and comparison is exactly the lever a fault attack pulls.

Differential fault analysis (DFA)

An attack that induces a hardware fault -- a voltage glitch, a clock glitch, a laser pulse -- during a computation, then compares the faulty output against a correct one to solve for the secret. Against a deterministic signer the attacker can obtain a correct signature and a faulted signature for the identical input, which is precisely what makes the difference exploitable.

This is not hypothetical. Aranha, Orlandi, Takahashi, and Zaverucha proved that de-randomized Fiat-Shamir schemes -- EdDSA among them -- are vulnerable to differential fault attacks [27]. And the standard itself agrees: FIPS 186-5 warns that fault attacks are "of particular concern for ... deterministic signature schemes, as well as embedded or IoT devices and smartcards" [26]. The very property that made determinism testable and repeatable -- same input, same output -- is what hands a fault attacker a fixed target to hammer.

The resolution is not to retreat to randomized signing, which reintroduces every repeat and bias failure. It is to take a small step back toward randomness, on purpose and in a controlled way: hedged signatures.

Hedged signature

A signature whose nonce is derived from the private key, the message, and a fresh random value rr: k=H(sk,m,r)k = H(sk, m, r). If the random source fails, the construction degrades to the deterministic -- still safe -- case. If a fault is injected, the fresh rr means the signer is no longer a fixed, replayable target.

Read that definition twice, because it is the whole trick. Hedging is not "randomized signing with extra steps." It is a design that is safe whichever thing goes wrong. Lose your entropy source entirely and you fall back to RFC 6979's determinism, which we already proved kills repeat and bias. Keep your entropy and you also get a moving target that defeats the fault attack determinism exposed. The randomness is present but no longer load-bearing.

"Signatures generated by this package are not deterministic, but entropy is mixed with the private key and the message, achieving the same level of security in case of randomness source failure." -- Go crypto/ecdsa [28]

That is why Go hedges by default, and it is not alone. BoringSSL's FIPS module passes "a SHA512 hash of the private key and digest as additional data into the RBG ... a hardening measure against entropy failure" [29]. RFC 6979 itself sanctions hedged variants in its Section 3.6 [4], and FIPS 186-5 specifies an "Extra Random Bits" method that draws a nonce at least 64 bits longer than needed so any statistical bias becomes negligible [26].

The honest caveats: hedging still consumes some entropy, and its security proofs cover specific fault classes rather than all conceivable faults. It is a well-chosen trade, not a free lunch.

The right mental model is three parallel choices selected by threat model, not a podium with one winner:

PropertyRandomizedDeterministic (RFC 6979 / EdDSA)Hedged
RNG needed at signing timeFullNoneSome (not load-bearing)
Immune to repeatsNo (RNG can collide)YesYes
Immune to biasNoYesYes
Resists fault injectionYes (moving target)No (fixed target)Yes
Known-answer test vectorsNoYesNo
StandardizedYesYes (RFC 6979, FIPS 186-5)Yes (RFC 6979 3.6; FIPS 186-5)
Shipped by default inLegacy codeMany librariesGo crypto/ecdsa, BoringSSL FIPS
Best whenRarely the right pickNo fault threat in scopeHardware, embedded, smartcard, HSM

So the signature side does not settle on a single champion. It settles on a matched set of choices, each correct for a different adversary. That is a satisfying place to land -- but it is only half the patient. What is the symmetric-encryption analogue for the cipher we left bleeding in Section 6?

9. Fixing the Cipher: Nonce-Misuse-Resistant AEAD

The signature fix was "derive the number." The cipher's fix rhymes: derive the IV from the message itself, so that the worst a repeat can leak is the fact that two messages were byte-for-byte identical. Same instinct, symmetric setting.

The idea predates AES-GCM-SIV. Phillip Rogaway and Thomas Shrimpton gave it a provable-security treatment in 2006, defining deterministic authenticated encryption and the Synthetic IV construction that realizes it [30] [31]. It was standardized as AES-SIV in RFC 5297 [32].

Synthetic IV (SIV)

An initialization vector computed from the message -- together with the key and associated data -- rather than drawn at random. Because the IV is a function of the plaintext, two different plaintexts get different IVs automatically, and only byte-identical messages ever collide.

Nonce-misuse-resistant AEAD (MRAE)

An authenticated cipher that, if a nonce is ever repeated, leaks at most whether two identical (key,nonce,plaintext,associated data)(\text{key}, \text{nonce}, \text{plaintext}, \text{associated data}) inputs were the same -- never the key, never arbitrary plaintext. Reuse degrades it gracefully rather than catastrophically.

The modern instantiation is AES-GCM-SIV (RFC 8452) [6]. It computes a keyed hash of the entire plaintext and associated data using POLYVAL, and folds that into a synthetic IV that doubles as the authentication tag; the synthetic IV then seeds ordinary AES-CTR encryption. POLYVAL is a little-endian relative of GHASH, chosen deliberately so AES-GCM-SIV can reuse the same carry-less multiplication hardware that already accelerates AES-GCM. The parallel to GCM is by design, not coincidence.

Two more refinements matter: fresh message-authentication and message-encryption keys are derived per nonce from the master key, which also pushes back the birthday bound that limits plain GCM and raises the safe message limit to roughly 2502^{50} per key [33]. The price is structural and unavoidable: because the tag depends on the whole plaintext, you cannot emit the first ciphertext byte until you have read the last plaintext byte. AES-GCM-SIV is inherently two-pass and not online.

Ctrl + scroll to zoom
The AES-GCM-SIV pipeline: the tag is synthesized from the whole plaintext, then seeds encryption

Now state precisely what "misuse-resistant" earns you, because the phrase invites overclaiming. On a nonce repeat, AES-GCM-SIV discloses only whether the two messages "were equal or not," which RFC 8452 identifies as "the minimum amount of information that a deterministic algorithm can leak" [6]. Compare that to Section 6, where a single GCM repeat surrendered P1P2P_1 \oplus P_2 and set up universal forgery. The SIV construction converts a catastrophe into a whisper.

On nonce reuse, a misuse-resistant AEAD discloses only "whether the messages were equal or not ... the minimum amount of information that a deterministic algorithm can leak." -- RFC 8452 [6]

There is a parallel path worth knowing, though it solves a slightly different problem. XChaCha20-Poly1305 extends the nonce to 192 bits, which makes random nonce selection collision-safe and lets systems stay stateless without a counter [34]. That is genuinely useful, but it is not true misuse resistance: an exact nonce repeat still breaks Poly1305 the way any keystream reuse does. A big nonce makes accidental collisions astronomically unlikely; it does not make a deliberate repeat safe. Collect the options:

SchemePasses / onlineOn nonce reuseMisuse-resistant?Nonce sizeNotes
AES-GCM1 pass, onlineCatastrophic (Section 6)No96-bitFastest with a reliable unique counter
AES-GCM-SIV2 pass, not onlineLeaks only message equalityYes96-bitPOLYVAL and per-nonce keys [6]
AES-SIV2 pass, not onlineLeaks only message equalityYesVector inputDeterministic key-wrap [32]
XChaCha20-Poly13051 pass, onlineRandom reuse unlikely; exact reuse breaksNo192-bitStateless random nonces [34]

Two families, one move. On the signature side we stopped trusting runtime randomness by deriving the number; on the AEAD side we stop trusting it by making a repeat non-catastrophic. It feels, at last, like the problem is solved. It is not -- and the reasons are not missing features anyone can build. Some of them are walls that no amount of engineering can move.

10. Theoretical Limits and the Open Frontier

Some of the walls we keep hitting are not missing features that a cleverer engineer will one day supply. They are proofs that you cannot have everything at once.

Those two impossibilities explain the shape of everything in Sections 7 through 9. AES-GCM-SIV is two-pass because it has to be. Hedged signatures exist because determinism alone cannot cover the fault case. We did not fail to find the one perfect design; the one perfect design is provably not there.

A third limit is epistemic, and it is the quiet engine under this entire article.

And the biased-nonce frontier is still descending: LadderLeak's sub-one-bit result is the current floor, not a proven bottom [8]. The theoretical minimum bias that remains exploitable is an open question, and history says to bet on "smaller than you think."

Then there is the genuinely open ground, where the same disease is re-emerging one abstraction level up. In threshold and multi-party ECDSA, several parties must jointly produce a nonce that is unbiased and secret from all of them, even when some participants misbehave. That is the Hidden Number Problem wearing a new coat: get the joint nonce generation subtly wrong and the biased-nonce attacks come straight back [35]. On the AEAD side, none of the four ciphers we surveyed is key-committing, and that gap is exploitable.

Committing AEAD

An authenticated cipher whose ciphertext binds to exactly one key, so it cannot be decrypted to a different valid plaintext under a different key. None of AES-GCM, AES-GCM-SIV, AES-SIV, or XChaCha20-Poly1305 is key-committing, which is precisely what enables partitioning-oracle attacks.

Julia Len, Paul Grubbs, and Thomas Ristenpart showed that this non-committing property turns certain systems into partitioning oracles that recover passwords and keys [36]. There is no drop-in standard for committing AEAD yet -- an active research front. It is worth being precise about what is not open, though: AES-GCM-SIV and AES-SIV already sit exactly at the minimum-leakage lower bound for the misuse case, because "leaks only equality" is provably optimal for any deterministic scheme [6]. That specific gap is closed; you cannot do better, and you do not need to.

Step back and the emotional arc completes. We began thinking nonce reuse was sloppy hygiene, discovered it was a cliff, thought determinism sealed the cliff, learned determinism opened a fault door, and now find that some of the remaining doors are welded shut by theorems while others open onto genuinely unexplored rooms. None of that theory, however, changes what an engineer should actually do on Monday morning. After all of it, what do you type?

11. What a Practitioner Does Today

Everything above collapses into a decision tree that fits on an index card. You do not need to re-derive Joux's polynomial in a code review; you need two questions for signing and two for encryption.

For signing: for any (EC)DSA or DSA signer, derive the nonce with RFC 6979 or a hedged variant rather than drawing it at runtime [4]. For greenfield systems, prefer Ed25519, which is deterministic by construction [5]. If fault injection is a realistic threat -- smart cards, HSMs, IoT silicon an attacker can hold -- hedge, so an entropy failure degrades to safe determinism and a glitch still faces a moving target [27] [29] [28]. And never compute a nonce as rand() mod n from a raw PRNG without the anti-bias margin FIPS 186-5 specifies as Extra Random Bits [26]. On hardware whose timing an attacker can measure -- smart cards, TPMs, co-located VMs -- pair all of this with a constant-time scalar multiplication: RFC 6979 fixes how kk is generated, not how it is used, so the Minerva, TPM-Fail, and LadderLeak timing leaks close only when kGk \cdot G itself runs in constant time [19] [20] [8].

For AEAD: if you can guarantee a unique nonce -- a reliable, non-resetting counter -- AES-GCM is the fastest choice, provided you cap invocations per key against the birthday bound and rekey before you approach it [12] [6]. If nonce uniqueness is even slightly uncertain -- multiple writers sharing a key, VM snapshots that replay state, forked or stateless workers -- reach for AES-GCM-SIV [6] or the 192-bit-nonce XChaCha20-Poly1305 [34]. For deterministic key-wrapping, AES-SIV is purpose-built [32].

Ctrl + scroll to zoom
The signing and AEAD decision tree, small enough for an index card

The same choices read cleanly as a do-and-do-not table:

SituationCall thisNever this
Signing, generalRFC 6979 deterministic or hedgedrand() mod n from a raw PRNG
Signing, greenfieldEd25519Home-rolled DSA nonce logic
Signing, hardware or embeddedHedged (key, message, entropy)Pure determinism on a fault-exposed device
Signing, measurable hardwareConstant-time scalar multiplicationVariable-time scalar multiplication an attacker can time
AEAD, reliable counterAES-GCM, capped per key and rekeyedAES-GCM past its invocation limit
AEAD, uncertain uniquenessAES-GCM-SIV or XChaCha20-Poly1305Plain AES-GCM with hopeful nonces
Deterministic key-wrapAES-SIV (RFC 5297)A data-plane GCM key reused for wrapping
A ten-second test for whether your signer is deterministic

Sign the same message twice, with the same key, and compare the two signatures. If they are byte-for-byte identical, the signer is deterministic (RFC 6979 or Ed25519). If they differ, it is randomized or hedged. Ed25519 in most libraries will match exactly; Go's crypto/ecdsa will not, by design. That one comparison tells you which row of the Section 8 table you are standing in -- and whether an entropy failure at runtime would be survivable.

Two rules for two primitives, resting on a single instinct. That instinct is strong enough to design around -- but a handful of persistent myths still surface in code review and threat models, and each one hides a real misunderstanding of the mechanism. Let us dismantle them one at a time.

12. Frequently Asked Questions

Nonce reuse, misconceptions corrected

Does a single biased signature leak my key?

No, and this distinction matters more than almost anything else here. A repeated nonce leaks the key from two signatures with certainty, through the subtraction in Section 3. A biased nonce is statistical: each signature is one noisy equation, and recovery needs many of them aggregated by a lattice or Fourier reduction [7] [8]. One biased signature on its own leaks nothing you can use. "One biased signature reveals your key" is the single most common misstatement in this area.

Is deterministic ECDSA always safer?

Not against every adversary. Determinism removes the repeat and generation-side bias failures completely (it does not stop a side-channel leak of kk during the scalar multiplication kGk \cdot G, which needs a constant-time implementation, not determinism), but it turns the signer into a fixed, replayable target for differential fault analysis -- proven for de-randomized Fiat-Shamir schemes including EdDSA [27], and flagged by FIPS 186-5 as a special concern for deterministic schemes on embedded and smartcard devices [26]. That is exactly why hedged signatures exist.

Does AES-GCM-SIV make nonce reuse free?

No. It degrades gracefully instead of catastrophically. On a repeat it discloses only whether two messages were identical -- the provable minimum for any deterministic scheme -- never the key and never arbitrary plaintext [6]. "Graceful" is not "free." Do not reuse nonces on purpose in the belief that the SIV mode makes it costless.

Is a repeated GCM nonce instantly full key recovery?

No, and precision matters. A single collision instantly leaks P1P2P_1 \oplus P_2 and destroys confidentiality [2]. Recovering the authentication subkey HH is a separate step: one collision yields a set of candidate roots, and pinning HH uniquely generally needs two or more collisions [2]. Live TLS servers doing this were found forgeable in 2016 [3], but the mechanism is "confidentiality gone at once, forgery after enough collisions," not "one reuse equals the key."

Why not just fix the RNG or add more entropy?

Because you cannot certify unpredictability, only fail to falsify it -- and sub-bit bias is still fatal across enough signatures. LadderLeak won with less than one bit of leakage [8]. Hardening the generator raises the bar; it does not change the structure. Deriving the number does.

I use random 96-bit GCM nonces -- am I safe?

Only within the birthday bound, and only if uniqueness genuinely holds. Random 96-bit nonces start colliding near 2482^{48} messages, which is why usage caps per key exist [6]. Worse, multi-writer keys, VM clones, and process forks silently re-emit the same nonce no matter how carefully you generated it. If uniqueness is uncertain, switch to AES-GCM-SIV [6] or XChaCha20-Poly1305's 192-bit nonce [34]; this reuse has been observed in the wild [3].

Do post-quantum signatures fix this?

No. Lattice- and Fiat-Shamir-based post-quantum signatures inherit the same sensitivity to per-signature randomness; several are precisely the de-randomized Fiat-Shamir schemes shown vulnerable to fault attacks [27]. Migrating to post-quantum cryptography re-instantiates nonce discipline -- it does not retire it.

13. One Cure for Two Catastrophes

Return to that stage in Berlin in 2010, but now you can see the whole shape of the thing. The PlayStation 3 master key did not fall to a broken cipher or a weak curve; it fell to one number, used twice, and two signatures' worth of subtraction [1]. The same shape swept real Bitcoin wallets when Android's generator repeated nonces [16].

Then the required leak kept shrinking -- bit-length timing on smart cards [19], side channels in TPMs [20], less than a single bit in LadderLeak [8], nine fixed bits and sixty signatures in PuTTY [23] -- and the very same disease surfaced in a cipher, where 184 live TLS servers reusing a GCM nonce were shown forgeable [3].

Every one of those failures shares a single sentence. Both primitives bet everything on a number that had to be unique and unpredictable exactly once, and both collapsed the moment that bet was lost. And the cures share a single sentence too. Deterministic signing derives the number from the key and the message so there is nothing left to repeat or bias [4], while a constant-time scalar multiplication closes the side-channel leaks that determinism never touched; hedged signing keeps a sliver of entropy so a fault has no fixed target [27]; misuse-resistant encryption derives the IV from the message so a repeat leaks only that two messages matched [6].

Two primitives, one disease, one cure: stop trusting runtime randomness for the once-per-operation number. Derive it, or make a repeat non-catastrophic. Everything else in this article is a footnote to that sentence.

Part 2 of this series taught the two ways randomness betrays you; this was the promised descent into what those betrayals actually cost and how the field designed them away. The punchline you were promised at the start has been earned line by line: in cryptography, reusing one number can cost you everything -- so build systems that never require you to trust yourself to use it only once.

Study guide

Key terms

Signing nonce (k)
The per-signature secret scalar in (EC)DSA; it must be unique, secret, and unpredictable, exactly once per key.
GCM nonce (IV)
The per-message value in AES-GCM; it must be unique under a given key, though it may be public.
Repeat vs. bias
A repeated nonce leaks the key from two signatures with certainty; a biased nonce is statistical and needs many signatures.
Hidden Number Problem (HNP)
Recovering a secret from many samples that each reveal a few bits of a related product mod n; the frame for biased-nonce attacks.
GHASH subkey (H)
The secret AES-of-zero value that keys GCM's polynomial authenticator; recovering it enables universal forgery.
Forbidden attack
Joux's GCM attack: reusing an IV cancels the tag blind, exposing a polynomial whose roots are candidates for H.
Deterministic signature
A signature whose nonce is a pseudorandom function of the key and message, using no runtime randomness (RFC 6979, EdDSA).
Hedged signature
A nonce derived from key, message, and fresh entropy; safe if the RNG fails and against fault injection.
Nonce-misuse-resistant AEAD
An AEAD that on nonce reuse leaks at most message equality, never the key or arbitrary plaintext (AES-GCM-SIV, AES-SIV).

References

  1. bushing, marcan, & sven (2010). Console Hacking 2010: PS3 Epic Fail (27C3). https://media.ccc.de/v/27c3-4087-en-console_hacking_2010 - fail0verflow's 27C3 disclosure of the PlayStation 3 constant-nonce ECDSA break.
  2. Antoine Joux (2006). Authentication Failures in NIST Version of GCM. https://csrc.nist.gov/csrc/media/projects/block-cipher-techniques/documents/bcm/comments/800-38-series-drafts/gcm/joux_comments.pdf - Joux's forbidden attack on GCM: reusing a (key, IV) cancels the tag blind, turning the tag difference into a polynomial whose roots are candidate subkeys H.
  3. Hanno Böck, Aaron Zauner, Sean Devlin, Juraj Somorovsky, & Philipp Jovanovic (2016). Nonce-Disrespecting Adversaries: Practical Forgery Attacks on GCM in TLS. https://eprint.iacr.org/2016/475 - Nonce-Disrespecting Adversaries: 184 live HTTPS servers repeating GCM nonces, which fully breaks the authenticity of the connections.
  4. Thomas Pornin (2013). RFC 6979: Deterministic Usage of the Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA). https://datatracker.ietf.org/doc/html/rfc6979 - Deterministic (EC)DSA nonce via HMAC-DRBG; removes the runtime generator that repeats and biases fail, and sanctions hedged variants in Section 3.6.
  5. Simon Josefsson & Ilari Liusvaara (2017). RFC 8032: Edwards-Curve Digital Signature Algorithm (EdDSA). https://datatracker.ietf.org/doc/html/rfc8032 - EdDSA/Ed25519, deterministic by design; the per-signature secret is a hash of a key-derived prefix and the message, with no runtime randomness.
  6. Shay Gueron, Adam Langley, & Yehuda Lindell (2019). RFC 8452: AES-GCM-SIV: Nonce Misuse-Resistant Authenticated Encryption. https://datatracker.ietf.org/doc/html/rfc8452 - AES-GCM-SIV specification; on nonce reuse it discloses only whether two messages were equal, the provable minimum, using two passes and per-nonce derived keys.
  7. Phong Q. Nguyen & Igor E. Shparlinski (2003). The Insecurity of the Elliptic Curve Digital Signature Algorithm with Partially Known Nonces. https://doi.org/10.1023/A:1025436905711 - Nguyen and Shparlinski prove polynomial-time ECDSA key recovery from just a few leaked nonce bits per signature.
  8. Diego F. Aranha, Felipe Rodrigues Novaes, Akira Takahashi, Mehdi Tibouchi, & Yuval Yarom (2020). LadderLeak: Breaking ECDSA with Less than One Bit of Nonce Leakage. https://eprint.iacr.org/2020/615 - LadderLeak breaks ECDSA with less than one bit of nonce leakage, exploiting an OpenSSL Montgomery-ladder side channel.
  9. TechSpot (2011). Hacker releases PlayStation 3 root key. https://www.techspot.com/news/41808-hacker-releases-playstation-3-root-key.html - Secondary coverage of geohot's separate January 2011 release of an extracted PS3 root key.
  10. Taher ElGamal (1985). A Public Key Cryptosystem and a Signature Scheme Based on Discrete Logarithms. https://doi.org/10.1109/TIT.1985.1057074 - ElGamal's 1985 signature scheme, which introduced the per-signature secret exponent.
  11. National Institute of Standards and Technology (1994). FIPS 186: Digital Signature Standard (DSS). https://csrc.nist.gov/pubs/fips/186/final - FIPS 186 (1994), the original US DSA standard that carried the per-signature nonce.
  12. Morris Dworkin (2007). NIST SP 800-38D: Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC. https://csrc.nist.gov/pubs/sp/800/38/d/final - NIST SP 800-38D, the GCM/GMAC specification with the normative unique-IV requirement and per-key invocation limits.
  13. Mihir Bellare, Shafi Goldwasser, & Daniele Micciancio (1997). Pseudo-Random Number Generation within Cryptographic Algorithms: The DSS Case. https://doi.org/10.1007/BFb0052242 - Bellare, Goldwasser, and Micciancio show a poorly generated DSA nonce (a linear-congruential generator) breaks the scheme.
  14. Dan Boneh & Ramarathnam Venkatesan (1996). Hardness of Computing the Most Significant Bits of Secret Keys in Diffie-Hellman and Related Schemes. https://doi.org/10.1007/3-540-68697-5_11 - Boneh and Venkatesan introduce the Hidden Number Problem, the framework underneath every biased-nonce attack on (EC)DSA.
  15. Nick Howgrave-Graham & Nigel P. Smart (2001). Lattice Attacks on Digital Signature Schemes. https://doi.org/10.1023/A:1011214926272 - Howgrave-Graham and Smart make the lattice attack practical, recovering keys from partially known (EC)DSA nonces.
  16. Bitcoin.org (2013). Android Security Vulnerability. https://bitcoin.org/en/alert/2013-08-11-android - The bitcoin.org advisory on the 2013 Android SecureRandom weakness that produced repeated and predictable ECDSA signing nonces.
  17. Alex Klyubin (2013). Some SecureRandom Thoughts. https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html - Google's writeup tracing the Android break to improper initialization of the underlying PRNG in the Java Cryptography Architecture.
  18. The Hacker News (2013). Android Bug Batters Bitcoin Wallets. https://thehackernews.com/2013/08/hacking-bitcoin-android-vulnerability-digital-wallets.html - Secondary news source of the widely repeated roughly 55 BTC loss figure, which is absent from the primary advisory.
  19. CRoCS, Masaryk University (2020). Minerva: The curse of ECDSA nonces. https://minerva.crocs.fi.muni.cz/ - Minerva: nonce bit-length timing leakage recovering ECDSA keys from real smart cards and libraries in hundreds to a few thousand signatures.
  20. Daniel Moghimi, Berk Sunar, Thomas Eisenbarth, & Nadia Heninger (2019). TPM-Fail: TPM meets Timing and Lattice Attacks. https://tpm.fail/ - TPM-Fail: timing side channels in Intel fTPM and an STMicroelectronics TPM that leak ECDSA nonce bits.
  21. Daniel Moghimi, Berk Sunar, Thomas Eisenbarth, & Nadia Heninger (2020). TPM-FAIL: TPM meets Timing and Lattice Attacks (USENIX Security 2020). https://www.usenix.org/conference/usenixsecurity20/presentation/moghimi-tpm - The TPM-Fail paper of record (USENIX Security 2020).
  22. Fabian Bäumer & Marcus Brinkmann (2024). PuTTY: Recovery of NIST P-521 Private Keys (CVE-2024-31497). https://www.openwall.com/lists/oss-security/2024/04/15/6 - The PuTTY P-521 disclosure (CVE-2024-31497): the first nine nonce bits are fixed at zero, enabling full key recovery in roughly 60 signatures.
  23. Jongsung Kim, Alex Biryukov, Bart Preneel, & Seokhie Hong (2006). On the Security of HMAC and NMAC Based on HAVAL, MD4, MD5, SHA-0 and SHA-1. https://eprint.iacr.org/2006/187 - Corrective anchor confirming that ePrint 2006/187 is an HMAC/NMAC paper, not Joux's GCM note.
  24. National Institute of Standards and Technology (2023). FIPS 186-5: Digital Signature Standard (DSS). https://csrc.nist.gov/pubs/fips/186-5/final - FIPS 186-5 landing page recording supersession of FIPS 186-4 and the approval of deterministic ECDSA.
  25. National Institute of Standards and Technology (2023). FIPS 186-5: Digital Signature Standard (DSS), full text. https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf - FIPS 186-5 full text: approves RFC 6979, warns that fault attacks are a special concern for deterministic schemes, and specifies the Extra Random Bits anti-bias method.
  26. Diego F. Aranha, Claudio Orlandi, Akira Takahashi, & Greg Zaverucha (2020). Security of Hedged Fiat-Shamir Signatures under Fault Attacks. https://eprint.iacr.org/2019/956 - Proof that de-randomized Fiat-Shamir schemes, including EdDSA, are vulnerable to differential fault attacks; the case for hedged nonces.
  27. The Go Authors (2024). Go crypto/ecdsa source (go1.22.0). https://raw.githubusercontent.com/golang/go/go1.22.0/src/crypto/ecdsa/ecdsa.go - The Go crypto/ecdsa source, which signs non-deterministically by default by mixing entropy with the private key and the message.
  28. Google (2023). BoringSSL FIPS module: ECDSA nonce hardening (ecdsa.cc.inc). https://github.com/google/boringssl/blob/156c7b75ae9b8c3b3f847acf264f17594c3859fb/crypto/fipsmodule/ecdsa/ecdsa.cc.inc - The BoringSSL FIPS module hardening ECDSA by mixing a SHA-512 hash of the private key and digest into the RBG.
  29. Dan Harkins (2008). RFC 5297: Synthetic Initialization Vector (SIV) Authenticated Encryption Using AES. https://datatracker.ietf.org/doc/html/rfc5297 - AES-SIV: the synthetic-IV construction for deterministic authenticated encryption and key wrapping.
  30. Scott Arciszewski (2020). XChaCha: eXtended-nonce ChaCha and AEAD_XChaCha20_Poly1305 (draft-irtf-cfrg-xchacha-03). https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha-03 - Extended-nonce XChaCha20 draft; a 192-bit nonce makes random-nonce collisions negligible, though it is not true misuse resistance.
  31. Jean-Philippe Aumasson, Adrian Hamelink, & Omer Shlomovits (2020). A Survey of ECDSA Threshold Signing. https://eprint.iacr.org/2020/1390 - A survey of threshold ECDSA signing and the open problem of unbiased joint nonce generation.
  32. Julia Len, Paul Grubbs, & Thomas Ristenpart (2021). Partitioning Oracle Attacks. https://www.usenix.org/conference/usenixsecurity21/presentation/len - Partitioning-oracle attacks that exploit non-committing AEAD to recover passwords and keys.
  33. Phillip Rogaway & Thomas Shrimpton (2006). A Provable-Security Treatment of the Key-Wrap Problem. https://doi.org/10.1007/11761679_23 - Rogaway and Shrimpton's provable-security treatment of deterministic authenticated encryption and the SIV construction (published version).
  34. Phillip Rogaway & Thomas Shrimpton (2006). Deterministic Authenticated-Encryption: A Provable-Security Treatment of the Key-Wrap Problem. https://eprint.iacr.org/2006/221 - Rogaway and Shrimpton's DAE/SIV paper (ePrint), the foundation of nonce-misuse resistance.
  35. Diego F. Aranha, Felipe Rodrigues Novaes, Akira Takahashi, Mehdi Tibouchi, & Yuval Yarom (2020). LadderLeak: Breaking ECDSA with Less than One Bit of Nonce Leakage (ACM CCS 2020). https://doi.org/10.1145/3372297.3417268 - Peer-reviewed LadderLeak (ACM CCS 2020): venue, DOI, and page range of record.
  36. Shay Gueron, Adam Langley, & Yehuda Lindell (2017). AES-GCM-SIV: Specification and Analysis. https://eprint.iacr.org/2017/168 - AES-GCM-SIV specification and analysis; per-nonce key derivation raises the safe message limit to roughly 2^50.