Heads up: posts on this site are drafted by Claude and fact-checked by Codex. Both can still get things wrong — read with care and verify anything load-bearing before relying on it.
why → how

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.

Security intermediate May 2, 2026 · updated Aug 25, 2026 · 13 min read

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.

the whole arrangement rests on one assumption: the private key is only on the maker’s machines firmware A + signature on every disc firmware B + signature on every disc a page of algebra the private signing key nobody broke into anything Recovered from signatures the manufacturer had already published. the curve is fine, the hash is fine, the key is fine — one variable was not random enough
Once you hold the signing key you can sign your own firmware as if you were the manufacturer, and the console’s chain of trust is over. The mechanism behind the break is embarrassingly small: the same per-signature random value used across two different blobs.

2 · Why one signature is safe

One equation, two unknowns.

a signature is one equation, and it contains two things nobody outside knows s = k⁻¹ · (e + r·d) mod n k — the nonce thrown away after signing both unknown d — the private key never leaves the signer Two unknowns, one equation. Nothing is solvable. the nonce is the blind that hides the private key — and every signature is meant to use a different one
The signing equation has to hide the private key while staying checkable by anyone, so it hides it behind a random blind. The nonce k is that blind, which is why the entire break is just “what happens when the blind stops being different.”

3 · The collapse

A second equation in the same two unknowns.

reuse the nonce on two different messages, and the system stops being underdetermined s₁ = k⁻¹ · (e₁ + r·d) mod n s₂ = k⁻¹ · (e₂ + r·d) mod n s₁ − s₂ = k⁻¹ · (e₁ − e₂) the r·d term cancels k = (e₁−e₂) · (s₁−s₂)⁻¹ mod n the nonce falls out d = (s·k − e) · r⁻¹ mod n and then the private key No quantum computer. No curve break. A modular inverse. and the tell is public: two signatures under one key sharing the same r, on different message hashes a strong signal rather than a proof — k and −k give the same r, and a deterministic signer repeats it on the same message
Subtracting the two signing equations cancels the private-key term, leaving the nonce as the only unknown; once the nonce is known the original equation rearranges straight into the key. It needs nothing the manufacturer hadn’t already published.

4 · The asymmetry, and the fix

Two assumptions, wildly different cost to break.

two assumptions, wildly different cost to break break the curve a mathematical breakthrough break the nonce two signatures and a modular inverse and it doesn’t even need reuse: a merely biased or predictable nonce gives up the key through lattice attacks so the fix takes the random number generator out of the loop RFC 6979 derives the nonce from the private key and the message hash instead of asking for randomness same key and same message always give the same nonce; two different messages give independent-looking ones Ed25519 bakes that in from the start — there is no RNG-shaped hole to fall into.
Determinism removes the generator from the threat model, not the nonce. A signer induced to sign the same message twice while a fault hits one computation can still leak the key, and side channels that leak bits of the nonce still walk back to it. The requirement moved from “trust the RNG every time” to “trust the hash function” — a much sturdier assumption, not an absent one.

5 · Keep this card

The whole thing on one index card.

ECDSA security = hard curve mathematics + a secret, unique, unpredictable nonce ∴ the second is load-bearing on its own — so treat the nonce as a second private key break the first and you need a breakthrough; break the second and you need two signatures
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. Where the framing breaks: unlike a real private key, the nonce is thrown away after one use, and under RFC 6979 it isn’t random at all. It earns the name purely because leaking it costs you just as much.

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:

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

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.

Going deeper