Chapter 6: Digital signatures reconsidered
A signature scheme is secure if an adversary who has seen signatures on any messages of its choice still cannot produce a valid signature on a fresh one. The security goal is called EUF-CMA, short for existential unforgeability under adaptive chosen-message attack (Goldwasser et al., 1988). Every digital signature scheme in the book targets this game or a strengthening of it. Textbook RSA fails it structurally, by a one-line algebraic forgery. ECDSA illustrates a different failure mode: its security depends critically on the per-message secret nonce . Reusing across two signatures under the same private key recovers the key outright from those two signatures alone. Biased or partially leaked nonces also lead to key recovery, but through a lattice attack on many signatures (the hidden number problem), not the closed-form derivation on two (Boneh & Venkatesan, 1996; Nguyen & Shparlinski, 2003). A few lines of Python make the two-signature case concrete.
A textbook forgery
Section titled “A textbook forgery”Textbook RSA signing raises the message to the private exponent modulo the public modulus and calls that the signature (Rivest et al., 1978). The verification check is , which reverses the signing map. Raw modular exponentiation is a group homomorphism on the unit group . If and , then by a single line of algebra. Anyone who has seen two valid signatures can multiply them and recover a valid signature on , without knowing or factoring .
The snippet below runs the forgery on the same 64-bit modulus Chapter 5 used for the toy RSA-KEM:
# Textbook RSA signing on the 64-bit modulus from Chapter 5.# Raw modular exponentiation is a group homomorphism on (Z/nZ)^*:# s1 * s2 = (m1 * m2)^d mod n, which verifies as a signature on (m1 * m2) mod n.p = 3184935163q = 3199286161n = p * qe = 65537d = pow(e, -1, (p - 1) * (q - 1))
# Honest signer produces two legitimate signatures.m1 = 0x1111222233334444m2 = 0x5555666677778888s1 = pow(m1, d, n)s2 = pow(m2, d, n)
# Attacker sees (m1, s1) and (m2, s2) and multiplies them.s_forged = (s1 * s2) % nm_forged = (m1 * m2) % n
# The forged pair verifies under the textbook rule s^e == m mod n,# and m_forged is a fresh message the signer never signed.assert m_forged not in {m1, m2}assert pow(s_forged, e, n) == m_forgedprint(pow(s_forged, e, n) == m_forged)# ==> TrueEvery Python block this chapter prints is also a standalone file in the companion repository, under chapter-code/ch06/, one file per block. Appendix C covers the clone and the environment they run on.
Raw RSA signing preserves a homomorphic relation between signatures and messages, and any useful definition of signature security has to rule out forgeries of this shape. The pedagogical repair is full-domain hash RSA (FDH-RSA): hash the message into the full RSA domain and sign the representative, so a scheme outputs instead of .
RSA exponentiation is still multiplicative, so the attacker can still compute . That product, however, only verifies as a signature on a message with . In the random-oracle model, finding such an requires inverting the random oracle at a value the attacker chose, which succeeds only with negligible probability (Bellare & Rogaway, 1996; Boneh & Shoup, 2023). What full-domain hashing removes is the message-level homomorphism, not the multiplicativity of the exponentiation. Real deployed RSA signature schemes use standardized encodings such as RSA-PSS (the probabilistic signature scheme) rather than the literal hash-and-exponentiate construction.
EUF-CMA as a game
Section titled “EUF-CMA as a game”A digital signature scheme is a triple . Gen() samples a keypair . Sign(sk, m) outputs a signature . Verify(pk, m, sigma) returns accept or reject. The scheme is correct if a signature produced by Sign always verifies: for every keypair and every message, Verify(pk, m, Sign(sk, m)) = 1 with probability one over the randomness of Gen and Sign. The security game fixes what it means for Verify to reject forgeries.
The EUF-CMA game against a signature scheme runs like this (Goldwasser et al., 1988). The challenger generates and gives to the adversary . may query a signing oracle on any message of its choice. The oracle returns . At any point outputs a forgery attempt . The adversary wins if and was never queried to the signing oracle. The advantage is
A signature scheme is EUF-CMA-secure if every polynomial-time adversary’s advantage is negligible in the security parameter (Boneh & Shoup, 2023).
Sign and forges on a message it never queried. The figure is the security game, not a deployment protocol: Sign in real systems is not a public oracle.It is useful to separate the goal (existential forgery on a fresh message) from the attack model (what the adversary gets to see). The game admits two weakenings and one strengthening worth naming. Every model hands the adversary the public key. They differ in what else it sees, and in what counts as a win.
| Notion | Also gets | Wins with |
|---|---|---|
| Key-only | Nothing | Any valid |
| EUF-KMA | Pairs on challenger-chosen messages | Valid , outside that set |
| EUF-CMA | A signing oracle on adversary-chosen messages | Valid , never queried |
| sEUF-CMA | The same as EUF-CMA | Any new valid pair, including a second on a queried |
Key-only and known-message (EUF-KMA, existential unforgeability under known-message attack) are the two weakenings. A scheme that fails EUF-CMA can still pass either of them, which is why neither is an adequate security target. The strengthening is sEUF-CMA (strong existential unforgeability), which denies the adversary even a fresh signature on a message the oracle already signed. The two standards this book builds sit on either side of that line: FIPS 205 states the SLH-DSA parameter-set security categories with respect to EUF-CMA (National Institute of Standards and Technology, 2024), while FIPS 204 designs ML-DSA for the stronger notion, which it writes SUF-CMA (National Institute of Standards and Technology, 2024a).
The full-domain hash RSA construction turns textbook RSA into an EUF-CMA-secure signature scheme in the random-oracle model (Bellare & Rogaway, 1993, 1996). The construction is direct. Sign(sk, m) outputs , where is a hash function whose output range covers . Verify(pk, m, sigma) accepts if . The security proof reduces EUF-CMA to the RSA assumption by answering the adversary’s hash queries itself. It plants the RSA challenge as the answer to one guessed query. Every other query gets a value whose -th root the reduction picked first and therefore knows, which is what lets it sign those messages on demand. If the forgery is built on the guessed query, the reduction reads the RSA inverse straight off it, and EUF-CMA is what guarantees that message was never sent to the signing oracle. The textbook treatment is in Boneh-Shoup (Boneh & Shoup, 2023).
Lattice-based signatures take a different route. ML-DSA is a Fiat-Shamir-with-aborts construction, and FIPS 204 bases its SUF-CMA security on MLWE (Module-LWE) over the ring and a nonstandard variant of MSIS (Module-SIS) called SelfTargetMSIS, in the random-oracle model (National Institute of Standards and Technology, 2024a). Chapter 9 defines and both module problems. Rejection sampling on the signer’s side prevents the signature distribution from leaking the secret.
Nonce reuse recovers the key
Section titled “Nonce reuse recovers the key”ECDSA signatures carry an independent random scalar called the nonce. If the same is ever used for two different signatures under the same private key, the attacker recovers the key from the two signatures alone (National Institute of Standards and Technology, 2023). The derivation is elementary and relies on the fact that the scalar order is prime.
Recall the ECDSA signing equation from Chapter 4. Given a private key , a message hash reduced modulo the scalar order , and a nonce , the signer computes and takes . The signature is .
Suppose the signer produces two signatures on and on under the same . Because is fixed, is the same in both signatures, so a repeated is the signal the attacker watches for. The two signature equations are
Subtract the second from the first. The terms cancel:
Multiply by and divide by to recover the nonce:
Because is prime, the inversion is well-defined iff , which in turn holds iff . Substitute back into the first signature equation and solve for :
This step also assumes . Real ECDSA rejects a signature with or , so a correctly implemented signer never emits one. What it does instead depends on how the nonce was produced. FIPS 186-5 sends a randomized signer back to draw a fresh , and makes a deterministic signer output failure, because re-deriving from the same key and message would reproduce the same and (National Institute of Standards and Technology, 2023). The recovery formula itself uses only the two signatures, the two message hashes, and the group order ; it does not use the generator or the public key . A real attacker still uses the public key to identify which signatures belong to the same signer; the formula above just no longer needs it once that pairing is known.
FIPS 186-5 therefore requires a per-message secret number for each signature. The standard allows to be generated randomly or deterministically from the message hash and the private key; in either case must remain secret and must not repeat across distinct message hashes under the same private key (National Institute of Standards and Technology, 2023).
The attack is mechanical on a toy prime-order group. The snippet below uses the order- subgroup of generated by , a private key , and the same nonce for two different message hashes and . Group exponentiation stands in for scalar multiplication, and is the integer reduced modulo . In real ECDSA, is an elliptic-curve point and is its -coordinate reduced modulo . The toy compresses that to R mod N because a multiplicative-group element has no coordinate pair. The attack is insensitive to how is derived, so the toy algebra and the secp256k1 algebra are identical.
# Toy ECDSA nonce-reuse attack on the order-11 subgroup of (Z/23)^*.# g = 4 has order 11 modulo 23 (check: 4 = 2^2, and (Z/23)^* has order 22).# The attacker sees two signatures (r, s1) and (r, s2) under the same nonce k# and recovers the private key d from the two signatures alone.p = 23N = 11g = 4
# Confirm that g has order N in (Z/p)^*.assert pow(g, N, p) == 1
# Signer's keypair.d = 7y = pow(g, d, p) # y = g^d mod p is the public "point"
# Two signatures under the SAME nonce on different message hashes.k = 6z1 = 3z2 = 5
R = pow(g, k, p) # "scalar multiplication" kG in the subgroupr = R % Ns1 = (pow(k, -1, N) * (z1 + r * d)) % Ns2 = (pow(k, -1, N) * (z2 + r * d)) % N
# Real ECDSA rejects r = 0 and the recovery needs s1 != s2.assert r != 0assert s1 != s2
# Attacker sees (r, s1, z1) and (r, s2, z2). Recover k, then d.k_rec = ((z1 - z2) * pow(s1 - s2, -1, N)) % Nd_rec = ((s1 * k_rec - z1) * pow(r, -1, N)) % N
print(d, d_rec, d == d_rec)# ==> 7 7 TrueThe recovered matches the original, as the marker shows. The algebraic fix is straightforward: use a correct per-message secret number as specified in FIPS 186-5, and never reuse the same under the same private key (National Institute of Standards and Technology, 2023). The engineering fix still requires care: the nonce path has to be protected against RNG failure, side channels, and fault injection, since any of those can leak or force a repeat without the signer noticing.
The attack has been run in the field. Sony’s PS3 code-signing key fell in 2010, after fail0verflow showed the console’s ECDSA signer used a fixed value in place of a per-signature nonce (fail0verflow, 2010). On the Bitcoin chain the same mistake is measurable: Bos and colleagues found 158 public keys that had signed more than once under the same nonce (Bos et al., 2014). One address appears to have collected over 59 bitcoin from ten of them between March and October 2013. Both cases were spotted the way the attacker spots them here, by a repeated .
Why textbook shortcuts fail EUF-CMA
Section titled “Why textbook shortcuts fail EUF-CMA”-
Textbook RSA. The multiplicative forgery in the opening snippet shows that an EUF-CMA adversary who obtains any two signatures can forge a third on their product. The fix is full-domain hash RSA: sign instead of , which removes the message-level relation the attacker exploited, even though RSA exponentiation itself stays multiplicative.
-
ECDSA with broken nonce generation. The nonce-reuse derivation above recovers the private key from two signatures under the same . The fix is strict per-message nonce discipline: either generate uniformly with explicit rejection at the boundary, or derive deterministically from the private key and message hash via an approved deterministic procedure such as RFC 6979 (National Institute of Standards and Technology, 2023). Deterministic generation eliminates dependence on fresh randomness for each signature; it does not eliminate the requirement for side-channel and fault-injection hardening, since either route still has to keep secret at runtime.
-
Nonces biased in any predictable way. Even without reuse, nonces sampled from a distribution biased toward a fixed bit pattern, a short bit length, or any other structured subset leak the private key through a lattice attack on the hidden number problem (Boneh & Venkatesan, 1996; Nguyen & Shparlinski, 2003). The fix is uniform sampling with explicit rejection at the boundary, or deterministic derivation from the message and the key.
EUF-CMA is stricter than keeping the private key secret. The signer loses the game if any computed quantity gives the adversary a path to forge. A product of signatures does that without revealing at all. A reused or biased nonce does it the other way, by letting the adversary compute from published signatures, even though the signer never transmits it.
Tradeoffs across post-quantum signature families
Section titled “Tradeoffs across post-quantum signature families”Post-quantum signature schemes in the book target at least the EUF-CMA game, and make different tradeoffs on key size, signature size, and verification cost.
| Family | Scheme (NIST level) | Verification key | Signature |
|---|---|---|---|
| Lattice | ML-DSA-44 (2) | 1,312 B | 2,420 B |
| Hash | SLH-DSA-128s (1) | 32 B | 7,856 B |
| Hash | SLH-DSA-256f (5) | 64 B | 49,856 B |
| Isogeny | SQIsign (1) | 83 B | 200 B |
Sizes are from FIPS 204 (National Institute of Standards and Technology, 2024a), FIPS 205 (National Institute of Standards and Technology, 2024b), and the SQIsign round-3 specification (The SQIsign Team, 2026). The two SLH-DSA rows are its extremes: verification keys are 32, 48, or 64 bytes as the security level rises, and no parameter set signs longer than SLH-DSA-256f.
-
Lattice-based. ML-DSA (FIPS 204) is NIST’s standardized general-purpose lattice-based signature scheme. Chapter 12 builds it from scratch against the FIPS 204 vectors, and Part V deploys it. FN-DSA (Fast-Fourier lattice-based digital signature algorithm, in development as FIPS 206 (Perlner, 2025)), derived from the pre-standard construction Falcon, is the smaller-signature lattice alternative at the cost of a more delicate signer. This edition discusses it but does not build it.
-
Hash-based. SLH-DSA (FIPS 205) has the largest signatures in the table. Its security rests on hash-function, extendable-output-function (XOF), and pseudorandom-function (PRF) assumptions rather than algebraic assumptions such as factoring, discrete log, or structured lattices. FIPS 205 assigns its EUF-CMA security categories under the bound that each key pair signs at most messages (National Institute of Standards and Technology, 2024b). Chapter 17 builds SLH-DSA.
-
Isogeny-based. SQIsign advanced to Round 3 of NIST’s Additional Digital Signatures process in May 2026 (National Institute of Standards and Technology, 2026) and is not yet a FIPS standard. Its size advantage is the exceptionally small combined public-key-plus-signature footprint. This is not strictly the smallest signature alone among the on-ramp candidates (UOV’s Round 2 spec lists shorter level-I signatures), but it is the smallest combined size. The tradeoff is a more complex and slower implementation profile than ML-DSA or FN-DSA. Chapter 23 builds SQIsign.
None of the three treats the raw message as the algebraic object being signed. Each hashes or encodes the message into a digest, a Fiat-Shamir challenge, or a transcript before the scheme-specific signing relation is checked, and each targets EUF-CMA or the stronger sEUF-CMA rather than a weaker unforgeability game.
Hash-based signatures sit outside the factoring and discrete-log families entirely. Their security rests on the working-level hash-function assumptions Chapter 3 treated as quantum attack targets, with no algebraic trapdoor. The historical problem is that the earliest hash-based constructions were stateful: the signer had to track which one-time keys had been used. That makes backup, restore, and multi-machine signing dangerous unless the state is coordinated so that one-time keys are never reused. Stateful schemes XMSS and LMS, standardized by NIST in SP 800-208, still exist for constrained environments where state management is feasible (Cooper et al., 2020). The stateless hash-based standard is SLH-DSA from FIPS 205, which eliminates state at the cost of larger signatures (National Institute of Standards and Technology, 2024b). Chapter 14 builds Lamport’s one-time signature and the Merkle tree that turns it into a many-time scheme, Chapter 15 builds the XMSS family, and Chapter 17 builds SLH-DSA.
Where Part I ends and Part II picks up
Section titled “Where Part I ends and Part II picks up”Part I has been a survey of what breaks and why. Chapter 1 set the timeline, Chapter 2 and Chapter 3 the algebra and the hard problems, Chapter 4 the two classical schemes Shor’s algorithm breaks, and Chapter 5 the key-establishment side of the replacement. This chapter closed the other side: the security definition every signature scheme in the book targets, and two ways a scheme can miss it. Textbook RSA lets an adversary forge without ever learning the private key. ECDSA with a repeated nonce is worse, and hands the key over from published signatures alone.
Part II builds the first replacement family from the ground up. Chapter 7 introduces lattices, Chapter 8 the LWE problem, and Chapter 9 its ring and module variants. Chapter 10 assembles Regev encryption and Chapter 11 ML-KEM against the FIPS 203 vectors. Chapter 12 builds ML-DSA, where the Fiat-Shamir-with-aborts construction and the SelfTargetMSIS assumption named above become code. Chapter 13 closes the Part with what it would cost an attacker to break any of it.
Exercises
Section titled “Exercises”-
Forge under textbook RSA by hand. Using the 64-bit modulus from the opening snippet, pick two 64-bit integers and and verify numerically that equals . Then state in one sentence why, in the random-oracle model, an FDH-RSA adversary cannot efficiently find a fresh whose full-domain hash satisfies .
-
Recover from nonce reuse. Using the nonce-reuse snippet as a template, pick a different private key and a different nonce . Produce two signatures on two distinct message hashes and run the recovery formula. Confirm that the recovered matches the original. Then set and explain in one sentence why the attack fails when the two message hashes are equal.
-
State EUF-CMA in your own words. Write a four-sentence statement of the EUF-CMA game that another student could use to look up the original paper. The statement must name the challenger, the signing oracle, the win condition on the forgery, and the advantage function.
-
Stateful versus stateless by counterexample. Explain in two sentences why a stateful hash-based signature scheme cannot be safely backed up across two machines without coordination. Name one NIST-approved stateful hash-based scheme (from SP 800-208) and one NIST stateless hash-based standard (from FIPS 205).
-
Schnorr on
secp256k1under long-lived key exposure. Restate the chapter’s EUF-CMA game against Schnorr onsecp256k1(Wuille et al., 2020) in the deployment setting where the verification key was published on a public ledger in year and never rotated. An adversary reads from the ledger at and waits. At year a cryptographically relevant quantum computer becomes available. The adversary runs Shor’s algorithm (Shor, 1994) on and recovers the secret scalar . State the EUF-CMA win condition the adversary now satisfies on a fresh message . Then derive the key-exposure window length as a function of and . Evaluate it at and . The first is a Taproot-era P2TR output, in which BIP-341 places the public key directly in the output script (Wuille, Nick, & Towns, 2020). The second is CNSSP 15’s CNSA 2.0 deadline, which is a migration target rather than a CRQC arrival forecast.
Worked solutions and editorial notes for these exercises are in Appendix D, Chapter 6. A separate track, for rebuilding rather than reading: the package exercises/ch06-signature-attacks has every function the chapter teaches replaced by a stub. Run PQC_IMPL=exercises pytest tests/ch06 to grade your version against the suite that proves the reference one.
References
Section titled “References”Last updated: