Why ECDSA nonce reuse leaks the private key
ECDSA needs a fresh random number for every signature. Use the same one twice and anyone watching can recover the private key with two lines of algebra — which is exactly how the PS3's master key fell out.
On this page
The picture version
Five pictures for a reader who has never met a signature scheme, following one break: the PlayStation 3’s signing key, recovered from signatures Sony had already shipped.
1 · The problem
The key fell out of signatures that were already public.
2 · Why one signature is safe
One equation, two unknowns.
3 · The collapse
A second equation in the same two unknowns.
4 · The asymmetry, and the fix
Two assumptions, wildly different cost to break.
5 · Keep this card
The whole thing on one index card.
Why it exists
Your phone refuses to install an app that isn’t signed. Your console refuses to boot firmware that isn’t signed. The whole arrangement rests on one assumption you never get asked about: the manufacturer’s private key is only on the manufacturer’s machines. In December 2010, at the 27th Chaos Communication Congress in Berlin, a group calling itself fail0verflow walked on stage and demonstrated that this assumption had failed for the PlayStation 3 — and failed without anyone breaking into Sony. They had recovered Sony’s code-signing private key from signatures Sony had already shipped on every PS3 in the world. Once they had that key, they could sign their own firmware as if they were Sony, and the console’s chain of trust collapsed: homebrew apps, alternate operating systems, and the rest of the jailbreak ecosystem fell out from there. The mechanism behind the break was almost embarrassingly small. Sony’s implementation of ECDSA — the Elliptic Curve Digital Signature Algorithm, the scheme this post is about — reused the same per-signature random value across different firmware blobs, and that’s all it takes.
The wild part isn’t the politics or the jailbreak. It’s that the math of ECDSA is fine. The curve is fine, the hash is fine, the private key is fine. The whole scheme is destroyed by one variable being not-random-enough. This is the cleanest example I know of a recurring lesson in real cryptography: security is usually a constraint on the implementation, not the math.
Why it matters now
ECDSA is everywhere you actually transact value or trust. Bitcoin signs transactions with it (over the curve secp256k1); plenty of other chains use ECDSA, Schnorr, Ed25519, or BLS depending on lineage. Elliptic-curve signatures are standard in platform code-signing pipelines. TLS certificates are issued with ECDSA keys too — Let’s Encrypt, for one, issues them, commonly over the P-256 curve. SSH keys default to Ed25519 in current OpenSSH, with ECDSA still present in plenty of existing keys. Every randomized ECDSA deployment that generates a fresh nonce per signature is one buggy RNG away from the PS3 outcome. (Deterministic ECDSA — see below — and Ed25519 sidestep that risk by construction.)
It has happened repeatedly. The PS3 in 2010 is the famous one. In 2013, Bitcoin Android wallets lost coins after weaknesses in Android’s pseudo-random number generation compromised the randomness those wallets fed into ECDSA signing; both Bitcoin.org and Android’s own security team published alerts that August. The pattern is the same either time: the curve math holds, the randomness fails, the key falls out.
The short answer
ECDSA security = elliptic-curve discrete-log hardness + a secret, unique, unpredictable nonce per signature
Picture to keep: two equations with two unknowns — the private key and the nonce. One signature gives you one equation, so nothing is solvable. Reuse the nonce and the second signature gives you a second equation in the same two unknowns, and a system that was underdetermined becomes a schoolbook simultaneous-equations exercise.
ECDSA pretends to be one equation but is really two assumptions stacked. If
the elliptic-curve discrete log is hard and the per-signature nonce k is
fresh and secret, the scheme is secure. If k is ever repeated across two
signatures with the same private key, the second assumption collapses, and
two signatures plus a few lines of modular arithmetic give up the private
key. The math doesn’t care that the curve is still strong.
How it works
The failure is easier to follow if you know what the signer was trying to
avoid in the first place. The signing equation has to hide the private key
d while still being checkable by anyone — so it hides d behind a random
blind, and every signature uses a different blind. The nonce k is the
blind. Keep that in view, because the entire break is “what happens when the
blind stops being different.”
An ECDSA signature on a message m under private key d (an integer) is a
pair (r, s) computed like this:
- Pick a nonce
k, a random integer in[1, n−1], wherenis the curve order. - Compute the curve point
kG, whereGis the generator. - Set
r = (kG).x mod n— the x-coordinate of that point, reduced modn. (Ifr = 0, retry with a newk.) - Set
s = k⁻¹ · (e + r·d) mod n, wheree = bits2int(Hash(m))— the message hash converted to an integer and truncated to the bit length ofn.
Verification uses only the public key Q = dG, the message, and (r, s). The
private key d never appears in the verifier; the nonce k is thrown away
after signing and is supposed to never appear anywhere again.
Now suppose the signer reuses the same k for two different messages m₁
and m₂ (with e₁ ≠ e₂) — two firmware blobs, say, both signed by Sony and
both sitting on a disc you own. Because r is derived from k alone, both
signatures will share the same r. So a passive observer who collects two
signatures under the same public key and spots a repeated r has a very
strong tell that the nonce repeated. (Strictly, r is only the
x-coordinate, and k and −k land on the same x — so equal r means the
same nonce up to sign, which costs an attacker one extra case to try, not
a failed attack.) From here it’s algebra, and it needs nothing the
manufacturer didn’t already publish.
s₁ = k⁻¹ · (e₁ + r·d) mod n
s₂ = k⁻¹ · (e₂ + r·d) mod n
s₁ − s₂ = k⁻¹ · (e₁ − e₂) mod n ← the r·d term cancels
k = (e₁ − e₂) · (s₁ − s₂)⁻¹ mod n
Subtracting the two signing equations cancels the private-key term, leaving
k as the only unknown. Once k is known, the signing equation rearranges
to give up d directly:
d = (s · k − e) · r⁻¹ mod n
That’s it. No quantum computer, no curve break, no factoring — just a public
observation that two signatures share an r, and a calculator that can do
modular inverses. The whole strength of the elliptic-curve discrete log was
wrapped around the assumption that k was an unknown random number each
time. Reusing k across two different messages is enough to give up the
private key.
It’s actually worse than reuse. If k is merely predictable — drawn from a
weak PRNG, biased toward
small values, or correlated across signatures — there are lattice-based
attacks that recover d from many signatures even when no two k’s are
identical. Same family of failure: the security of ECDSA leans entirely on
k being indistinguishable from uniform random in [1, n−1].
Why this is a property of ECDSA (and DSA), not all signatures
The same defect lives in classical DSA — ECDSA is just DSA over an elliptic curve. RSA signatures are not vulnerable to this particular failure mode (they don’t have a per-signature nonce in the same role; RSA-PSS uses random salt for different reasons). This specific key-recovery algebra also doesn’t apply to symmetric ciphers — though don’t read that as “AES is fine to misuse.” Nonce reuse in AES-CTR XORs two plaintexts together by reusing the same keystream, and in AES-GCM it does that and leaks the authentication key, which lets an attacker forge messages. Different math, same shape of catastrophe. The lesson generalizes: nonces are load-bearing in many primitives, and each scheme has its own way of collapsing when you reuse one.
The fix: stop relying on the RNG
The standard fix has been around since 2013 in the form of
RFC
6979, which specifies deterministic ECDSA: derive k from the private key
and the message hash via
HMAC-DRBG
(seeded from d and Hash(m)) instead of asking the RNG. Same private key
plus same message always yields the same k, but two different messages
yield independent-looking ks, and the secret d is mixed in so an
attacker can’t precompute. This makes nonce reuse structurally impossible
as long as you sign different messages. libsecp256k1, the library Bitcoin Core signs with, derives k this way.
The cleaner answer is to skip ECDSA entirely. EdDSA (Ed25519 is the popular instance) bakes deterministic nonces into the specification itself rather than retrofitting them — there is no RNG-shaped hole to fall into. Current OpenSSH generates Ed25519 keys by default.
Show the seams
- Determinism has its own subtle failure mode. If a deterministic-ECDSA
signer is induced to sign the same message twice but a fault hits one
computation (a glitched bit during signing), an attacker can again get two
signatures with the same
kand different effectiveH(m), recoveringd. Fault-injection attacks against deterministic ECDSA have been demonstrated in academic settings. How often it has been used against deployed hardware in the wild isn’t something there’s a public tally of. - The PS3 specifics, and where they stop. What the 27C3 talk established is clear enough: Sony’s ECDSA implementation produced the same nonce across different signatures, and that was enough to recover the signing key. Why the value was constant — a hardcoded constant, or a generator that never varied — gets described different ways in secondhand accounts, so this post claims only the part the talk demonstrates.
- “Just use a good RNG” is the wrong takeaway. The lesson of RFC 6979 isn’t that RNGs got better; it’s that a signature scheme whose security depends on every signer having a flawless RNG forever is a bad scheme. The fix moved the requirement from “trust the RNG every time” to “trust the hash function” — a much sturdier assumption.
- Detection is asymmetric. A signer can’t easily tell in real time
whether their RNG is betraying them — short of post-hoc scanning their
own signatures for repeated
rs. A passive attacker watching a public ledger (a blockchain, a CT log, a package archive) can scan millions of signatures for repeatedrvalues trivially. The attacker has the easier job.
The mental model: in ECDSA, the nonce k is not a knob, it is a second
private key. Treating it as anything less — letting it leak, letting it
repeat, letting it correlate — gives away the first private key for free.
(Where that framing breaks: unlike a real private key, k is thrown away
after one use and, under RFC 6979, isn’t random at all. It earns the name
purely because leaking it costs you exactly as much.)
You started with ECDSA security = elliptic-curve discrete-log hardness + a secret, unique, unpredictable nonce per signature. What did this post add?
— + the second term is not a supporting condition, it is load-bearing on its own. Break the first assumption and you need a mathematical
breakthrough; break the second and you need two signatures and a modular
inverse. That asymmetry is why RFC 6979 and Ed25519 moved k out of the
RNG’s hands entirely.
Check yourself
Before you go — you’re auditing a hardware wallet. It signs with deterministic ECDSA per RFC 6979, so nonce reuse driven by a failing RNG is removed by construction. Your colleague concludes the nonce is no longer part of the threat model. Where are they wrong?
Answer
Determinism removes the RNG from the threat model, not the nonce. Two
things still bite. First, k is now a deterministic function of the private
key and the message — so any side channel that leaks bits of k during the
k⁻¹ or kG computation (timing, power, EM) still walks back to d, which
is why signing implementations need to be constant-time regardless. Second,
fault injection: glitch the device while it signs the same message twice and
you can get two signatures that share k but differ in the value actually
fed into the equation — the exact condition this whole post is about. The
nonce stays load-bearing; determinism just closes the most common way it
used to fail.
And one more — a chain’s block explorer lets you scan every signature ever published. What would you compute to find compromised keys, and who is in a better position to run that check: the wallets, or a stranger?
Answer
Group signatures by public key and look for two that share an r across
different message hashes. That’s a strong repeated-nonce signal rather than
a proof — the k/−k case above costs an attacker one extra try, and a
deterministic signer legitimately repeats r when it signs the same message
twice — and where it holds, the algebra above turns it into d. This is the shape of the 2013 Android-wallet thefts.
Any individual wallet can audit its own signatures, and should — but the
stranger is better positioned, because the public ledger hands them every
key’s signatures at once, including keys belonging to people who long ago
stopped looking. The asymmetry isn’t that signers are unable to check; it’s
that one scan over aggregated public data finds every victim simultaneously.
That’s the argument for removing the failure mode by construction rather
than monitoring for it.
Famous related terms
- RFC 6979 —
RFC 6979 = ECDSA + k from HMAC-DRBG seeded with (d, H(m))— the standard fix; eliminates the RNG dependency at the source. - EdDSA / Ed25519 —
EdDSA = Edwards curve + deterministic nonce by design— modern signature scheme without ECDSA’s nonce-shaped trapdoor. It’s OpenSSH’s default key type and TLS 1.3 defines it; Signal uses the related XEdDSA/XEd25519 family rather than Ed25519 itself. - Schnorr signatures —
Schnorr ≈ ECDSA's cleaner cousin— same elliptic-curve setting, simpler math, supports key aggregation. Bitcoin added Schnorr (BIP-340) alongside ECDSA in the Taproot upgrade. - Lattice attacks on biased nonces —
lattice attack ≈ many signatures with slightly-biased k → reconstruct d— generalizes nonce reuse: the attacker doesn’t need a collision, just a statistical pattern ink. - Public-key cryptography — the broader setting ECDSA lives inside.
- Signatures vs encryption — why ECDSA is a signature primitive, not encryption-in-reverse.
Going deeper
- RFC 6979, Deterministic Usage of the Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA) (Thomas Pornin, 2013) — the primary source for the one question this post only sketches: exactly how
kis derived when you take the RNG out of the loop. - fail0verflow, Console Hacking 2010 — PS3 Epic Fail, 27C3 (December 2010) — the explainer, and the best answer to “what did this look like from the outside,” since the talk walks the whole chain from observation to signed firmware.
- Nguyen & Shparlinski, The Insecurity of the Elliptic Curve Digital Signature Algorithm with Partially Known Nonces (Designs, Codes and Cryptography, 2003) — the rabbit hole for “what if the nonces never actually repeat, just lean,” which is the version of this attack still finding victims.