45 min read

How Elliptic Curves and Diffie-Hellman Break in Real Life: The Discrete Log Never Fell

No one has solved the discrete log on a strong curve or a 2048-bit group -- yet PS3, Android wallets, TPMs, CurveBall, and Logjam all fell. Here is exactly how.

Permalink

1. Seven Breaks, One Unbroken Problem

On a well-chosen elliptic curve, the best attack anyone has ever fielded against the discrete logarithm is a square-root-time random walk that has barely moved since the 1970s [1][2]. No deployed P-256, Curve25519, or secp256k1 key, and no standard 2048-bit Diffie-Hellman group, has ever had its discrete log solved in public. By every measurement we can make, the mathematics is holding.

And yet. PlayStation 3 consoles were jailbroken [3]. Android Bitcoin wallets were emptied [4]. Tamper-resistant TPMs certified to government standards surrendered their signing keys [5]. Windows accepted forged certificates that chained to a counterfeit authority [6]. Live TLS sessions were downgraded and decrypted in transit [7]. Every one of those systems ran the discrete-log math exactly as specified. The math was never where they broke.

That is the paradox this article resolves, and the resolution fits in one sentence: none of these attacks solved a discrete logarithm. Each attacked a layer the math depends on but does not control. There are exactly three such layers, and they organize everything that follows:

  • The per-signature nonce -- the throwaway secret ECDSA needs for every signature. PS3, Android, Minerva, TPM-Fail, and LadderLeak all landed here.
  • The curve and certificate parameters -- which curve, and whose generator, you are actually talking to. CurveBall landed here.
  • The negotiated strength -- how strong a key exchange two parties agree to use before they exchange anything. Logjam landed here.

The discrete-logarithm assumption protects the private key against being directly computed -- and nothing else. "Nobody solved the discrete log" and "somebody recovered the private key" are not contradictory statements, because the discrete-log problem (genuinely hard) and a discrete-log deployment (a nonce, some parameters, a negotiation) are different things. Every real break in this article lives in the gap between them.

A note on scope. This piece treats the hardness of the elliptic-curve discrete logarithm as a black box: assume it holds, and watch everything around it fail. The structural mathematics of curve choice -- why one curve is weak and another is strong, how the number field sieve and Shor's algorithm actually work -- belongs to a companion article, "How the Discrete Log Would Break: Elliptic Curves, Finite Fields, and Why Curve Choice Is the Weak Part." Here, we assume the strongbox is uncrackable and ask how the key kept getting out anyway.

To see why a hard problem protects so little, you first have to see exactly what it promises -- and what it quietly leaves to the deployment.

2. What the Math Actually Promises

In 1976, Whitfield Diffie and Martin Hellman reduced the ancient problem of exchanging a secret over an open wire to a single piece of hard arithmetic: the discrete logarithm [8]. Two parties each pick a private exponent, exchange public powers of a shared generator, and combine them into a key that an eavesdropper cannot reconstruct without solving for one of those exponents.

Nine years later, Victor Miller and, independently, Neal Koblitz moved the same hard problem onto elliptic curves [9][10]. Koblitz argued the curve version was "likely to be harder than the classical discrete logarithm problem" [10] -- which is why a 256-bit curve buys security that a finite field needs thousands of bits to match. A clean, triumphant origin. So where did the promise leak?

Discrete Logarithm Problem (DLP / ECDLP)

Given a generator G and a public point Q = dG on an elliptic curve (or a base g and g^d in a finite field), recovering the secret integer d is the discrete logarithm problem. The security of ECDSA, ECDH, and Diffie-Hellman rests on the assumption that this recovery is computationally infeasible for well-chosen parameters. It is the one thing the math promises -- and, as we will see, the only thing.

Signatures are where the story starts, because signatures introduce a second secret. The Elliptic Curve Digital Signature Algorithm (ECDSA) signs a message hash z under a long-term private key d by generating a fresh random value k, computing a point kG, taking its x-coordinate as r, and producing:

s=k1(z+rd)modns = k^{-1}\,(z + r\,d) \bmod n

where n is the order of the group. The verifier only ever sees (r, s). The private key d is buried inside, protected by the discrete-log assumption -- nobody can read d off the signature. But look at what else is in that equation.

Per-signature nonce (k)

The k in ECDSA is a nonce: a number used once. It must be secret, statistically uniform, and unique to each signature. It is not the private key, and it is thrown away the instant the signature is produced. It is also the single most load-bearing prerequisite in the whole scheme -- because k and d appear together in one linear equation, anything an attacker learns about k turns directly into knowledge of d.

The discrete-log assumption guards d against being computed from the public key. It says nothing whatsoever about three things the assumption quietly depends on but does not itself enforce:

  1. The nonce k must be secret, uniform, and unique. The math assumes a perfect k and never checks that you supplied one.
  2. The parameters must be the standard, named ones. The math assumes you are on the curve you think you are, with the generator you think you have.
  3. The negotiated strength must not be crippled or shared. The math assumes the group you agreed to use is actually strong.

Each of those is the deployment's responsibility, not the primitive's. And each one became a pillar of failure.

Ctrl + scroll to zoom
The discrete-log assumption protects only against directly computing the key. The three layers it depends on but does not control are where every field break landed.

The curve migration itself is not our subject. Miller (1985) and Koblitz (1987) are mentioned here only to fix the primitive's birth. Whether a particular curve is structurally weak -- anomalous curves, small embedding degrees, the number field sieve, Shor's algorithm -- is the structural mathematics deferred to the companion article. This article assumes the curve is strong and attacks everything around it. The math guards the key against being computed. It says nothing about the key being handed over. Three contracts govern that handover, and each one broke.

3. Three Contracts the Deployment Signs and Never Reads

Every cryptographic deployment signs a contract it never reads. There are three clauses, one for each layer the math leans on, and the fine print on all three is where real products sank.

The nonce contract: k must be fresh

Take the ECDSA signing equation and ask the cruelest possible question: what if k is not unique? Suppose two different messages, with hashes z1 and z2, are signed under the same nonce k. Because r is the x-coordinate of kG, the same k produces the same r in both signatures. Now write them down side by side:

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

Subtract. The rd term is identical in both, so it cancels, and k falls straight out:

s1s2=k1(z1z2),k=z1z2s1s2modns_1 - s_2 = k^{-1}(z_1 - z_2), \qquad k = \frac{z_1 - z_2}{s_1 - s_2} \bmod n

Once you know k, the first equation has exactly one unknown left, and you solve for the private key by hand:

d=s1kz1rmodnd = \frac{s_1\,k - z_1}{r} \bmod n

No lattice. No side channel. No discrete log. Two signatures that share a nonce are two linear equations in two unknowns, and a middle-schooler with modular arithmetic can finish the job.

The contract, then, is strict: k must be secret, statistically uniform, and never reused or partially leaked. Break any word of that clause and the algebra above (or its statistical cousin, later) takes your key.

The parameter contract: talk to the curve you think you are

The second clause is about identity. A named curve -- "P-256," "secp256k1" -- is an agreement to use one specific set of domain parameters, and in particular one specific generator, the base point G that every public key is measured against.

Generator / base point (G)

Every named elliptic curve fixes a single public point G from which all key material is derived: a private key d corresponds to the public point dG. The generator is not a secret -- it is a published constant. But it is load-bearing: "the public key is dG" is only meaningful if both sides agree on which G.

Named curve vs. explicit parameters

A certificate can specify its curve two ways. A named curve is an object identifier pointing at standardized domain parameters (fixed a, b, p, G, n). Explicit parameters spell out all of those numbers inline, which lets the certificate carry a custom generator. Accepting explicit parameters without checking them against a known named curve means trusting an attacker to tell you what G is.

The contract: never trust attacker-supplied explicit parameters. A validator that checks a public point but not the generator it was measured against has, in effect, let the attacker choose the ruler and then declared the measurement correct. That is precisely the door CurveBall walked through [6].

The negotiation contract: agree to strength, not to a museum piece

The third clause governs what two parties agree to before they exchange anything. In ephemeral Diffie-Hellman, each side picks a fresh secret per connection, which is supposed to guarantee that compromising one session cannot retroactively expose others.

Ephemeral Diffie-Hellman (DHE) and forward secrecy

In ephemeral DH, the private exponents are generated fresh for each connection and discarded afterward, so a key recovered later cannot decrypt past sessions. This property is called forward secrecy. It is the reason "just use a fresh ephemeral key" feels like a complete defense -- and, as Logjam showed, the reason that feeling is dangerously incomplete.

Export-grade cryptography (DHE_EXPORT)

In the 1990s, US export regulations capped the strength of cryptography shipped abroad, producing deliberately weakened cipher suites such as 512-bit DHE_EXPORT Diffie-Hellman [7]. The policy was abandoned, but the code was not: two decades later, servers and libraries still spoke these crippled suites on request.

The contract: the negotiated group must be strong, fresh, and unshared. The fine print that sank it: many servers ship the same standardized 512-bit prime, so breaking one group breaks all of them at once [7]. A fresh ephemeral exponent does not save you when the prime itself is weak and shared.

ContractWhat it requiresWhat violates itField break
Noncek secret, uniform, unique per signaturea constant, repeated, or biased kPS3, Android, Minerva, TPM-Fail, LadderLeak
Parameternamed curve, standard generator Gtrusting attacker-supplied explicit parametersCurveBall
Negotiationstrong, fresh, unshared groupdowngrade to a crippled, shared groupLogjam

Three contracts, three clauses of fine print. Over fifteen years, every clause was breached in the field -- and the breaches fall into exactly three piles.

4. The Failure Catalog: Seven Breaks, Three Layers, One Shape

None of the seven incidents below solved a discrete logarithm. Every one of them recovered a private key or forged a trusted one. Watch where each attack actually landed -- because the landing spot, not the marquee name, is the whole lesson.

Ctrl + scroll to zoom
Half a century of deployment breaks, none of which solved the discrete log on a strong group.

Here is the entire corpus on one page. The rightmost column is the thesis in a single word, repeated seven times.

IncidentYearPillarMechanismEffort to breakWhat fellDiscrete log solved?
PS32010Nonce (reuse)a constant k2 signaturesECDSA firmware-signing keyNo
Android wallets2013Nonce (reuse)repeated k from a broken RNG2 reused signaturesBitcoin wallet keysNo
Logjam2015Downgradeforced 512-bit shared prime1 NFS precompute per primeTLS session secrecyOnly a crippled, shared 512-bit export prime
TPM-Fail2019-2020Nonce (bias)timing leak of nonce bit-lengthmany signatures + lattice256-bit TPM keysNo
Minerva2020Nonce (bias)timing leak of nonce bit-lengthabout 2100 signatures + latticeECDSA keyNo
LadderLeak2020Nonce (bias)sub-bit ladder leakmany signatures + Bleichenbacher/FourierECDSA keyNo
CurveBall2020Validationan unchecked generator1 forged certificatecertificate trust itselfNo

Six "No"s and one heavily qualified "Yes." Let us walk the three pillars in turn.

Pillar 1a: the nonce, reused (certain, from two signatures)

In December 2010, at the 27th Chaos Communication Congress, the group fail0verflow presented "Console Hacking 2010" and revealed that Sony had signed PlayStation 3 firmware using ECDSA with a constant nonce [3]. Not a weak random k. The same k, every time. Every signature Sony ever produced shared a nonce with every other, which means any two of them collapse to the algebra from Section 3. Keep two PS3 events distinct. fail0verflow's 27C3 talk exposed the constant-nonce mechanism. George Hotz released a separate PS3 root key weeks later, in January 2011 [11]. The teaching case -- a hardcoded constant nonce -- is fail0verflow's. The console's chain of trust, the thing Sony spent years engineering, came apart because a random number generator was told to always return the same number.

Ctrl + scroll to zoom
Two signatures that share a nonce are two linear equations in two unknowns. The key falls out by elementary algebra.

This is not a metaphor. Here is the recovery, executable. Two signatures share a nonce, and a dozen lines of BigInt arithmetic reproduce the private key exactly:

JavaScript Recover an ECDSA private key from two signatures that reuse the nonce
// secp256k1 group order
const n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141n;
const mod = (a, m) => ((a % m) + m) % m;

// Modular inverse via the extended Euclidean algorithm
function inv(a, m) {
let [oldr, r] = [mod(a, m), m];
let [olds, s] = [1n, 0n];
while (r !== 0n) {
  const q = oldr / r;
  [oldr, r] = [r, oldr - q * r];
  [olds, s] = [s, olds - q * s];
}
return mod(olds, m);
}

// A victim signs two different messages with the SAME nonce k
const d  = 0x00c0ffee1234567890abcdef00c0ffee1234567890abcdef00c0ffee12345678n; // secret
const k  = 0x0000deadbeef0000feed0000deadbeef0000feed0000deadbeef0000feed0001n; // reused nonce
const r  = mod(0x1122334455667788112233445566778811223344556677881122334455667788n, n);
const z1 = 0x1111111111111111111111111111111111111111111111111111111111111111n;
const z2 = 0x2222222222222222222222222222222222222222222222222222222222222222n;
const s1 = mod(inv(k, n) * mod(z1 + mod(r * d, n), n), n);
const s2 = mod(inv(k, n) * mod(z2 + mod(r * d, n), n), n);

// The attacker sees only (r, s1, z1) and (r, s2, z2). Recover k, then d.
const kRec = mod((z1 - z2) * inv(mod(s1 - s2, n), n), n);
const dRec = mod((mod(s1 * kRec, n) - z1) * inv(r, n), n);
console.log('recovered nonce matches:  ' + (kRec === k));
console.log('recovered private key:    ' + (dRec === d));
console.log('d = 0x' + dRec.toString(16));

Press Run to execute.

Three years later, the same algebra emptied wallets. In August 2013, an advisory on bitcoin.org warned that "a component of Android responsible for generating secure random numbers contains critical weaknesses" that rendered "all Android wallets" vulnerable to theft [4]. The root cause, per Google's own postmortem, was that the platform's SecureRandom "may not receive cryptographically strong values" because the underlying PRNG was improperly initialized [12].

The consequence was nonce repetition across transactions. And because every Bitcoin signature is broadcast to a public ledger, anyone could scan the chain for two signatures sharing an r and drain the wallet behind them. The bitcoin.org advisory names the flaw and the affected wallets but states no total loss figure [4]. Any "coins stolen" number you have seen is reported, not established -- treat it accordingly.

The detector that would have caught both PS3 and Android is embarrassingly short. Group public signatures by r; any collision is an exposed key:

JavaScript Scan a batch of signatures for a reused nonce (a repeated r)
const n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141n;
const mod = (a, m) => ((a % m) + m) % m;
function inv(a, m) {
let [oldr, r] = [mod(a, m), m];
let [olds, s] = [1n, 0n];
while (r !== 0n) { const q = oldr / r; [oldr, r] = [r, oldr - q * r]; [olds, s] = [s, olds - q * s]; }
return mod(olds, m);
}
// Build a public feed in which one signer reused a nonce, then forget the secret
const dSecret = 777n, kReused = 424242n, rReused = 987654321n;
const mk = (z) => ({ r: rReused, s: mod(inv(kReused, n) * mod(z + mod(rReused * dSecret, n), n), n), z });
const feed = [ { r: 111n, s: 22n, z: 5n }, mk(1001n), { r: 222n, s: 44n, z: 9n }, mk(2002n), { r: 333n, s: 66n, z: 12n } ];

const seen = new Map();
for (const g of feed) {
const key = g.r.toString();
if (seen.has(key)) {
  const a = seen.get(key), b = g;
  const k = mod((a.z - b.z) * inv(mod(a.s - b.s, n), n), n);
  const d = mod((mod(a.s * k, n) - a.z) * inv(a.r, n), n);
  console.log('NONCE REUSE at r = ' + key + '  ->  private key d = ' + d.toString());
} else {
  seen.set(key, g);
}
}

Press Run to execute.

Two incidents, two different root causes -- a hardcoded constant and a starved RNG -- and one identical, certain outcome. This is the crudest form of the whole thesis: the deployment lost the key while the discrete log stood untouched.

DimensionReused nonceBiased nonce
What leaksthe whole nonce (it repeats)a partial statistic about the nonce
Signatures neededexactly 2many (Minerva about 2100; PuTTY about 60 [13])
Attackelementary algebraHidden Number Problem (lattice or Fourier)
Certaintycertainstatistical
ExamplesPS3, AndroidMinerva, TPM-Fail, LadderLeak, PuTTY

Pillar 1b: the nonce, biased (statistical, over many signatures)

Reuse is loud. The subtler failure is a nonce that never repeats but is not quite uniform -- one whose top bit is a little too often zero, say. It turns out that even this surrenders the key, and the theory predicting it predates the exploits by two decades.

Hidden Number Problem (HNP)

Given many samples that each leak a few of the most-significant bits of k, together with the public signature data, recover the fixed secret d. Boneh and Venkatesan defined this problem in 1996 and proved it tractable [14]. Every biased-nonce attack in this article -- Minerva, TPM-Fail, LadderLeak, PuTTY -- is an instance of it.

Nguyen and Shparlinski turned the abstract HNP into a concrete lattice attack on (EC)DSA with partially known nonces [15], and Brumley and Tuveri showed in 2011 that the necessary bit-leak could be harvested remotely, over a network, from an OpenSSL implementation whose scalar multiplication was not constant-time [16]. Then the field split into two solver regimes, and telling them apart is essential.

When the timing channel leaks a few bits of the nonce -- typically its exact bit-length -- the HNP is solved by lattice reduction. Minerva (CHES 2020) demonstrated this against smartcards and libraries whose scalar multiplication ran in time correlated with the nonce's length, reporting roughly "2100 signatures to recover the private key on the standard secp256r1 curve" [17].

TPM-Fail (USENIX Security 2020) carried the same idea into hardware roots of trust. A timing leak in Intel firmware TPMs (CVE-2019-11090 [18]) and STMicroelectronics ST33 chips (CVE-2019-16863 [19]) recovered a 256-bit ECDSA key from an Intel fTPM in 4 to 20 minutes, and a VPN authentication key remotely in about five hours [5]. Two honesty notes. Minerva's project page retracted its original EdDSA claim; the confirmed result is ECDSA-only [17]. And the TPM-Fail targets were not toys -- they held Common Criteria EAL4+ and FIPS 140-2 certification, and the leak survived that scrutiny [5].

Ctrl + scroll to zoom
One framework, the Hidden Number Problem, with two solver regimes chosen by leak size. LadderLeak is not a lattice attack.

The second regime is where people get it wrong. When the leak drops below a single bit -- LadderLeak revealed the most-significant bit of the nonce "but with probability less than one" -- lattices become intractable, and the attack instead revives a Fourier-analysis method the paper credits to Daniel Bleichenbacher [20].

The LadderLeak authors note that "most of the attacks so far have relied on at least two bits of nonce bias," precisely the lattice regime. Their contribution was to break below it, over curves sect163r1 and NIST P-192, using the Fourier solver rather than a lattice [20]. Calling LadderLeak a lattice attack is the field's classic mistake.

"Breaking ECDSA With Less Than One Bit Of Nonce Leakage" -- the title of the LadderLeak paper, and the most compact statement of how little a nonce must betray before the key is gone.

Notice what happened across this subsection. Every one of these attacks beat a signer that had already removed the reuse bug. The leak had moved from how the nonce was generated to how it was used -- a variable-time scalar multiplication -- and the cure had to move with it. Hold that thought; it is the pivot of the entire article. But reuse or bias, lattice or Fourier, two signatures or two thousand, the outcome is the same and the discrete logarithm is never touched: the deployment hands over d, and the strongbox stays locked.

Pillar 2: the parameters, unvalidated (CurveBall)

The nonce pillar is about a secret the deployment mishandles. The second pillar is about an identity the deployment fails to check. On 14 January 2020, Microsoft patched CVE-2020-0601, reported by the NSA: "a spoofing vulnerability exists in the way Windows CryptoAPI (Crypt32.dll) validates Elliptic Curve Cryptography (ECC) certificates" [6]. It became known as CurveBall, and it is the cleanest example in the whole corpus of a break that has nothing to do with the mathematics of ECC.

Recall the parameter contract. A public key is the point dG -- meaningful only if everyone agrees on G. CryptoAPI, when handed a certificate that specified its curve with explicit parameters, checked that the certificate's public point matched a trusted root's public key. What it did not check was the generator.

So an attacker could craft a curve with a custom generator G', pick any private key d' they liked, and compute G' such that d' * G' equals the exact public point of a trusted root certificate authority. The forged certificate then presents the right public point on the wrong curve. Windows, comparing only the point, accepts it -- while a library that pins named curves rejects it instantly, because G' is not the standard base point.

Ctrl + scroll to zoom
CVE-2020-0601: crypt32.dll matched the public point but never verified the generator against the named curve.

The ECDLP was never in play. The attacker chose their own private key; they never had to recover anyone's. The failure is a single missing comparison -- generator against named curve -- buried in a certificate validation stack that a billion machines trusted. CurveBall is a validation bug, not a curve break, and the fix is exactly what the missing check would have been: reject explicit parameters, or fully re-validate them against the claimed named curve.

Pillar 3: the negotiation, downgraded (Logjam)

The third pillar is the one honest exception, and handled carelessly it looks like a refutation of the whole thesis. In 2015, the Logjam team (CVE-2015-4000) showed that a man-in-the-middle could rewrite a TLS handshake -- "rewriting a ClientHello with DHE replaced by DHE_EXPORT" -- to force the connection onto a 512-bit export-grade Diffie-Hellman group [21]. And here, unlike everywhere else, the attacker really does compute a discrete logarithm.

The trick is that the expensive part of the number field sieve has to be done only once per prime, and servers share primes.

Number Field Sieve (NFS)

The fastest known classical algorithm for the finite-field discrete logarithm (and for integer factoring). Its decisive feature here: its costly first stage depends only on the prime being attacked, not on any particular exchanged key. Precompute once per prime, and every session under that prime becomes cheap to break. The internals belong to the companion article; what matters here is that one structural fact.

The Logjam researchers found that "8.4% of the Top 1 Million domains were initially vulnerable," and that because so many servers reused a handful of standardized 512-bit primes, "the first step in the number field sieve ... is dependent only on this prime" [7]. One precomputation, amortized across every server that shipped that prime.

"The first step in the number field sieve ... is dependent only on this prime." One precomputation breaks every server that shares the group.

Ctrl + scroll to zoom
The number field sieve's expensive first step depends only on the prime, so one precomputation breaks every server sharing it. The downgrade set up the weak, shared group.

Read carefully, Logjam is not a counterexample; it is the thesis in its most literal form. A discrete log was computed, but only against a 512-bit prime that a downgrade forced the connection onto and that policy had left crippled and shared. The deployment set the weak, shared group on the table; the number field sieve merely finished the job. No strong, standard-sized group ever fell. The fix is the same shape as the break: remove export ciphers, negotiate vetted named groups (RFC 7919 [22]), and adopt TLS 1.3, which removes static Diffie-Hellman entirely [23].

Three pillars, seven breaks, one shape: every attack hit a layer the discrete-log math depends on but does not control. Name the shape, and you have the whole discipline.

5. The Realization: Fix the Contracts, Not the Curve

There was no single eureka here. The insight accumulated across fifteen years of incidents and then snapped into one sentence: every field break attacked a layer the discrete-log math depends on but does not control -- the nonce, then the parameters, then the negotiated strength -- and every fix changed how the primitive is generated, used, validated, or negotiated, never the curve and never the log.

The sharpest crystallization hides inside the word "bias." For years it was treated as one problem with one fix: remove the random number generator, derive the nonce deterministically (RFC 6979 [24], later blessed by FIPS 186-5 [25]), and the biased-nonce class is solved. But Minerva, TPM-Fail, and LadderLeak all recovered keys from signers that had already done that. The reason is that "bias" was concealing two distinct root causes with two distinct cures.

Ctrl + scroll to zoom
Two root causes hid under one word. Determinism fixes generation; constant-time fixes usage. Neither substitutes for the other.

A generation defect is a bad nonce coming out of the sampler -- a constant (PS3), a repeat (Android), a predictable value. Determinism and hedging cure it. A usage defect is a perfectly good nonce leaking through the timing of the scalar multiplication that consumes it -- the bit-length falling out through a side channel (Minerva, TPM-Fail) or a sub-bit correlation (LadderLeak). Only constant-time code cures that. The two cures are orthogonal, and you need both.

Generalize the two-cures fork and you get the entire discipline of this field: four contracts, not one curve. Generate the nonce so it cannot be predicted or repeated; use it in constant time so it cannot leak; validate your parameters so no attacker chooses your generator; negotiate only strong, unshared groups so no downgrade can strand you. Every documented break is a breach of one of those four. No break in the corpus is a break of the discrete logarithm.

This also dissolves the apparent contradiction the article opened with. "Nobody solved the discrete log" and "somebody recovered the key" only sound incompatible if you conflate the discrete-log problem with a discrete-log deployment. The problem is a statement about computational hardness; the deployment is a nonce, a set of parameters, and a negotiation, wrapped around that hardness. The problem stayed hard. The wrapping tore.

If the discipline is "honor the four contracts, not the curve," what does a deployment that honors all four actually look like in 2026?

6. What Correct EC/DH Deployment Looks Like in 2026

The state of the art in this field is not a better discrete-log solver -- no such thing exists. It is a deployment discipline at the three layers the math never controlled. Here it is, pillar by pillar.

Nonce: two orthogonal cures, and a primitive that folds in both

Deterministic ECDSA (RFC 6979)

Derive the nonce k deterministically from the private key and the message hash via an HMAC-based construction, so the signer "do[es] not need access to a source of high-quality randomness" [24]. Identical key-and-message pairs always yield the same k; distinct messages yield unrelated nonces. This closes the generation defect -- the PS3 and Android reuse classes cannot occur.

RFC 6979 also quietly records the deeper lesson. It insists on comparing each candidate nonce against the group order rather than reducing it modulo the order, warning that a "simple modular reduction would induce biases that would be detrimental to signature security" [24]. That is a standards document, in 2013, acknowledging that bias, not just reuse, is fatal. You can watch the effect yourself:

JavaScript Why RFC 6979 forbids reducing the nonce modulo the group order
// A raw sampler emits values in [0, 256). We need a nonce in [0, q).
const q = 200n, B = 256n, trials = 400000;
const raw = () => BigInt(Math.floor(Number(B) * Math.random()));
let biasedHigh = 0, fairHigh = 0;
const half = q / 2n;
for (let i = 0; i < trials; i++) {
const reduced = raw() % q;              // reduce mod q -> BIASED
if (reduced >= half) biasedHigh++;
let fair; do { fair = raw(); } while (fair >= q);  // compare to q, retry -> FAIR
if (fair >= half) fairHigh++;
}
console.log('reduce mod q -> P(nonce in top half): ' + (biasedHigh / trials).toFixed(4));
console.log('compare to q -> P(nonce in top half): ' + (fairHigh / trials).toFixed(4));
console.log('That gap from 0.5 is a free bit for a Hidden Number Problem attacker.');

Press Run to execute.

Determinism, though, fixes only generation. On hardware it also adds a risk.

Hedged signing (FIPS 186-5)

Compute the nonce from the private key, the message hash, and a few bytes of fresh randomness. A dead RNG falls back to the safe deterministic core; a differential fault, which needs two identical signings to differ, is defeated by the fresh input. FIPS 186-5 recommends this for hardware because bare determinism is "of particular concern for ... deterministic signature schemes, as well as embedded or IoT devices and smartcards" [25].

Constant-time scalar multiplication

Compute kG with a data-independent trace of instructions, branches, and memory accesses, so the runtime never depends on the bit-length or value of k. This is the usage cure -- the only defense against Minerva, TPM-Fail, and LadderLeak, whose leaks all live in the multiplication, not the sampler. Its precursor is Brumley and Tuveri's 2011 remote attack on a non-constant-time OpenSSL ladder [16].

New designs can sidestep the whole fork by choosing a misuse-resistant primitive. Ed25519 (RFC 8032) derives its nonce as a hash of the secret and message -- deterministic by construction, no per-signature RNG -- and signs with a single complete, constant-time addition law that has no exceptional cases to mishandle [26]. It folds both cures into the primitive and removes the dangerous choices from the caller's hands. Misuse-resistant is not misuse-proof. PuTTY derived P-521 ECDSA nonces such that "the first 9 bits of each ECDSA nonce are zero," allowing "full secret key recovery in roughly 60 signatures" (CVE-2024-31497) [13]. Determinism implemented carelessly re-introduced exactly the bias it was meant to prevent.

Validation: reject what you cannot vouch for

The CurveBall cure is direct: bind a certificate's curve to the standard parameters of its named curve, and reject explicit parameters or fully re-validate them. The January 2020 patch made crypt32.dll check the generator, not merely the point [6].

For key exchange with static keys, the discipline is fuller. Before using a received point, confirm it is not the identity, lies on the curve, and sits in the correct prime-order subgroup -- the full public-key validation of NIST SP 800-56A, which blocks invalid-curve and small-subgroup attacks that would otherwise bleed a static key out one query at a time [27].

The most durable answer is to make invalid inputs unrepresentable. X25519 works on a Montgomery curve chosen so that every 32-byte string is an acceptable public key; the RFC even instructs implementations to "accept non-canonical values," and to run the conditional swap "in constant time" [28]. There is no explicit-parameter path to abuse and no on-curve check to forget. This is the "make invalid states unrepresentable" principle applied to cryptography: the safest validation code is the code you deleted because the type system already guarantees the property. But note the boundary carefully.

Negotiation: remove the weak option entirely

The downgrade pillar's fix is structural. RFC 7919 replaced ad-hoc, shared Diffie-Hellman primes with a menu of vetted named groups negotiated like curves [22]. TLS 1.3 went further and deleted the weak options outright, so there is nothing to downgrade to.

"Static RSA and Diffie-Hellman cipher suites have been removed; all public-key based key exchange mechanisms now provide forward secrecy." -- RFC 8446, the TLS 1.3 specification [23].

Because TLS 1.3 permits only strong ephemeral groups and binds the negotiation into the handshake transcript, the Logjam rewrite is not merely discouraged -- it is structurally impossible [23]. The end state of the negotiation pillar is a protocol in which the crippled, shared 512-bit group Logjam relied on simply cannot be selected.

Each of these is a choice, and where there is a choice, engineers argue. Which discipline actually wins in which threat model?

7. Competing Approaches: Which Defense Answers Which Adversary

These defenses are not rungs on one ladder. They are answers to different adversaries, and the honest way to compare them is one pillar at a time.

Nonce: which signing discipline stops which adversary

The load-bearing insight is that no single column stops every row. Generation cures (deterministic [24], hedged [25]) and the usage cure (constant-time) are orthogonal, which is why hedged-plus-constant-time became the practitioner default and why Ed25519 [26] folds most of both into the primitive.

Adversary / failureRandomized (bare RNG)Deterministic (RFC 6979)Hedged (FIPS 186-5)Constant-time multEd25519
RNG returns constant or repeat (PS3, Android)failsstopsstopsorthogonalstops
Differential fault on a deterministic signerrandomness helpsfailsstopsorthogonalinherits the caveat
Timing leak of nonce bit-length (Minerva, TPM-Fail)failsfailsfailsstopsstops (uniform ladder)
Sub-bit ladder leak (LadderLeak)failsfailsfailsstopsstops (uniform ladder)

Read the rows, not the columns: reuse fails only the first row and is certain from two signatures; the timing leaks fail three of the five columns and are cured on a different axis entirely. That is the two-cures fork, rendered as a matrix.

Validation: three philosophies of not trusting your input

DimensionNamed-curve pinningFull validation (SP 800-56A)All-inputs-valid (X25519)
Philosophyreject non-standard parametersvalidate every received inputmake invalid inputs unrepresentable
Stops CurveBall (unvalidated generator)yes, its exact fixyes, re-derives the generatoryes, no explicit-parameter path
Stops invalid-curve / small-subgrouppartialyes, on-curve plus subgroupyes, twist-secure
Per-operation costO(1) table compareO(1) up to one scalar multone constant-time ladder
Best suited forX.509, code-signing, PKIstatic-key ECDH, HSMsephemeral ECDH

Named-curve pinning is the precise CurveBall fix [6]; SP 800-56A validation is the belt-and-suspenders choice for static keys [27]; X25519 deletes the problem by construction [28]. They converge on stopping CurveBall and diverge on everything else.

Downgrade: hardening, deletion, or hedging against tomorrow

DimensionConfig hardening + FFDHETLS 1.3Hybrid post-quantum
Removes the 512-bit export rungyes, within FFDHEyes, structurallyyes, inherits 1.3
Removes shared or unknown primesyes, named menuyes, fixed groupsyes
Downgrade protection in the handshakeno, still in-bandyes, transcript-boundyes
Defends against a future Shor adversarynonoyes, if ML-KEM holds
Residual weaknessthe legacy long tailnon-TLS 1024-bit primesa KEM is not a NIKE, young PQC

RFC 7919 named groups [22] are the transitional hardening for TLS 1.2; TLS 1.3 is the structural end state [23]; hybrid X25519 with ML-KEM (RFC 9954 [29], ML-KEM standardized as FIPS 203 [30]) is the forward hedge against a quantum adversary. Only the last column defends against a break that would be genuine mathematics rather than a deployment slip.

Every column in every table changed the deployment, not the curve. So is the discrete log itself simply unbreakable? Almost -- and the "almost" is the most honest paragraph in this article.

8. Theoretical Limits: What Is Provably True on Both Sides

This is the honest concession the thesis has been earning the right to make. There are two provable sides here, and the argument needs both.

The hardness side: no room for a strong curve to fall

On a well-chosen group, the discrete logarithm is genuinely hard, and we can say so with unusual precision. The best classical attack is Pollard's rho, a square-root-time random walk that needs negligible memory [2]. In the strict generic model its expected cost is about πn/2\sqrt{\pi n/2}, roughly 1.25 times n\sqrt{n} group operations; on an elliptic curve, the negation map (where PP and P-P share an x-coordinate) trims that to about 0.886 times n\sqrt{n}. Either way the exponent is the same, matching baby-step giant-step's O(n)O(\sqrt{n}) time [1].

Against that upper bound, Shoup proved a generic lower bound of Ω(p)\Omega(\sqrt{p}): no algorithm restricted to the group operation can do better [31]. The two meet at Θ(n)\Theta(\sqrt{n}). The generic gap is essentially closed -- which is exactly why a 256-bit curve delivers around 128-bit security, and why no strong deployed curve's discrete log has fallen.

QuantityValueNote
Best classical DL attackPollard's rho, about 1.25 times sqrt(n) generic; 0.886 times sqrt(n) on curvesnegligible space
Baby-step giant-stepO(sqrt(n)) time and O(sqrt(n)) spacethe space-heavy twin
Generic lower boundOmega(sqrt(p)), provably no faster generic algorithmShoup 1997
Finite-field DH (non-generic)sub-exponential via the number field sievewhy DH needs about 3072-bit primes (2048-bit minimum)
Strong deployed curve or standard group ever solvednone, only Logjam's crippled shared 512-bit primethe thesis in one row

The last two rows carry the concession. Finite-field Diffie-Hellman is not generic: the number field sieve solves it in sub-exponential time, which is why finite-field DH needs primes of about 3072 bits to match the security a 256-bit curve gives (2048 bits is the absolute minimum), and why Logjam's downgrade to 512 bits was finishable at all [7]. The number-field-sieve mathematics belongs to the companion article.

Logjam is the only break in this corpus that reached the mathematics, and the reason is structural, not accidental. A finite field carries extra arithmetic structure that a generic group lacks, which lets the number field sieve run in sub-exponential time, faster than the square-root barrier that protects a strong elliptic curve. That structural gap is the sole opening the discrete log ever offered, and even it was not enough alone: the computation became feasible only after the prime was cut to 512 export-grade bits. Raise the group back to a standard 2048-bit prime, or move to a curve where no such shortcut exists, and the opening closes.

The leakage side: no room to hide a little bias

The other provable side indicts the deployment just as sharply. The Hidden Number Problem makes partial leakage fatal by construction: Boneh and Venkatesan proved that recovering a secret from many small most-significant-bit leaks is tractable [14], and Nguyen and Shparlinski turned that into a working lattice attack on (EC)DSA with partial nonces [15].

There is no "a little bias is tolerable" regime: any consistent partial leak of k, integrated over enough signatures, provably recovers d. Two or more leaked bits fall to a lattice; a sub-bit leak falls to Bleichenbacher's Fourier method [20]. "k is secret, uniform, and unique" is not a best practice -- it is a hard boundary.

So where, concretely, does EC and DH still break tomorrow?

9. Where EC and DH Still Break in the Field

The incidents are settled. The classes are not. Every open problem below is a documented pattern waiting for its next instance, and each one maps to a pillar you have already met.

The next SecureRandom (nonce generation, Pillar 1). A signer needs a unique, secret nonce at the exact moment its entropy is weakest: first boot, a headless IoT device with no entropy events, or a freshly cloned virtual machine carrying a duplicated seed. This is the mechanism behind Android 2013 [12], and it recurs whenever hardware is provisioned faster than it can gather randomness. Cloned-VM state duplication is an especially nasty modern form: two hosts that never coordinated can emit the same "random" nonce because they booted from one snapshot. The signing path can be hedged [25], but key generation and ephemeral key exchange still need a live, well-seeded source.

The next Minerva or LadderLeak (nonce usage, Pillar 1). Constant-time scalar multiplication must be re-established against every new microarchitecture -- caches, execution ports, prefetchers, simultaneous multithreading -- and on every fragile incomplete-addition curve. The bit-length leak of Minerva [17] and the sub-bit leak of LadderLeak [20] both post-date deterministic nonces precisely because the leak had moved to usage. Formally verified primitives close the known channels on the chosen curve; FIPS-mandated P-curves and secp256k1 keep hand-written code in production.

The long tail of shared primes (downgrade, Pillar 3). TLS 1.3 closes the web protocol layer, but export-grade and shared standardized primes outlived their policy elsewhere. IKEv1 VPNs and older SSH still ship shared 1024-bit Diffie-Hellman groups, and a single precomputation per shared prime amortizes across every server using it [7]. The consensus recommendation is blunt: retire 1024-bit DH now.

The next CurveBall (validation, Pillar 2). CurveBall was one unchecked generator in one library [6]; the class is "somewhere in a large validation stack, attacker-supplied parameters are trusted." Every new parser, certificate profile, or post-quantum key format reopens the class, and a single such bug in a widely embedded validator forges trust across everything that depends on it.

Post-quantum migration ahead of Shor (cross-pillar). Hybrid key exchange -- running X25519 alongside ML-KEM so the session stays secure if either component holds -- is standardized (RFC 9954 [29]; concrete groups such as X25519MLKEM768 in the ongoing ECDHE-MLKEM work [32]; ML-KEM standardized as FIPS 203 [30]) and is already deployed at scale: it protected a majority of the human web traffic Cloudflare measured by late 2025 [33]. But the migration carries a trap that has nothing to do with the discrete log.

None of these needs new mathematics to break you. Each needs exactly one deployment mistake. Here is how not to make it.

10. What to Do on Monday

Every item below maps to a specific incident in this article. Do these, and you do not ship the next one.

  • Never put a bare runtime RNG in the signing path. Use deterministic (RFC 6979 [24]) or, on hardware, hedged (FIPS 186-5 [25]) nonces. Prevents: PS3, Android.
  • Demand constant-time, exception-free scalar multiplication. This is a separate control from the nonce discipline, not a duplicate of it. Prevents: Minerva, TPM-Fail, LadderLeak.
  • Prefer misuse-resistant primitives. Ed25519 for new signing [26], X25519 for ephemeral key exchange [28]; for static-key ECDH, run full public-key validation per SP 800-56A [27]. Prevents: whole classes of implementer error.
  • Reject explicit curve parameters; require named curves. Pin the curve, and the generator with it. Prevents: CurveBall [6].
  • Disable export ciphers and use vetted groups. RFC 7919 named groups [22] for residual TLS 1.2 DHE, or move to TLS 1.3 [23]. Prevents: Logjam.
  • Never assume a fresh ephemeral rescues a shared prime. The number-field-sieve precomputation is per-prime, not per-connection [7]. Prevents: the subtle half of Logjam.
  • Plan the post-quantum migration as hybrid, not pure. Run a classical curve alongside ML-KEM (RFC 9954 [29]); remember a KEM is not a NIKE. Prevents: harvest-now-decrypt-later exposure.
A three-question self-audit for any EC or DH deployment
  1. Nonce: For every signature, can you show the nonce is both unpredictable (hedged or deterministic) and consumed in constant time? If you can only answer one half, you are exposed to the other.
  2. Parameters: Does your certificate and key-exchange path reject attacker-supplied explicit parameters and validate every received point against the named curve?
  3. Negotiation: Can a man-in-the-middle force any weaker group or version than you intend? If you cannot prove "no," assume "yes."

Notice that not one item on this list is "use a bigger curve." For every break except Logjam's downgrade, key size is irrelevant -- a 384-bit curve reuses a nonce exactly as fatally as a 256-bit one. The controls are about generation, usage, validation, and negotiation, because those are the four contracts, and the contracts are where reality broke.

Two questions decide whether you got this right, and they happen to be the two most-repeated errors in the field.

11. FAQ: Misconceptions, Precisely Corrected

Frequently asked questions

Has anyone ever solved the discrete log in the wild?

Once, and only against a deliberately crippled target. Logjam computed discrete logarithms against a 512-bit export-grade Diffie-Hellman prime -- one that a man-in-the-middle downgrade could select and that many servers had in common [7][21]. No strong deployed curve -- P-256, Curve25519, secp256k1 -- and no standard-sized group of 2048 bits or more has ever had its discrete log solved in public. The ceiling of the entire corpus is a 512-bit prime that policy left broken.

Does one biased signature leak the key?

No, and this is the most common error. A repeated nonce recovers the key with certainty from exactly two signatures, by elementary algebra. A merely biased nonce emits only a faint statistical signal per signature, so recovery takes many of them plus a dedicated lattice or Fourier attack -- about 2100 for Minerva on secp256r1 [17], roughly 60 for PuTTY's nine-zero-bit bias [13]. One biased signature leaks almost nothing.

Is LadderLeak a lattice attack?

No. LadderLeak's leak is under a single bit per signature, which lattice methods cannot exploit; it revives Bleichenbacher's Fourier-analysis solver instead [20]. The lattice regime is Minerva and TPM-Fail, whose leaks are two bits or more [17][5]. Calling all three "lattice attacks" collapses a distinction the attacks themselves are built on.

Is there an EC or DH padding-oracle break like RSA has?

No. Padding oracles are an RSA and CBC-mode phenomenon; there is no elliptic-curve or Diffie-Hellman padding-oracle exemplar, and you should not go looking to manufacture one. The EC and DH attack surface is exactly the three pillars here -- the nonce, parameter validation, and downgrade. RSA's padding oracles, and the fact that RSA signing has no per-signature secret nonce to reuse, are covered in the companion piece "How RSA Breaks in Real Life."

Does deterministic ECDSA make me safe?

Only against half the problem. RFC 6979 removes the random number generator from the signing path and eliminates the reuse class [24], but it does nothing about a timing leak during nonce usage -- which is exactly how Minerva, TPM-Fail, and LadderLeak recovered keys from deterministic signers. The complete answer is hedged signing plus constant-time scalar multiplication [25], the two orthogonal cures.

Is a bigger curve or group the fix?

Almost never. The nonce, validation, and downgrade defects are all indifferent to key size: a forged CurveBall certificate is accepted no matter how large the curve is, because the flaw is a skipped generator check rather than a hard curve [6], and a reused or leaked nonce surrenders the private key whether that key is 256 or 384 bits. The one place size mattered was the export-group downgrade, and there the fix was to stop negotiating the 512-bit group at all [7], not to enlarge it.

So is ECC or Diffie-Hellman broken?

The primitive, no. The discrete logarithm on a strong group remains as hard as it was in the 1970s. What broke, repeatedly, was the deployment around it. Fix the nonce path, validate your parameters against named curves, and retire export and shared groups, and you have closed every break in this article. CurveBall was a validation bug, not a curve break [6] -- and that distinction is the whole point.

Half a century after Diffie and Hellman reduced key exchange to one hard problem, the scoreboard is unambiguous: seven documented field breaks across three deployment layers, and a discrete-log ceiling that only ever reached a deliberately crippled, shared 512-bit export group -- never a strong deployed curve, never a standard-sized group. The mathematics kept its promise. The deployments did not.

The discrete log never fell. The nonce did, the parameters did, and the negotiation did -- and every one of those is the deployment's job, not the curve's.

For the other half of the story -- how a curve itself could be structurally weak, how the number field sieve and Shor's algorithm actually break the math -- see the structural companion, "How the Discrete Log Would Break." For the primitive that has no per-signature nonce to reuse and its own padding-oracle history, see the series sibling, "How RSA Breaks in Real Life." This article was about the gap between a hard problem and a shipped product. That gap is where the keys keep getting out.

Study guide

Key terms

Per-signature nonce (k)
The once-used secret in ECDSA that must be secret, uniform, and unique per signature; the load-bearing prerequisite behind PS3, Android, Minerva, TPM-Fail, and LadderLeak.
Nonce reuse vs. bias
A repeated nonce recovers the key with certainty from two signatures; a biased nonce needs a statistical Hidden Number Problem attack over many signatures.
Hidden Number Problem
Recovering a fixed secret from many samples that each leak a few most-significant bits; the framework behind every biased-nonce attack.
Two-cures fork
Determinism and hedging fix nonce generation; constant-time scalar multiplication fixes nonce usage. The two are orthogonal and both are required.
CurveBall (CVE-2020-0601)
A Windows CryptoAPI bug that matched a certificate public point but never checked the generator against the named curve; a validation bug, not a curve break.
Logjam (CVE-2015-4000)
A TLS downgrade to a shared 512-bit export Diffie-Hellman prime, breakable because the number field sieve precomputes once per prime; the only discrete log in the corpus.
Named curve vs. explicit parameters
Referencing standardized domain parameters by identifier versus trusting attacker-supplied inline parameters, including a custom generator.

Comprehension questions

  1. Why does a reused nonce recover the key from only two signatures?

    Two signatures with the same nonce share r; subtracting the signing equations cancels the private-key term, yielding the nonce, and one equation then solves for the key.

  2. Why is LadderLeak not a lattice attack?

    Its leak is under one bit per signature, which lattices cannot exploit, so it uses Bleichenbacher's Fourier method instead. Lattices are the Minerva and TPM-Fail regime.

  3. Is Logjam a counterexample to the thesis?

    No. The only discrete log computed landed on a downgrade-forced, crippled, shared 512-bit prime; no strong or standard-sized group ever fell.

References

  1. Alfred J. Menezes, Paul C. van Oorschot, & Scott A. Vanstone (1996). Handbook of Applied Cryptography, Chapter 11. https://cacr.uwaterloo.ca/hac/about/chap11.pdf
  2. Edlyn Teske (2001). On random walks for Pollard rho method. https://doi.org/10.1090/S0025-5718-00-01213-8
  3. fail0verflow (2010). Console Hacking 2010 (PS3 Epic Fail), 27C3. https://media.ccc.de/v/27c3-4087-en-console_hacking_2010
  4. (2013). Android Security Vulnerability. https://bitcoin.org/en/alert/2013-08-11-android - bitcoin.org advisory; states no total loss figure
  5. Daniel Moghimi, Berk Sunar, Thomas Eisenbarth, & Nadia Heninger (2020). TPM-FAIL: TPM meets Timing and Lattice Attacks. https://tpm.fail/
  6. (2020). CVE-2020-0601 (CurveBall / Windows CryptoAPI Spoofing Vulnerability). https://nvd.nist.gov/vuln/detail/CVE-2020-0601
  7. David Adrian, Nadia Heninger, J. Alex Halderman, & Paul Zimmermann (2015). Imperfect Forward Secrecy: How Diffie-Hellman Fails in Practice (Logjam). https://weakdh.org/
  8. Whitfield Diffie & Martin E. Hellman (1976). New Directions in Cryptography. https://doi.org/10.1109/TIT.1976.1055638 - DH key exchange; security grounded in discrete-log hardness
  9. Victor S. Miller (1985). Use of Elliptic Curves in Cryptography. https://doi.org/10.1007/3-540-39799-X_31
  10. Neal Koblitz (1987). Elliptic Curve Cryptosystems. https://doi.org/10.2307/2007884
  11. George Hotz (2011). PS3 root-key disclosure (separate from the fail0verflow 27C3 talk).
  12. Alex Klyubin (2013). Some SecureRandom Thoughts. https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html
  13. (2024). CVE-2024-31497 (PuTTY biased P-521 ECDSA nonces). https://www.openwall.com/lists/oss-security/2024/04/15/6
  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 - Defines the Hidden Number Problem
  15. 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
  16. Billy Bob Brumley & Nicola Tuveri (2011). Remote Timing Attacks Are Still Practical. https://eprint.iacr.org/2011/232
  17. Jan Jancar, Vladimir Sedlacek, Petr Svenda, & Marek Sys (2020). Minerva: The curse of ECDSA nonces. https://minerva.crocs.fi.muni.cz/
  18. (2019). CVE-2019-11090 (Intel PTT / fTPM timing side channel). https://www.cve.org/CVERecord?id=CVE-2019-11090
  19. (2019). CVE-2019-16863 (STMicroelectronics ST33 TPM timing side channel). https://www.cve.org/CVERecord?id=CVE-2019-16863
  20. 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
  21. (2015). CVE-2015-4000 (Logjam). https://nvd.nist.gov/vuln/detail/CVE-2015-4000
  22. Daniel Kahn Gillmor (2016). Negotiated Finite Field Diffie-Hellman Ephemeral Parameters for TLS (RFC 7919). https://datatracker.ietf.org/doc/html/rfc7919
  23. Eric Rescorla (2018). The Transport Layer Security (TLS) Protocol Version 1.3 (RFC 8446). https://datatracker.ietf.org/doc/html/rfc8446
  24. Thomas Pornin (2013). Deterministic Usage of DSA and ECDSA (RFC 6979). https://datatracker.ietf.org/doc/html/rfc6979
  25. NIST (2023). FIPS 186-5: Digital Signature Standard (DSS). https://csrc.nist.gov/pubs/fips/186-5/final
  26. Simon Josefsson & Ilari Liusvaara (2017). Edwards-Curve Digital Signature Algorithm (EdDSA) (RFC 8032). https://datatracker.ietf.org/doc/html/rfc8032
  27. Elaine Barker, Lily Chen, Allen Roginsky, Apostol Vassilev, & Richard Davis (2018). NIST SP 800-56A Rev. 3: Recommendation for Pair-Wise Key-Establishment Using Discrete Logarithm Cryptography. https://csrc.nist.gov/pubs/sp/800/56/a/r3/final
  28. Adam Langley, Mike Hamburg, & Sean Turner (2016). Elliptic Curves for Security (RFC 7748). https://datatracker.ietf.org/doc/html/rfc7748
  29. Douglas Stebila, Scott Fluhrer, & Shay Gueron (2026). Hybrid Key Exchange in TLS 1.3 (RFC 9954). https://datatracker.ietf.org/doc/html/rfc9954
  30. NIST (2024). FIPS 203: Module-Lattice-Based Key-Encapsulation Mechanism (ML-KEM). https://csrc.nist.gov/pubs/fips/203/final
  31. Victor Shoup (1997). Lower Bounds for Discrete Logarithms and Related Problems. https://www.shoup.net/papers/dlbounds1.pdf
  32. Kris Kwiatkowski, Panos Kampanakis, Bas Westerbaan, & Douglas Stebila Post-quantum hybrid ECDHE-MLKEM Key Agreement for TLSv1.3 (work in progress). https://datatracker.ietf.org/doc/draft-ietf-tls-ecdhe-mlkem/
  33. Cloudflare Radar (2025). Post-Quantum Encryption Worldwide (Cloudflare Radar). https://radar.cloudflare.com/post-quantum