<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Parag Mali - tag: slh-dsa</title><description>Posts tagged slh-dsa.</description><link>https://paragmali.com/</link><language>en-US</language><lastBuildDate>Sat, 25 Jul 2026 08:57:53 GMT</lastBuildDate><atom:link href="https://paragmali.com/tags/slh-dsa/rss.xml" rel="self" type="application/rss+xml"/><item><title>How SLH-DSA Would Break: The Signature That Can Only Fall If a Hash Falls First</title><link>https://paragmali.com/blog/how-slh-dsa-would-break-the-signature-that-can-only-fall-if-/</link><guid isPermaLink="true">https://paragmali.com/blog/how-slh-dsa-would-break-the-signature-that-can-only-fall-if-/</guid><description>SLH-DSA has almost no attack surface of its own. A structural tour of FORS, WOTS+ hypertrees and tweakable hashes, and why it fails only if SHA-2 or SHAKE does.</description><pubDate>Sat, 18 Jul 2026 00:00:00 GMT</pubDate><content:encoded>
**SLH-DSA (FIPS 205) is NIST&apos;s conservative post-quantum signature, and it is built from nothing but tweakable-hash calls** -- FORS few-time signatures under a hypertree of WOTS+ Merkle trees -- so it has almost no attack surface of its own. Its unforgeability reduces to a short list of hash properties (PRF, SM-TCR, SM-DSPR, ITSR), and the shipped *simple* variant rests on a random-oracle heuristic bought for a factor-three speed-up. The strongest structural result against it, a category-5 SHA-256 margin shortfall, produces no forgery and traces straight to the hash&apos;s Merkle-Damgard structure. Shor cannot touch it and Grover is already priced into the digest size, so its most likely structural break is a break of SHA-2 or SHAKE: it fails only if the hash falls first.
&lt;h2&gt;1. A Signature With Nothing of Its Own to Break&lt;/h2&gt;
&lt;p&gt;Every other digital signature standard has a soft spot you can name. RSA has &lt;a href=&quot;https://paragmali.com/blog/how-rsa-would-break-why-factoring-is-the-slow-path-and-coppe/&quot; rel=&quot;noopener&quot;&gt;integer factoring&lt;/a&gt;. ECDSA has the &lt;a href=&quot;https://paragmali.com/blog/the-log-was-never-the-weak-part-how-discrete-log-cryptograph/&quot; rel=&quot;noopener&quot;&gt;discrete logarithm&lt;/a&gt;. The two other post-quantum signatures NIST has standardized or drafted -- ML-DSA and FN-DSA -- rest on &lt;a href=&quot;https://paragmali.com/blog/two-standards-one-lattice-how-ml-kem-and-ml-dsa-would-break/&quot; rel=&quot;noopener&quot;&gt;structured lattices&lt;/a&gt; [@fips204, @oqs_falcon]. Each of those is a specific piece of mathematics an adversary can attack on its own terms, and each has a research community devoted to doing exactly that.&lt;/p&gt;
&lt;p&gt;SLH-DSA has none of them. No ring, no group, no lattice, no number theory of any kind. Its designers built it that way on purpose, so that it would have almost nothing of its own to attack. That choice is what makes a simple-sounding question strangely hard to answer: if a signature scheme has no mathematics of its own, &lt;em&gt;how&lt;/em&gt; would it ever break?&lt;/p&gt;
&lt;p&gt;That question is the whole article, and the answer is the thesis. SLH-DSA is the Stateless Hash-Based Digital Signature Algorithm, standardized by NIST as FIPS 205 on 13 August 2024 [@fips205]. It is assembled entirely from calls to a hash function, so its security rests on no hard number-theoretic problem -- only on a short, named list of properties of that hash.&lt;/p&gt;
&lt;p&gt;Drive the analysis down through the construction and you never hit an algebraic layer where a clever attacker could set up shop. You hit the hash, and you stop. The scheme fails only if the hash falls first.&lt;/p&gt;

The standard security target for a signature scheme. An adversary who may request signatures on any messages of its choosing still cannot produce a single valid signature on any *new* message. Every reduction in this article is ultimately protecting EUF-CMA: to &quot;break&quot; SLH-DSA means to forge one signature the key owner never issued.
&lt;p&gt;One fence needs setting before we start. This is a structural analysis -- it asks how the &lt;em&gt;mathematics&lt;/em&gt; of SLH-DSA would fail, not the hardware it runs on, the code that implements it, or the random-number generator that feeds it. Those failure modes are real, and one even carries a headline-grabbing name (SLasH-DSA, a Rowhammer attack whose own authors call the scheme &quot;theoretically sound&quot;) [@slash25].&lt;/p&gt;
&lt;p&gt;But a bit flipped in DRAM is not cryptanalysis, and such attacks belong to this article&apos;s empirical sibling, not here. We are asking whether the design itself can be broken with pencil, paper, and computation.&lt;/p&gt;
&lt;p&gt;One apparent exception is worth flagging now. Everywhere else in this series, the decisive structural threat is a quantum computer running &lt;a href=&quot;https://paragmali.com/blog/how-q-day-breaks-everything-shors-algorithm-and-the-simultan/&quot; rel=&quot;noopener&quot;&gt;Shor&apos;s algorithm&lt;/a&gt;, which dismantles factoring and discrete logs outright. Against SLH-DSA, Shor simply has nothing to grab -- a fact so central that a later section is spent on exactly why. To see how little there is to attack, you first have to see what the thing is made of.&lt;/p&gt;
&lt;h2&gt;2. What SLH-DSA Actually Is: FORS Under a Hypertree of WOTS+&lt;/h2&gt;
&lt;p&gt;Open the box. A signature you can verify with nothing but a hash function -- how is that even assembled? FIPS 205 answers top-down, and the shape is easier than the acronyms make it sound [@fips205, @openssl35].&lt;/p&gt;
&lt;p&gt;The public key is tiny: essentially a single hash value (the root of a giant tree) together with a public seed, just &lt;code&gt;2n&lt;/code&gt; bytes, where &lt;code&gt;n&lt;/code&gt; is the digest size [@fips205].&lt;/p&gt;
&lt;p&gt;Signing has three stages. First, a pseudorandom function turns the secret key and the message into a randomizer, and a hash binds that randomizer, the public key, and the message into a message digest plus an index. Second, the message digest is signed by a &lt;strong&gt;FORS&lt;/strong&gt; few-time signature at the bottom of the structure. Third, the FORS public key is authenticated up a &lt;strong&gt;hypertree&lt;/strong&gt; -- a tree of Merkle trees -- whose layers are stitched together by &lt;strong&gt;WOTS+&lt;/strong&gt; one-time signatures.&lt;/p&gt;
&lt;p&gt;Verification just recomputes hashes up to the root and checks that it matches the public key.&lt;/p&gt;

A tree of Merkle trees, stacked `d` layers deep (`d` is 7, 8, 17, or 22 in the standardized sets). Each layer is an ordinary Merkle tree whose leaves are WOTS+ public keys; a WOTS+ signature in one layer signs the root of the tree in the layer below. The single root at the very top is the SLH-DSA public key. The bottom layer can hold up to `2^68` leaves in the largest parameter set -- a quantity deliberately distinct from the signature budget below, and large enough to make an accidental leaf collision astronomically rare.The `2^68` leaf count belongs to SLH-DSA-256f (hypertree height `h = 68`); across the twelve sets the height is 63, 64, 66, or 68, so the leaf count is `2^63` to `2^68`. Do not confuse it with the `2^64`-signature budget discussed in Section 10 -- they are different numbers that happen to sit near each other [@fips205].

A hash call keyed, per call, by two extra inputs beyond its message: an `n`-byte public seed and a 32-byte address (`ADRS`) that names exactly which node of which tree at which layer is being hashed. Because every location in the whole structure gets a different address, every call is effectively a different keyed function. FIPS 205 uses three tweakable hashes, written `F`, `H`, and `T_l`, for every internal hash in the scheme; this per-call keying is what defeats multi-target attacks, as Section 6 makes precise.
&lt;p&gt;Put the three layers in one picture and the absence of anything algebraic becomes visible.&lt;/p&gt;

flowchart TD
    subgraph L1[&quot;Layer 1 -- FORS few-time signature&quot;]
      A[&quot;Message digest md&quot;] --&amp;gt; B[&quot;FORS signs md&quot;]
      B --&amp;gt; C[&quot;FORS public key becomes a leaf&quot;]
    end
    subgraph L2[&quot;Layer 2 -- hypertree of WOTS plus Merkle trees&quot;]
      C --&amp;gt; D[&quot;WOTS plus signs each subtree root&quot;]
      D --&amp;gt; E[&quot;Merkle authentication paths climb d layers&quot;]
    end
    subgraph L3[&quot;Layer 3 -- the public key&quot;]
      E --&amp;gt; F[&quot;Top hypertree root plus public seed&quot;]
      F --&amp;gt; G[&quot;Public key, only 2n bytes&quot;]
    end
    TH[&quot;Every box is computed by a tweakable hash keyed by address plus public seed&quot;] -.-&amp;gt; B
    TH -.-&amp;gt; D
    TH -.-&amp;gt; F
&lt;p&gt;That is the entire scheme. There is no algebra anywhere -- no ring, group, or lattice, only hashing.OpenSSL&apos;s manual page for SLH-DSA documents the design as a fixed set of internal tweakable-hash roles -- seven hash-related functions in all -- and states plainly that the scheme &quot;relies only on hash functions.&quot; [@openssl35] The contrast with the rest of the field is the thing to internalize before we go on.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scheme&lt;/th&gt;
&lt;th&gt;Security basis&lt;/th&gt;
&lt;th&gt;Algebraic surface&lt;/th&gt;
&lt;th&gt;Stateful?&lt;/th&gt;
&lt;th&gt;Public key&lt;/th&gt;
&lt;th&gt;Signature&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;SLH-DSA&lt;/td&gt;
&lt;td&gt;Hash only (SHA-2/SHAKE)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;None&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;32 to 64 B&lt;/td&gt;
&lt;td&gt;7,856 to 49,856 B&lt;/td&gt;
&lt;td&gt;Final, FIPS 205 (2024) [@fips205, @oqs_slh]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;XMSS / LMS&lt;/td&gt;
&lt;td&gt;Hash only&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;None&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt; (leaf reuse)&lt;/td&gt;
&lt;td&gt;tens of B&lt;/td&gt;
&lt;td&gt;a few KB&lt;/td&gt;
&lt;td&gt;Approved, SP 800-208 [@rfc8391, @sp800208]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ML-DSA&lt;/td&gt;
&lt;td&gt;Module-LWE / Module-SIS&lt;/td&gt;
&lt;td&gt;Lattice&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;1,312 to 2,592 B&lt;/td&gt;
&lt;td&gt;2,420 to 4,627 B&lt;/td&gt;
&lt;td&gt;Final, FIPS 204 (2024) [@fips204, @oqs_mldsa]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FN-DSA / Falcon&lt;/td&gt;
&lt;td&gt;NTRU lattice&lt;/td&gt;
&lt;td&gt;Lattice&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;897 to 1,793 B&lt;/td&gt;
&lt;td&gt;666 to 1,462 B&lt;/td&gt;
&lt;td&gt;Draft, FIPS 206 [@oqs_falcon]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Read down the &quot;algebraic surface&quot; column. SLH-DSA and its stateful cousins are the only rows that say &lt;strong&gt;None&lt;/strong&gt;. Every other scheme carries a mathematical object that could, in principle, crack on its own terms. SLH-DSA pays for that emptiness in size and signing speed, and buys in exchange an attack surface that is nothing but its hash.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The only cryptographic ingredient in SLH-DSA is the hash. FORS, WOTS+, the Merkle trees, the hypertree, even the pseudorandom functions that derive its secrets -- every one is a particular pattern of calls to a hash function. There is no second ingredient for an attacker to reach for.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If the whole scheme is just &quot;hash it together correctly,&quot; where did that idea come from -- and has anyone, in half a century of trying, ever managed to break it?&lt;/p&gt;
&lt;h2&gt;3. Only a Hash: Lamport, Merkle, and the First Signatures&lt;/h2&gt;
&lt;p&gt;At a coffee house in Berkeley around 1975, Whitfield Diffie described a problem to Leslie Lamport: how could someone sign a digital document so that anyone can check the signature and no one can forge it? Lamport proposed a solution on the spot. By his own account it was the first digital signature algorithm, and it used no number theory at all -- just a one-way function [@lamport79].Lamport wrote the idea up formally in 1979 as &lt;em&gt;Constructing Digital Signatures from a One-Way Function&lt;/em&gt;, an internal report he notes &quot;is cited in the cryptography literature and is considered significant.&quot; [@lamport79]&lt;/p&gt;
&lt;p&gt;That casual choice is the genetic marker of the entire family. From the very first idea, this branch of cryptography needed no factoring and no discrete logs. It needed a hash.&lt;/p&gt;

A key pair that can sign exactly one message safely. Lamport&apos;s version publishes hashes of secret values as the public key. To sign, the owner reveals the right secrets; a verifier hashes them and checks against the public key. Because inverting the hash is infeasible, only the owner can produce the preimages -- but the moment a second message is signed, enough secrets leak to forge a third.
&lt;p&gt;Here is the whole scheme in code, including the fatal reuse: sign one message and it is secure; sign a second with the same key and an attacker can forge a third the owner never touched.&lt;/p&gt;
&lt;p&gt;{`
// toyHash is NOT cryptographic. It only illustrates a one-way function.
function toyHash(x) {
  let h = 2166136261 &amp;gt;&amp;gt;&amp;gt; 0;
  for (const ch of x) {
    h = Math.imul(h ^ ch.charCodeAt(0), 16777619) &amp;gt;&amp;gt;&amp;gt; 0;
  }
  return (&quot;00000000&quot; + h.toString(16)).slice(-8);
}&lt;/p&gt;
&lt;p&gt;const idx = [0, 1, 2, 3]; // a tiny 4-bit message&lt;/p&gt;
&lt;p&gt;function keygen() {
  const sk = [], pk = [];
  idx.forEach(function (i) {
    const s0 = &quot;secret_&quot; + i + &quot;&lt;em&gt;for_bit_value_0&quot;;
    const s1 = &quot;secret&lt;/em&gt;&quot; + i + &quot;_for_bit_value_1&quot;;
    sk.push([s0, s1]);
    pk.push([toyHash(s0), toyHash(s1)]); // publish the hashes
  });
  return { sk: sk, pk: pk };
}&lt;/p&gt;
&lt;p&gt;function sign(sk, bits) { return bits.map(function (b, i) { return sk[i][b]; }); }
function verify(pk, bits, sig) {
  return bits.every(function (b, i) { return toyHash(sig[i]) === pk[i][b]; });
}&lt;/p&gt;
&lt;p&gt;const keys = keygen();
const m1 = [0, 1, 0, 1];
const sig1 = sign(keys.sk, m1);
console.log(&quot;first message verifies:&quot;, verify(keys.pk, m1, sig1));&lt;/p&gt;
&lt;p&gt;// The mistake: reuse the SAME key for a second, complementary message.
const m2 = [1, 0, 1, 0];
const sig2 = sign(keys.sk, m2);&lt;/p&gt;
&lt;p&gt;// The attacker has now seen a valid secret for BOTH values of every bit.
const leaked = idx.map(function (i) {
  const row = [];
  row[m1[i]] = sig1[i];
  row[m2[i]] = sig2[i];
  return row;
});&lt;/p&gt;
&lt;p&gt;// Forge a THIRD message that was never signed by the owner.
const forgery = [1, 1, 0, 0];
const forgedSig = forgery.map(function (b, i) { return leaked[i][b]; });
console.log(&quot;forged third message verifies:&quot;, verify(keys.pk, forgery, forgedSig));
`}&lt;/p&gt;
&lt;p&gt;Run it and both lines print &lt;code&gt;true&lt;/code&gt;. The security proof does not degrade gracefully after a second signature -- it evaporates. That single fact, &quot;one key signs once,&quot; is the hazard the next fifty years of research engineered around. Notice what it is &lt;em&gt;not&lt;/em&gt;: it is not a weakness in the hash, and not an algebraic shortcut. It is a &lt;em&gt;usage&lt;/em&gt; rule. Break the rule and you leak secrets; keep it and there is nothing to attack but the one-way function itself.&lt;/p&gt;
&lt;p&gt;Lamport&apos;s signatures are also large and clumsy: fresh keys for every message, thousands of bytes each. The fix came from Ralph Merkle, whose late-1970s Stanford work was published canonically as &lt;em&gt;A Certified Digital Signature&lt;/em&gt; at CRYPTO 1989 [@merkle89].&lt;/p&gt;

A binary tree in which every leaf is the hash of a one-time public key and every internal node is the hash of its two children. Only the single root hash is published as the long-lived public key. To prove a leaf belongs under that root, a signer supplies the sibling hashes along the path from leaf to root -- the authentication path -- and the verifier recomputes the root. This turns many single-use keys into one small, reusable public key.
&lt;p&gt;Merkle&apos;s tree is the structural move that makes hash-based signatures usable at all, and it is still the spine of every scheme in this article, up to and including SLH-DSA. Its defining property, the reason the whole line proved immortal, is that it &quot;only depends on the existence of secure hash functions.&quot; No conjecture about factoring, no assumption about lattices. A hash.&lt;/p&gt;

timeline
    title From Lamport to FIPS 205 -- only ever a hash
    1979 : Lamport one-time signatures
    1989 : Merkle trees and the Merkle signature scheme
    2011 : XMSS, a practical stateful Merkle scheme
    2013 : WOTS+, a compact one-time signature
    2015 : SPHINCS buys statelessness
    2019 : SPHINCS+ framework and tweakable hashes
    2024 : FIPS 205 standardizes SLH-DSA
&lt;p&gt;The historical spine of the thesis is worth stating flatly: roughly fifty years after Lamport, there is still no structural break of the Merkle hash-tree construction. There never was an algebraic surface to attack, so no one has attacked one. But Lamport&apos;s key can sign only once, and Merkle&apos;s fix -- brilliant as it is -- quietly introduced a hazard that would dog the field for the next thirty years.&lt;/p&gt;
&lt;h2&gt;4. WOTS+ and XMSS: Powerful, Provable, and Dangerously Stateful&lt;/h2&gt;
&lt;p&gt;The hazard has a name: &lt;strong&gt;state&lt;/strong&gt;. Merkle&apos;s tree is safe forever as a public key, but the &lt;em&gt;signer&lt;/em&gt; now carries a fragile counter. It must remember which one-time leaves it has already spent, because each leaf is a one-time key and reusing one re-opens the Lamport failure from the last section.&lt;/p&gt;
&lt;p&gt;A backup restore, a virtual-machine clone, a crash that rolls back the counter -- any of these can silently reuse a leaf and leak secrets. Why is a signer that must &lt;em&gt;remember&lt;/em&gt; something a cryptographic landmine? Because state is the one part of a signing system that ordinary operations routinely corrupt.&lt;/p&gt;
&lt;p&gt;Two refinements around 2011 to 2013 pushed this stateful design to its high-water mark. Andreas Hulsing&apos;s WOTS+ shrank the one-time leaf, and XMSS made the tree practical and provable.&lt;/p&gt;

A one-time signature that replaces Lamport&apos;s &quot;one secret per bit&quot; with hash chains. The message digest is written in base `w`; each base-`w` digit gets its own chain, whose start is a secret and whose end (after `w-1` hashes) is public. A signature reveals each chain iterated partway, to the digit&apos;s value. A separate checksum block prevents an attacker from advancing a chain to forge a larger digit. Larger `w` means fewer, longer chains -- smaller signatures but slower signing.
&lt;p&gt;The checksum is the clever part, and it is worth watching it work. An attacker who sees a signature can always hash &lt;em&gt;forward&lt;/em&gt; to forge a larger message digit. The checksum is constructed so that raising any message digit forces a checksum digit to &lt;em&gt;fall&lt;/em&gt; -- which would require running a hash chain &lt;em&gt;backward&lt;/em&gt;, that is, inverting the hash. That is the block.&lt;/p&gt;
&lt;p&gt;{`
// Illustrative only: toyHash stands in for a real one-way function.
function toyHash(x){ let h = 2166136261 &amp;gt;&amp;gt;&amp;gt; 0; for (const c of String(x)) { h = Math.imul(h ^ c.charCodeAt(0), 16777619) &amp;gt;&amp;gt;&amp;gt; 0; } return &quot;h&quot; + (h &amp;gt;&amp;gt;&amp;gt; 0).toString(16).slice(0, 6); }&lt;/p&gt;
&lt;p&gt;const w = 16; // base-w digits, values 0..15
function chain(start, steps){ let v = start, k = steps; while (k &amp;gt; 0) { v = toyHash(v); k = k - 1; } return v; }
function toBaseW(num, len){ const out = []; let t = num, k = len; while (k &amp;gt; 0) { out.unshift(t % w); t = Math.floor(t / w); k = k - 1; } return out; }
function checksum(ds){ let c = 0; ds.forEach(function (x) { c += (w - 1) - x; }); return c; }&lt;/p&gt;
&lt;p&gt;// One hash chain per digit: message digits, then checksum digits.
const msg  = [5, 2];
const full = msg.concat(toBaseW(checksum(msg), 2));      // [5, 2, 1, 7]
const sk   = full.map(function (&lt;em&gt;, i) { return &quot;wots_secret&lt;/em&gt;&quot; + i; });
const pk   = sk.map(function (s) { return chain(s, w - 1); });
const sig  = full.map(function (d, i) { return chain(sk[i], d); });&lt;/p&gt;
&lt;p&gt;// An attacker can only hash FORWARD from a published signature value.
function forwardOnly(sigValue, fromSteps, toSteps){
  if (fromSteps &amp;gt; toSteps) return null;                 // backward means inverting the hash
  return chain(sigValue, toSteps - fromSteps);
}&lt;/p&gt;
&lt;p&gt;// Try to raise the first message digit 5 -&amp;gt; 9. Trivial on its own chain...
const target     = [9, 2];
const targetFull = target.concat(toBaseW(checksum(target), 2));  // [9, 2, 1, 3]
const forged     = targetFull.map(function (d, i) { return forwardOnly(sig[i], full[i], d); });
const stuck      = forged.some(function (v) { return v === null; });&lt;/p&gt;
&lt;p&gt;console.log(&quot;honest signature verifies:&quot;, sig.every(function (s, i) { return chain(s, (w - 1) - full[i]) === pk[i]; }));
console.log(&quot;checksum digits, honest vs forged:&quot;, full.slice(2), &quot;vs&quot;, targetFull.slice(2));
console.log(&quot;forgery buildable by hashing forward only?&quot;, !stuck);
`}&lt;/p&gt;
&lt;p&gt;The forged checksum digits drop from &lt;code&gt;[1, 7]&lt;/code&gt; to &lt;code&gt;[1, 3]&lt;/code&gt;, so the last chain would have to run backward. The attacker is stuck. WOTS+ gets this guarantee with a tight, standard-model proof, and it survives unchanged as the one-time layer inside SLH-DSA today.&lt;/p&gt;
&lt;p&gt;XMSS wraps WOTS+ leaves in a modern Merkle tree with keyed hashing and forward-secure key derivation, and proves security on what its authors call minimal assumptions [@xmss11]. The RFC that standardized it states the property that matters for our thesis in the bluntest possible terms.&lt;/p&gt;

XMSS &quot;provides cryptographic digital signatures without relying on the conjectured hardness of mathematical problems. Instead, it is proven that it only relies on the properties of cryptographic hash functions ... and is even secure when the collision resistance of the underlying hash function is broken.&quot; -- RFC 8391 [@rfc8391]
&lt;p&gt;Read that last clause twice. XMSS keeps working &lt;em&gt;even if&lt;/em&gt; an attacker can find hash collisions, because its proof leans only on the weaker property of second-preimage resistance.Source hygiene note: WOTS+&apos;s ePrint identifier is disputed in the literature, so it is cited here by its DOI rather than an ePrint number [@wotsplus13]. That is what &quot;minimal assumptions&quot; buys: a scheme whose safety margin degrades slowly, not suddenly, as the hash weakens. It is also the first hint of why SLH-DSA leans on second-preimage and target-collision resistance rather than plain collision resistance.&lt;/p&gt;
&lt;p&gt;And yet XMSS is still stateful. The signer must persist and advance a leaf index for every signature, and any reuse collapses security. This is exactly why NIST standardized the stateful schemes only behind a bright warning fence.&lt;/p&gt;

XMSS, its multi-tree variant XMSS^MT, and the Leighton-Micali schemes LMS and HSS were not retired. NIST approved them in SP 800-208 (2020) for settings where the signer&apos;s state can be tightly controlled -- above all firmware and code signing [@sp800208, @rfc8554]. LMS makes the same quantum argument as XMSS: hash-based signatures &quot;would still be secure even if it proves feasible for an attacker to build a quantum computer&quot; [@rfc8554]. The price of their smaller, faster signatures is the &quot;never reuse a leaf&quot; rule, enforced operationally rather than mathematically. They are the right tool when you sign rarely from one controlled machine, and the wrong tool for a general, high-fan-out protocol.
&lt;p&gt;If reusing a leaf is the entire danger, the obvious question is whether you could pick leaves in a way that needs no memory at all -- so that accidental reuse is not forbidden by a rule, but negligibly rare by construction.&lt;/p&gt;
&lt;h2&gt;5. SPHINCS: Buying Statelessness With Size&lt;/h2&gt;
&lt;p&gt;You cannot make state safe. Every operational path that touches a counter -- backups, snapshots, failovers -- is a path that can corrupt it. So the 2015 breakthrough did not try to protect the state. It deleted it.&lt;/p&gt;
&lt;p&gt;The scheme was SPHINCS, from Bernstein, Hopwood, Hulsing, Lange, and five co-authors, presented at EUROCRYPT 2015 [@sphincs15]. The insight is the first half of this article&apos;s second aha moment, and it is genuinely surprising: you can sign safely without remembering what you already signed, &lt;em&gt;if you are willing to pay in size.&lt;/em&gt;&lt;/p&gt;

A signing scheme is stateless when it holds no secret internal state that must change from one signature to the next. The same signing operation, repeated, is always safe. Statelessness is what lets a signature be dropped into any protocol without a fragile counter to persist, roll back, or clone -- the exact hazard that dogged every stateful predecessor.
&lt;p&gt;Here is how you buy it. Make the hypertree so astronomically large that its leaf space is effectively unlimited, then pick the signing leaf &lt;em&gt;pseudorandomly&lt;/em&gt; from the message itself rather than from a counter. At the bottom of the chosen leaf, sign with a &lt;em&gt;few-time&lt;/em&gt; signature -- one that tolerates a small number of accidental repeats -- instead of a strictly one-time one.&lt;/p&gt;
&lt;p&gt;Size the whole thing so that, across an enormous budget of signatures, the probability of reusing a leaf enough times to matter stays negligible. No memory required: the &quot;which leaf&quot; question is answered by hashing the message, not by counting.&lt;/p&gt;

A signature key that stays secure across a small, bounded number of uses before its guarantee erodes -- a middle point between a one-time key (safe for exactly one message) and an unlimited key. Because SPHINCS selects its bottom key pseudorandomly, an occasional repeat is inevitable, so the bottom layer must tolerate a few uses. SPHINCS used a few-time scheme called HORST; SLH-DSA replaces it with FORS.
&lt;p&gt;The trade was concrete, and its size story matters for the rest of the article. SPHINCS shipped a single instantiation, SPHINCS-256, whose signatures are about 41 KB and which its own paper designed to provide &quot;&lt;code&gt;2^128&lt;/code&gt; security even against attackers equipped with quantum computers&quot; [@sphincs15].SPHINCS was parameterized for up to &lt;code&gt;2^50&lt;/code&gt; signatures per key pair; the standardized SLH-DSA later raised the design budget to as many as &lt;code&gt;2^64&lt;/code&gt; [@huelsingblog].&lt;/p&gt;
&lt;p&gt;That &lt;code&gt;2^128&lt;/code&gt;-quantum figure (and the &lt;code&gt;2^256&lt;/code&gt;-classical it implies, from its 256-bit hashes) is the AES-256 ballpark -- NIST&apos;s category 5, the &lt;em&gt;highest&lt;/em&gt; security tier, not the lowest. Keep that anchor in hand: the famous 41 KB is a category-5-class number. When the next section reports SPHINCS+ shrinking the signature, the honest comparison has to hold the security level fixed rather than quietly sliding to an easier one.&lt;/p&gt;

flowchart LR
    A[&quot;Lamport OTS -- signs only once&quot;] --&amp;gt; B[&quot;Merkle tree -- reusable root, but now stateful&quot;]
    B --&amp;gt; C[&quot;WOTS plus and XMSS -- smaller and provable, still stateful&quot;]
    C --&amp;gt; D[&quot;SPHINCS -- deletes state, but 41 KB and multi-target exposure&quot;]
    D --&amp;gt; E[&quot;SPHINCS plus and SLH-DSA -- smaller, multi-target-resistant, assumption trimmed&quot;]
&lt;p&gt;But statelessness did not come free, and the two costs it introduced are exactly what the next generation set out to cut. First, size: even at 41 KB, SPHINCS-256 was an order of magnitude larger than a lattice signature [@sphincs15, @huelsingblog]. Second, and more subtly, SPHINCS exposed itself to &lt;em&gt;multi-target&lt;/em&gt; attacks. With a single hash function reused across all instances (global bitmasks, not keyed per location) and an unverifiable pseudorandom index, an attacker who computed one hash value could aim it at &lt;em&gt;all&lt;/em&gt; the few-time instances at once, effectively multiplying the odds of success by the number of targets [@huelsingblog].&lt;/p&gt;
&lt;p&gt;Notice, again, what these costs are not: neither is a forgery. Nobody broke SPHINCS; it worked exactly as proved. It was simply too big and left a generic hash attack more room than its designers wanted. Both bills -- tens of kilobytes and a new way to gang up on the hash -- had to be paid by the next generation without surrendering statelessness.&lt;/p&gt;
&lt;h2&gt;6. SPHINCS+ and FIPS 205: FORS, Tweakable Hashes, and an Attack Surface You Can List&lt;/h2&gt;
&lt;p&gt;Three cuts, one result. How do you shrink the signature, neutralize the multi-target attack, and end with an attack surface you can write on an index card? SPHINCS+, submitted to NIST in November 2017 and standardized as SLH-DSA in 2024, closed SPHINCS&apos;s gaps one at a time [@huelsingblog, @fips205].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cut one: tweakable hashing.&lt;/strong&gt; Every internal hash call is keyed by an address plus the public seed, producing a distinct effective function for every location in the structure. The idea arrived as multi-target mitigation in Hulsing, Rijneveld, and Song at PKC 2016, and was abstracted into the general notion of tweakable hash functions in the SPHINCS+ Framework at CCS 2019 [@pkc16, @ccs19]. This cut deserves mechanizing rather than sloganizing: &quot;it keys the hash so multi-target attacks go away&quot; hides the actual arithmetic.&lt;/p&gt;
&lt;p&gt;Here is the mechanism. Preimage and second-preimage resistance are &lt;em&gt;targeted&lt;/em&gt; properties, and the SPHINCS+ specification states the danger exactly: &quot;If it suffices to break the given property for one out of many targets, the adversarial effort is reduced by a factor of the number of targets&quot; [@sphincsspec].&lt;/p&gt;
&lt;p&gt;Concretely, suppose the scheme publishes &lt;code&gt;T&lt;/code&gt; hash values, all outputs of one fixed function &lt;code&gt;F&lt;/code&gt;. An attacker computes a single candidate &lt;code&gt;F(x)&lt;/code&gt; and tests it against all &lt;code&gt;T&lt;/code&gt; targets at once, so the expected work to hit &lt;em&gt;some&lt;/em&gt; target falls to $2^n / T$: the security level slips from $n$ bits to $n - \log_2 T$.&lt;/p&gt;
&lt;p&gt;Keying removes exactly that discount. With a per-call tweakable hash &lt;code&gt;F(PK.seed, ADRS, x)&lt;/code&gt;, each target lives under its own address, so a computed value can match only the &lt;em&gt;one&lt;/em&gt; target sharing that address. The attacker can no longer spread one evaluation across many targets; it must attack each of the &lt;code&gt;T&lt;/code&gt; separately. The factor-&lt;code&gt;T&lt;/code&gt; amortization is gone, and &lt;code&gt;T&lt;/code&gt; folds into the security &lt;em&gt;analysis&lt;/em&gt; as a small logarithmic term instead of being subtracted from the level. That is precisely the single-function, multi-target property (SM-TCR / SM-DSPR) the next section names.The address &lt;code&gt;ADRS&lt;/code&gt; is 32 bytes: a 4-byte &lt;code&gt;layer&lt;/code&gt; (which of the &lt;code&gt;d&lt;/code&gt; hypertree layers), a 12-byte &lt;code&gt;tree&lt;/code&gt; (which Merkle tree in that layer), a 4-byte &lt;code&gt;type&lt;/code&gt; word that takes one of seven values, and a 12-byte type-dependent tail naming the exact key pair, chain, and node. FIPS 205 says its purpose in one line: &quot;A different ADRS value is used for each call to each function ... to mitigate multi-target attacks&quot; [@fips205, @sphincsspec].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cut two: verifiable index selection.&lt;/strong&gt; SPHINCS chose its leaf with an unverifiable pseudorandom index, part of what let attackers pool targets. SPHINCS+ computes the index &lt;em&gt;together with&lt;/em&gt; the message digest: a randomizer &lt;code&gt;R&lt;/code&gt;, itself part of the signature, is hashed with the public key and the message to produce both the digest and the index. Now every attacker-chosen message is bound to exactly one few-time instance and is useless against any other [@huelsingblog].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cut three: FORS replaces HORST.&lt;/strong&gt; The few-time layer was rebuilt to be leaner.&lt;/p&gt;

The few-time signature at the bottom of SLH-DSA. A FORS key is not one monolithic tree but `k` separate trees of height `a = log t`; the leaves are hashes of `k` times `t` secret values, and the FORS public key is the tweakable hash of all `k` roots. Because each of the `k` message-selected indices draws from its *own* dedicated set of secrets, FORS is markedly smaller and faster than the HORST scheme it replaced, and even if one message maps twice to the same index the signature reveals different secrets.Swapping HORST for FORS gives each message index a dedicated set of secrets, which is what shrinks both signature size and signing time [@huelsingblog, @sphincsspec].
&lt;p&gt;There was also a proof-side refinement. Bernstein and Hulsing&apos;s 2019 work on decisional second-preimage resistance (DSPR) removed a statistical assumption the tight security reduction had previously needed on the hash [@dspr19]. We will meet DSPR again in the next section; for now, note that it is yet another &lt;em&gt;property of the hash&lt;/em&gt;, added to a list that already had several.&lt;/p&gt;
&lt;p&gt;Put the mechanism in one picture. Signing derives a randomizer, binds the message to the public key, splits the result into a message digest and an index, FORS-signs the digest, and authenticates the FORS public key up the hypertree.&lt;/p&gt;

flowchart LR
    M[&quot;Message M&quot;] --&amp;gt; R[&quot;PRF derives randomizer R&quot;]
    R --&amp;gt; H[&quot;Hash binds R, public key, and M into a digest&quot;]
    H --&amp;gt; S[&quot;Split into message digest md, tree index, leaf index&quot;]
    S --&amp;gt; F[&quot;FORS signs md&quot;]
    F --&amp;gt; A[&quot;Hypertree of WOTS plus authenticates the FORS public key&quot;]
    A --&amp;gt; SIG[&quot;Signature is R plus FORS sig plus hypertree sig&quot;]
&lt;p&gt;The result was decisive on every axis the designers cared about, and its size story is best read at a fixed security level.The popular &quot;41 KB to 8 KB&quot; line is a cross-level comparison. At level 5 the honest cut is about 41 KB (SPHINCS-256) to about 30 KB (SLH-DSA-256s, 29,792 bytes); the roughly 8 KB figure is a &lt;em&gt;new&lt;/em&gt; level-1 capability (SLH-DSA-128s, 7,856 bytes), not a same-level shrink of SPHINCS-256. The two numbers sit at opposite ends of the security range and should not be subtracted [@sphincs15, @fips205]. Holding NIST category 5 fixed, the SPHINCS-256 signature of about 41 KB became roughly 30 KB in SLH-DSA-256s; separately, SPHINCS+ newly &lt;em&gt;reached&lt;/em&gt; category 1 at about 8 KB (SLH-DSA-128s), a tier SPHINCS-256 never targeted [@sphincs15, @fips205].&lt;/p&gt;
&lt;p&gt;The multi-target attack was folded into parameters rather than the security level. A statistical proof assumption was gone. And twelve parameter sets were defined over just two hash families.SPHINCS+ originally shipped three hash instantiations: SHAKE-256, SHA-256, and Haraka. FIPS 205 dropped Haraka and kept only SHA-2 and SHAKE, which is precisely why &quot;SHA-2 or SHAKE&quot; is the exact phrase for the standard [@fips205, @sphincsorg]. NIST selected this design in July 2022 and published it as FIPS 205 in August 2024 [@ir8413, @nistsel, @fips205].&lt;/p&gt;
&lt;p&gt;Here is the second half of the aha moment. After all three cuts, the entire question of whether SLH-DSA can be forged reduces to a short, explicit list of properties -- and every item on the list is a property of the tweakable hash. Not a lattice, not a group, not a number-theoretic conjecture. A handful of things you can ask about SHA-2 or SHAKE. That is what it means to drive an attack surface all the way down to the hash.&lt;/p&gt;
&lt;p&gt;So what, exactly, is on that list -- and is &quot;it reduces to the hash&quot; the whole story, or a comforting simplification?&lt;/p&gt;
&lt;h2&gt;7. What &quot;Reduces to the Hash&quot; Really Means&lt;/h2&gt;
&lt;p&gt;There is a one-line version of this article&apos;s thesis that you will see repeated in slide decks: SLH-DSA &quot;reduces to second-preimage and target-collision resistance.&quot; That line is &lt;em&gt;almost&lt;/em&gt; right. And for a piece about how a thing would break, almost right is not good enough, because the gap between the slogan and the truth is exactly where the only honest worries live.&lt;/p&gt;
&lt;p&gt;Here is the real property set the security reduction bottoms out at. There are four items, not two.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;What it guards&lt;/th&gt;
&lt;th&gt;Which object&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PRF&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;secrecy of every secret value the scheme derives&lt;/td&gt;
&lt;td&gt;the pseudorandom functions [@ccs19]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SM-TCR&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;no useful second preimage across many keyed targets&lt;/td&gt;
&lt;td&gt;the tweakable hash in WOTS+, Merkle, and the hypertree [@ccs19, @pkc16]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SM-DSPR&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;removes a statistical assumption so the proof can be tight&lt;/td&gt;
&lt;td&gt;the tweakable hash [@dspr19]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ITSR&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;no forgery assembled from revealed FORS subsets&lt;/td&gt;
&lt;td&gt;the FORS few-time layer [@pkc16]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

The single-function, multi-target hash properties SLH-DSA&apos;s proof invokes. **SM-TCR** (target-collision resistance) and **SM-DSPR** (decisional second-preimage resistance) are properties of the *tweakable* hash: &quot;single-function, multi-target&quot; captures the fact that an attacker may choose among many targets but faces a distinct keyed function at every location -- exactly what the per-call `ADRS` keying of the previous section provides, which is why &quot;multi-target&quot; is already priced into the property rather than left as a discount for the attacker. **ITSR** (interleaved target subset resilience) is the property of FORS that bounds an attacker&apos;s advantage from the message-dependent choice of which secret subsets are revealed across many signatures.
&lt;p&gt;Look at the third column. Every single property is a property of the hash (or of the pseudorandom functions, which are themselves built from the hash). There is nothing else in the list. This is the thesis stated precisely instead of loosely: to break SLH-DSA you must defeat one of these, and each one is a question about SHA-2 or SHAKE.&lt;/p&gt;

flowchart TD
    EUF[&quot;EUF-CMA unforgeability of SLH-DSA&quot;] --&amp;gt; PRF[&quot;PRF security&quot;]
    EUF --&amp;gt; TCR[&quot;SM-TCR of the tweakable hash&quot;]
    EUF --&amp;gt; DSPR[&quot;SM-DSPR of the tweakable hash&quot;]
    EUF --&amp;gt; ITSR[&quot;ITSR of FORS&quot;]
    PRF --&amp;gt; HASH[&quot;A property of SHA-2 or SHAKE&quot;]
    TCR --&amp;gt; HASH
    DSPR --&amp;gt; HASH
    ITSR --&amp;gt; HASH
&lt;p&gt;Now the distinction that the slogan hides, and the single most important nuance in this article. SPHINCS+ was defined in two instantiation styles. One -- the sturdier of the two, built for a standard-model reduction to the properties above -- carries a proof that does not treat the hash as magic. The other, the &lt;em&gt;simple&lt;/em&gt; style, is faster but rests on a heuristic. FIPS 205 standardized the &lt;strong&gt;simple&lt;/strong&gt; style [@sphincsorg, @fips205].&lt;/p&gt;

&quot;The simple variants are pure random oracle instantiations. These ... achieve about a factor three speed-up ... at the cost of a purely heuristic security argument.&quot; -- sphincs.org [@sphincsorg]

A proof technique that treats the hash function as if it were a perfectly random function every party can query. ROM proofs are common and have a good track record, but they are heuristic: no real hash is a random oracle, so a ROM proof is strong evidence of security rather than a guarantee reducible to a concrete, named property of the specific hash. The variant FIPS 205 standardized has its security argument in the ROM.
&lt;p&gt;This is why the focus word &quot;conservative&quot; needs careful handling. It does not mean &quot;backed by a tight standard-model proof of the shipped scheme,&quot; because the shipped scheme&apos;s argument is a random-oracle heuristic.&lt;/p&gt;

Read &quot;conservative&quot; as *design-level* conservatism, not as a statement about the tightness of the proof of the standardized variant. SLH-DSA is conservative because it makes minimal, well-studied assumptions (a hash, nothing more), uses large parameters, budgets for up to `2^64` signatures, and inherits roughly fifty years of a lineage in which no structural forgery has ever appeared. That is a strong basis for trust. It is a *different* basis than &quot;the exact bytes NIST shipped have a tight standard-model reduction,&quot; which they do not -- they have a ROM argument bought for a factor-three speed-up over the standard-model style [@sphincsorg]. Both things are true at once, and an honest &quot;how it breaks&quot; analysis has to hold both.
&lt;p&gt;There is one more honest wrinkle, and it cuts the right way. The tight security reduction for the multi-target and ITSR arguments turned out to have a &lt;em&gt;gap&lt;/em&gt; -- a genuine bug in the proof. Kudinov, Kiktenko, and Fedorov reported it in 2020; Andreas Hulsing and Mikhail Kudinov then recovered the tight proof and published it at ASIACRYPT 2022 [@kkf20, @hk22].&lt;/p&gt;
&lt;p&gt;Sit with what that episode is and is not. It is a flaw in an &lt;em&gt;argument about&lt;/em&gt; the scheme, found and fixed by the scheme&apos;s own community. It is not a forgery, not an attack, not a weakness anyone could exploit. Even SLH-DSA&apos;s imperfections are imperfections of proofs and hashes -- never of algebra, because there is no algebra to be imperfect.&lt;/p&gt;
&lt;p&gt;So the precise version of the thesis is this: every property the reduction needs is a property of the hash, and the one place the standardized scheme trades a tight proof for speed is a place where the residual risk is in the &lt;em&gt;heuristic&lt;/em&gt;, not in some hidden mathematical structure. Every wrinkle so far has been about proofs and hashes. But has anyone actually &lt;em&gt;attacked&lt;/em&gt; the standardized scheme and gotten anywhere?&lt;/p&gt;
&lt;h2&gt;8. The Strongest Test: Breaking Category-Five SPHINCS+ With SHA-256&lt;/h2&gt;
&lt;p&gt;In 2022, three NIST cryptographers -- Ray Perlner, John Kelsey, and David Cooper -- set out to break the highest-security version of the scheme their own agency was about to standardize. Their paper is titled, provocatively, &lt;em&gt;Breaking Category Five SPHINCS+ with SHA-256&lt;/em&gt; [@pkc22]. It is the single most important piece of evidence in this whole article, and not for the reason the title suggests.&lt;/p&gt;
&lt;p&gt;What they found is a genuine shortfall. Using a purely &lt;em&gt;classical&lt;/em&gt; analysis, they showed that the SHA-256 category-5 parameter sets do not quite reach the NIST category-5 security level -- each security claim comes down by roughly 40 bits [@pkc22, @wiki_sphincs]. That is a real result, presented at a real conference, about the shipped standard. Take it seriously.&lt;/p&gt;
&lt;p&gt;Now read the two qualifications that turn it from a scare into the article&apos;s decisive move.&lt;/p&gt;
&lt;p&gt;First: there is &lt;strong&gt;no practical forgery&lt;/strong&gt;. The analysis needs an astronomically large number of signatures and an infeasible amount of computation; it moves a margin, it does not produce a forged signature. The authors are explicit that their work does not call the general soundness of the design into question [@wiki_sphincs].&lt;/p&gt;
&lt;p&gt;Second, and this is the whole point: the shortfall traces directly to &lt;strong&gt;SHA-256&apos;s internal Merkle-Damgard structure&lt;/strong&gt; -- specifically the multicollision and &quot;herding&quot; behaviors that chaining construction permits. It is not a weakness in FORS, or WOTS+, or the hypertree, or the index selection, or any part of the SPHINCS+ design. It is a property of the hash.&lt;/p&gt;

The internal design of SHA-2 (and of MD5 and SHA-1 before it): a hash built by chaining a compression function across message blocks. That chaining is what enables multicollision and herding shortcuts, which make some multi-target attacks cheaper than they would be against an ideal function. SHAKE is built on a different internal design, the sponge, which does not share this particular shortcut.
&lt;p&gt;The consequence is striking. The SHAKE-based category-5 sets, being sponge constructions rather than Merkle-Damgard, are not subject to the same effect. The very same SLH-DSA design, wrapped around a different hash, does not show the shortfall. If that does not convince you the &quot;weakness&quot; belongs to the hash rather than the scheme, nothing will.&lt;/p&gt;

The engine is multicollision and herding on a Merkle-Damgard hash. Because SHA-256 chains a compression function block by block, an attacker can build a large set of messages that all collide to a chosen intermediate value far more cheaply than the ideal `2^n` cost, then &quot;herd&quot; a target into that set. Against the category-5 SHA-256 parameters, exploiting this structure lowers the effective work by about 40 bits versus the claimed level. Swap in SHAKE, whose sponge has no comparable intermediate-state chaining, and the shortcut disappears [@pkc22, @wiki_sphincs].
&lt;p&gt;The other thing worth mechanizing is &lt;em&gt;how&lt;/em&gt; SLH-DSA behaves when you push it, because &quot;degrades gracefully&quot; is another slogan that hides real arithmetic. The FORS few-time layer is what wears out as a key pair signs more messages, and it erodes smoothly for a structural reason.&lt;/p&gt;
&lt;p&gt;A forgery assembled from already-seen material needs a &lt;em&gt;fresh&lt;/em&gt; message whose &lt;code&gt;k&lt;/code&gt; FORS positions are &lt;strong&gt;all&lt;/strong&gt; already revealed by the signatures the attacker has seen -- and that requires two independent coincidences at once. The same hypertree leaf &lt;code&gt;I&lt;/code&gt; must recur (probability $2^{-h}$ per signature), &lt;em&gt;and&lt;/em&gt; all &lt;code&gt;k&lt;/code&gt; of the message-selected indices must land on already-revealed spots. The SPHINCS+ specification gives the coverage probability exactly [@sphincsspec]:&lt;/p&gt;
&lt;p&gt;$$\Pr\left[S_0 \subset S_1 \cup \dots \cup S_q\right] = \sum_{\gamma} \binom{q}{\gamma}\left(1 - 2^{-h}\right)^{q-\gamma} 2^{-h\gamma}\left[1 - \left(1 - 1/t\right)^{\gamma}\right]^{k}$$&lt;/p&gt;
&lt;p&gt;Because &lt;code&gt;k&lt;/code&gt; independently chosen positions must be covered &lt;em&gt;simultaneously&lt;/em&gt;, and repeated leaves are themselves rare, this is a high-order function of the signature count &lt;code&gt;q&lt;/code&gt;.At the design budget the number is astronomically small: for the level-5 set (&lt;code&gt;t = 2^14&lt;/code&gt;, &lt;code&gt;k = 22&lt;/code&gt;, &lt;code&gt;h = 64&lt;/code&gt;) at &lt;code&gt;q = 2^64&lt;/code&gt;, the coverage probability is about &lt;code&gt;2^-256.01&lt;/code&gt;. Past the budget it declines &lt;em&gt;smoothly&lt;/em&gt; -- roughly 10 bits of margin per doubling for the level-5 set (about 7 bits for level 1), the exponent falling 256.0, 246.5, 235.3 across &lt;code&gt;q = 2^64&lt;/code&gt;, &lt;code&gt;2^65&lt;/code&gt;, &lt;code&gt;2^66&lt;/code&gt; -- and it accelerates only gradually, never as a discontinuity [@sphincsspec, @kp22]. Below the budget the term sits far above the category-level target and does nothing; the flat, hash-property terms set the security level. Only once you pass the budget does it begin to bind, and then it slides rather than snaps.&lt;/p&gt;
&lt;p&gt;Kolbl and Philipoom characterize the same behavior from the design side: security &quot;degrades ... surprisingly slowly,&quot; the limit &quot;can be exceeded by several orders of magnitude before it becomes a practical issue,&quot; and their reduced-budget sets keep over 100-bit security even at &lt;code&gt;2^30&lt;/code&gt; signatures [@kp22].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The strongest published in-scope result against SLH-DSA is not an attack on SLH-DSA. It is an attack on SHA-256&apos;s Merkle-Damgard structure that happens to lower a SPHINCS+ margin, produces no forgery, degrades gracefully, and vanishes when you switch to SHAKE. Every property of that result points at the hash and away from the design. This is the thesis proving itself in the one place where a structural weakness might have appeared.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is the third aha moment, and it reframes everything a casual reader might have assumed. &quot;There is a paper breaking category-five SPHINCS+&quot; sounds like the scheme has a real structural flaw, like any other cryptosystem. It does not. The best shot anyone has taken landed exactly where this article said any weakness would have to live: on the hash, not on the construction wrapped around it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The single strongest structural result against SLH-DSA is an attack on SHA-256, not on SLH-DSA. It yields no forgery, it degrades gracefully, and it disappears on the SHAKE parameter sets -- because the &quot;weakness&quot; was inherited entirely from the hash.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;How a hash break would actually arrive -- what a real advance against SHA-2 or SHAKE would look like -- is the subject of Part 2 of this series, &lt;a href=&quot;https://paragmali.com/blog/how-sha-2-and-sha-3-would-break-merkle-damgard-collisions-le/&quot; rel=&quot;noopener&quot;&gt;&lt;em&gt;How SHA-2 and SHA-3 Would Break&lt;/em&gt;&lt;/a&gt;. This article does not need to re-derive it; it only needs to show that this is where every path leads. If the strongest structural test lands on the hash and yields no forgery, then the real question is not &lt;em&gt;whether&lt;/em&gt; SLH-DSA breaks but &lt;em&gt;how&lt;/em&gt; it would -- and which hypothesis is most likely.&lt;/p&gt;
&lt;h2&gt;9. Weighing the Hypotheses: How Would It Actually Break?&lt;/h2&gt;
&lt;p&gt;Put every candidate on trial. There are four ways SLH-DSA could conceivably fall, and honesty demands we rank them worst rival first rather than simply asserting the thesis. Here they are, with the property each one would have to defeat.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Hypothesis&lt;/th&gt;
&lt;th&gt;The attack it requires&lt;/th&gt;
&lt;th&gt;Property it defeats&lt;/th&gt;
&lt;th&gt;Likelihood&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;A&lt;/strong&gt; (the thesis)&lt;/td&gt;
&lt;td&gt;a preimage, second-preimage, or collision advance on SHA-2 or SHAKE&lt;/td&gt;
&lt;td&gt;SM-TCR / SM-DSPR -- the hash&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Most likely structural break&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;B&lt;/strong&gt; (the caveat)&lt;/td&gt;
&lt;td&gt;a flaw in the ROM heuristic or in the tweakable-hash keying and addressing&lt;/td&gt;
&lt;td&gt;the security &lt;em&gt;argument&lt;/em&gt;, not the compression function&lt;/td&gt;
&lt;td&gt;The most interesting honest caveat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;C&lt;/strong&gt; (bounded)&lt;/td&gt;
&lt;td&gt;exhausting or mis-sizing the FORS few-time and ITSR budget&lt;/td&gt;
&lt;td&gt;ITSR&lt;/td&gt;
&lt;td&gt;Bounded, graceful degradation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;D&lt;/strong&gt; (dismissed)&lt;/td&gt;
&lt;td&gt;a classical algebraic structural break&lt;/td&gt;
&lt;td&gt;none -- no such object exists&lt;/td&gt;
&lt;td&gt;Dismissed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Hypothesis A -- a break of the hash.&lt;/strong&gt; This is the thesis, and it ranks first because it is the only place the reduction actually bottoms out. If someone finds a better-than-generic multi-target preimage or second-preimage attack, or a damaging collision advance, against SHA-2 or SHAKE, then SM-TCR or SM-DSPR weakens and SLH-DSA&apos;s margin moves with it.&lt;/p&gt;
&lt;p&gt;This is not a hypothetical about SLH-DSA&apos;s design; it is a hypothetical about the hash -- precisely the subject Part 2 of this series takes up. Everything in Sections 6 through 8 was building the case that this is where a real break would begin.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hypothesis B -- a break of the argument, not the compression function.&lt;/strong&gt; This is the honest caveat, and the most interesting entry in the table, because it is the one the careful reader of Section 7 should be worried about. The shipped simple variant rests on a random-oracle heuristic. Suppose the heuristic itself is flawed -- not because SHA-256&apos;s compression function is weak, but because the &lt;em&gt;way&lt;/em&gt; SLH-DSA uses it (the tweakable-hash keying, the addressing scheme, the domain separation) fails to behave like the random oracle the proof assumes.&lt;/p&gt;
&lt;p&gt;That would be a real break, and it would not be a break of the hash&apos;s compression function [@sphincsorg, @sphincsspec]. But note what it still is not: algebraic. There is no ring or lattice here either. It is a failure of a &lt;em&gt;hash-construction argument&lt;/em&gt; -- a close cousin of the thesis, not a refutation of it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hypothesis C -- a budget failure.&lt;/strong&gt; FORS is a &lt;em&gt;few-time&lt;/em&gt; signature, and ITSR bounds how much an attacker gains as signatures accumulate. Sign far past the &lt;code&gt;2^64&lt;/code&gt; design budget, or mis-parameterize the few-time layer, and the margin erodes. But as Section 8 established with the coverage formula, this erosion is a smooth, high-order decline -- on the order of ten bits per doubling just past the limit -- not a cliff [@kp22, @sphincsspec]. It is a parameter and usage boundary, the kind of thing an operator avoids by respecting the budget, not a structural forgery lurking in the mathematics.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hypothesis D -- an algebraic break.&lt;/strong&gt; This is the one every other article in this series spends its length on, and here it is dismissed in a sentence, because there is no algebra to attack. No ring, no group, no lattice, no number-theoretic structure. The absence is not an oversight; it is the entire design goal. You cannot break a mathematical structure that was deliberately never included.&lt;/p&gt;

flowchart TD
    Q1{&quot;Is there an algebraic structure to attack?&quot;} --&amp;gt;|&quot;No such structure exists&quot;| D[&quot;Hypothesis D dismissed&quot;]
    Q1 --&amp;gt;|&quot;Only hash-based targets remain&quot;| Q2{&quot;Attack the function, the argument, or the budget?&quot;}
    Q2 --&amp;gt;|&quot;The compression function&quot;| A[&quot;Hypothesis A -- break SHA-2 or SHAKE&quot;]
    Q2 --&amp;gt;|&quot;The argument or keying&quot;| B[&quot;Hypothesis B -- ROM heuristic or tweakable-hash construction&quot;]
    Q2 --&amp;gt;|&quot;The usage budget&quot;| C[&quot;Hypothesis C -- FORS and ITSR budget&quot;]
    A --&amp;gt; HASH[&quot;Every surviving path ends at the hash&quot;]
    B --&amp;gt; HASH
    C --&amp;gt; HASH
&lt;p&gt;Stare at the decision graph and the pattern is unmistakable: the only path that leads &lt;em&gt;away&lt;/em&gt; from the hash is the one marked &quot;dismissed,&quot; and it is dismissed precisely because the structure it would attack was never built. Every other path -- every path a real attacker could actually walk -- ends at SHA-2 or SHAKE.&lt;/p&gt;
&lt;p&gt;Rank aside, two hard walls bound all of this: what can actually be proved, and what a quantum computer changes. It is time to meet the limits.&lt;/p&gt;
&lt;h2&gt;10. The Two Ceilings: What Is Provable, and What Quantum Changes&lt;/h2&gt;
&lt;p&gt;Two walls bound everything in this article. One is what can be proved. The other is what a quantum computer does.&lt;/p&gt;
&lt;p&gt;Take the proof ceiling first. As Section 7 laid out, the standardized simple variant has a random-oracle argument, while the sturdier standard-model style carries a tight reduction to the hash properties [@sphincsorg]. The &lt;code&gt;2^64&lt;/code&gt;-signature budget is a &lt;em&gt;designed&lt;/em&gt; ceiling, not a cliff -- pass it and security degrades slowly rather than snapping [@kp22]. So the honest statement of the upper bound is: SLH-DSA&apos;s shipped security is as good as its random-oracle argument and its parameters, both of which are conservative, and neither of which is a tight standard-model proof of the exact bytes NIST published.&lt;/p&gt;
&lt;p&gt;There is also a lower bound that no amount of cleverness escapes: size. Statelessness bought with a hypertree, on top of a hash-only construction, forces signatures into the kilobyte range. FIPS 205 fixes the layout exactly [@fips205]:&lt;/p&gt;
&lt;p&gt;$$|SIG| = \left(1 + k(1 + a) + h + d \cdot \mathit{len}\right) \cdot n$$&lt;/p&gt;
&lt;p&gt;Read the four terms left to right: a one-block randomizer &lt;code&gt;R&lt;/code&gt; costs &lt;code&gt;n&lt;/code&gt; bytes; the FORS signature costs $k(1 + a) \cdot n = O(k \log t \cdot n)$ bytes (each of the &lt;code&gt;k&lt;/code&gt; FORS trees reveals a secret &lt;em&gt;and&lt;/em&gt; its length-&lt;code&gt;a&lt;/code&gt; authentication path, so it is not merely $O(k \cdot n)$); the hypertree signature costs $(h + d \cdot \mathit{len}) \cdot n$ bytes, which splits into &lt;code&gt;d&lt;/code&gt; stacked WOTS+ signatures of $\mathit{len} \cdot n$ each plus an $h \cdot n$ Merkle authentication path. The single largest term is the one people usually forget.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Set&lt;/th&gt;
&lt;th&gt;n&lt;/th&gt;
&lt;th&gt;R&lt;/th&gt;
&lt;th&gt;FORS &lt;code&gt;k(1+a)n&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;WOTS+ &lt;code&gt;d*len*n&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;paths &lt;code&gt;h*n&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;Total&lt;/th&gt;
&lt;th&gt;WOTS+ share&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;128s&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;2,912&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3,920&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1,008&lt;/td&gt;
&lt;td&gt;7,856&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;49.9%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;128f&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;3,696&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;12,320&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1,056&lt;/td&gt;
&lt;td&gt;17,088&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;72.1%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;192s&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;6,120&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;8,568&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1,512&lt;/td&gt;
&lt;td&gt;16,224&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;52.8%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;192f&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;7,128&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;26,928&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1,584&lt;/td&gt;
&lt;td&gt;35,664&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;75.5%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;256s&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;10,560&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;17,152&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2,048&lt;/td&gt;
&lt;td&gt;29,792&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;57.6%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;256f&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;11,200&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;36,448&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2,176&lt;/td&gt;
&lt;td&gt;49,856&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;73.1%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Evaluate that formula on the twelve standardized sets and it reproduces the FIPS 205 sizes exactly. The breakdown is the surprise: the &lt;code&gt;d&lt;/code&gt; WOTS+ hypertree signatures are the &lt;em&gt;largest&lt;/em&gt; component of every single parameter set, from 49.9% at 128s to 75.5% at 192f, and they are biggest in the &lt;code&gt;f&lt;/code&gt; (&quot;fast&quot;) sets because those stack the most layers &lt;code&gt;d&lt;/code&gt; [@fips205]. FORS is second at roughly 20 to 38%. The Merkle authentication paths and the randomizer -- the parts a casual explanation usually blames -- are the two &lt;em&gt;smallest&lt;/em&gt; terms, together under 15%.&lt;/p&gt;
&lt;p&gt;It is one full Winternitz signature at each of the &lt;code&gt;d&lt;/code&gt; hypertree layers, not the authentication paths, that makes SLH-DSA kilobyte-scale. The size &lt;em&gt;is&lt;/em&gt; the cost of having no algebra: the same emptiness that removes the attack surface removes the option of a small signature.The hypertree&apos;s leaf count and the signature budget are different quantities. The bottom layer holds &lt;code&gt;2^63&lt;/code&gt; to &lt;code&gt;2^68&lt;/code&gt; leaves depending on the set, sized to absorb the &lt;code&gt;2^64&lt;/code&gt;-signature budget with negligible reuse. The level-1 and level-3 &lt;code&gt;s&lt;/code&gt; sets even have &lt;em&gt;fewer&lt;/em&gt; leaves (&lt;code&gt;2^63&lt;/code&gt;) than the &lt;code&gt;2^64&lt;/code&gt; budget -- safe only because the bottom is a &lt;em&gt;few-time&lt;/em&gt; FORS key, so a leaf can be reused a handful of times without collapse [@fips205].&lt;/p&gt;
&lt;p&gt;Now the quantum ceiling, which is where SLH-DSA differs from every other primitive in this series. The threat that dismantles RSA and ECC is Shor&apos;s algorithm, which needs a hidden-subgroup or period structure -- factoring, discrete logs -- to act on [@shor97]. A hash exposes no such structure. Shor has literally nothing to grab. This is not a lucky accident of parameter choice; it is a structural fact, and it is &lt;em&gt;precisely why&lt;/em&gt; NIST anchored its most conservative signature in hashing rather than in more algebra.&lt;/p&gt;
&lt;p&gt;The only quantum lever against a hash is Grover&apos;s algorithm, which speeds up generic unstructured search from $2^n$ to $2^{n/2}$ [@grover96]. That is a quadratic speedup, and it is generic -- it applies to any search, exploits no structure, and is fully absorbed by choosing a large enough digest. It is the reason SLH-DSA uses digest sizes of 16, 24, and 32 bytes for categories 1, 3, and 5 [@fips205].&lt;/p&gt;
&lt;p&gt;{`
// Costs shown as log2 of the work (the exponent). Bigger is harder.
const digests = [
  { level: 1, nBits: 128 },
  { level: 3, nBits: 192 },
  { level: 5, nBits: 256 }
];&lt;/p&gt;
&lt;p&gt;digests.forEach(function (d) {
  const classicalExp = d.nBits;        // 2^n classical preimage search
  const groverExp    = d.nBits / 2;    // 2^(n/2) with Grover
  console.log(
    &quot;category &quot; + d.level + &quot; (n=&quot; + d.nBits + &quot; bits): &quot; +
    &quot;classical 2^&quot; + classicalExp + &quot;, quantum 2^&quot; + groverExp
  );
});&lt;/p&gt;
&lt;p&gt;// Grover only halves the exponent. A 256-bit digest still leaves 2^128 quantum
// work -- infeasible -- which is why NIST maps digest sizes to categories with
// Grover already priced in.
console.log(&quot;Grover turns 2^256 into 2^128: still out of reach, and already budgeted.&quot;);
`}&lt;/p&gt;
&lt;p&gt;Run it and the pattern is plain: Grover halves the exponent, never the base. A category-5 digest that would cost $2^{256}$ classically still costs $2^{128}$ against a quantum search -- which is why the digest sizes were chosen where they were.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &quot;SLH-DSA has no structural quantum attack&quot; and &quot;Grover gives a generic speedup&quot; are different statements, and conflating them is the source of most confusion about hash-based signatures. Shor finds nothing to act on because there is no hidden-subgroup or period structure [@shor97] -- a &lt;em&gt;structural&lt;/em&gt; fact. Grover offers a generic quadratic speedup against any search -- a &lt;em&gt;generic&lt;/em&gt; fact, already absorbed by the 16, 24, and 32-byte digest sizes [@grover96, @fips205]. The first says the door does not exist; the second says a known, smaller door was measured and walled off in advance.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If nothing inside the construction can move the margin -- not the proof, not the size, not a quantum computer acting structurally -- then progress and risk both have to live somewhere else. Where is the research frontier actually pointing?&lt;/p&gt;
&lt;h2&gt;11. The Frontier Is the Hash&apos;s Frontier&lt;/h2&gt;
&lt;p&gt;Every honest survey ends with the open problems, and SLH-DSA&apos;s are worth listing -- not because they are alarming, but because of the single surprising thing they all have in common.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Can the standardized variant get a standard-model guarantee without losing the speedup?&lt;/strong&gt; FIPS 205 shipped the simple variant, whose security is a random-oracle heuristic; the standard-model style exists but runs about three times slower [@sphincsorg]. Closing that gap -- a standard-model proof at the simple variant&apos;s speed -- is the central residual question. DSPR and the recovered tight proof strengthened the standard-model case, but no one has produced a standard-model proof of the simple construction at simple-variant speed [@dspr19, @hk22].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How tight is the FIPS-205 bound, really, and can it be machine-checked?&lt;/strong&gt; The tight reduction was itself once buggy and then recovered, which is exactly the kind of history that motivates mechanizing the proof end to end [@hk22]. In 2024 a scheme-level machine-checked tight proof of SPHINCS+ covering the standardized parameter sets was formally verified in EasyCrypt [@ec24]; the residual target is tightening that mechanization to the exact FIPS 205 byte-level specification and the simple variant&apos;s random-oracle argument.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Can the signatures shrink without touching the assumption?&lt;/strong&gt; Fluhrer and Dang&apos;s 2024 work, &lt;em&gt;Smaller Sphincs+&lt;/em&gt;, gives a simpler formula for the security strength of a parameter set at a given number of signatures and uses it to search for smaller sets [@fd24]. The size floor from Section 10 -- dominated by those &lt;code&gt;d&lt;/code&gt; WOTS+ hypertree signatures -- bounds how far this can go, but there is room to move by trading the signature budget for bytes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Should the SHA-2 category-5 sets be re-parameterized relative to SHAKE?&lt;/strong&gt; The roughly 40-bit shortfall from Section 8 is a Merkle-Damgard artifact absent from the sponge-based SHAKE sets. Perlner, Kelsey, and Cooper quantified it; Kolbl and Philipoom characterized the graceful degradation; parameter guidance was proposed [@pkc22, @kp22]. Whether the standard should adjust the SHA-2 category-5 parameters is a live maintenance question.&lt;/p&gt;
&lt;p&gt;Now stand back and look at that list as a whole. Every entry is, at bottom, a question about a hash. The ROM question asks whether the way SLH-DSA calls its hash behaves like a random oracle. The tightness question asks how precisely the hash properties bound the forgery probability. The size question is constrained by how much hashing an authentication path and a stack of WOTS+ signatures irreducibly require. And the category-5 question is explicitly about SHA-256&apos;s internal structure versus SHAKE&apos;s. There is not one open problem on the list whose resolution lives &lt;em&gt;outside&lt;/em&gt; the hash.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; SLH-DSA&apos;s open problems are the hash&apos;s open problems. Because the attack surface &lt;em&gt;is&lt;/em&gt; the tweakable hash, every question that could actually move the scheme&apos;s security margin -- better multi-target or quantum preimage attacks, a structural weakness in Merkle-Damgard or in the sponge -- is a question about SHA-2 or SHAKE. The frontier of SLH-DSA is the frontier of its hash.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is the loop closing. The construction drove its attack surface all the way down to the hash, and so the research questions came to rest in the same place. Every margin-moving advance would be an advance against SHA-2 or SHAKE -- which is the whole content of Part 2 of this series. Knowing all of this, the last question is the practical one: how should you actually &lt;em&gt;use&lt;/em&gt; the thing?&lt;/p&gt;
&lt;h2&gt;12. Using It: Parameters, Misconceptions, and the Boundary&lt;/h2&gt;
&lt;p&gt;You have decided SLH-DSA is the conservative hedge -- the signature whose failure is bounded by a hash rather than a lattice. Now the practical questions: what do you actually pick, and what should you &lt;em&gt;not&lt;/em&gt; believe about it?&lt;/p&gt;
&lt;p&gt;Three choices define a parameter set. The &lt;code&gt;s&lt;/code&gt; (&quot;small&quot;) family produces smaller signatures but signs much more slowly; the &lt;code&gt;f&lt;/code&gt; (&quot;fast&quot;) family signs faster at roughly double the signature size [@openssl35]. The category (1, 3, or 5) sets the digest size &lt;code&gt;n&lt;/code&gt; and the assurance horizon, with signature size growing roughly linearly as you climb. And the hash family is SHA-2 or SHAKE: identical in size, with SHAKE sidestepping the Merkle-Damgard category-5 nuance from Section 8, and SHA-2 potentially faster where hardware acceleration exists [@fips205, @openssl35].&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter set&lt;/th&gt;
&lt;th&gt;NIST level&lt;/th&gt;
&lt;th&gt;Public key&lt;/th&gt;
&lt;th&gt;Signature&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;SLH-DSA-128s&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;32 B&lt;/td&gt;
&lt;td&gt;7,856 B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SLH-DSA-128f&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;32 B&lt;/td&gt;
&lt;td&gt;17,088 B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SLH-DSA-192s&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;48 B&lt;/td&gt;
&lt;td&gt;16,224 B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SLH-DSA-192f&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;48 B&lt;/td&gt;
&lt;td&gt;35,664 B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SLH-DSA-256s&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;64 B&lt;/td&gt;
&lt;td&gt;29,792 B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SLH-DSA-256f&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;64 B&lt;/td&gt;
&lt;td&gt;49,856 B&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Each of these six comes in a SHA-2 and a SHAKE flavor -- for example &lt;code&gt;SLH-DSA-SHA2-128f&lt;/code&gt; and &lt;code&gt;SLH-DSA-SHAKE-128f&lt;/code&gt; -- giving the twelve standardized sets in all; the sizes are identical across the two hash families [@oqs_slh, @openssl35].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Respect the &lt;code&gt;2^64&lt;/code&gt;-signature budget per key: it is a designed ceiling with graceful degradation beyond it, not a limit to test. And keep SLH-DSA off hot signing paths -- its slow signing and large signatures make it a poor fit for per-request handshakes or high-throughput APIs, where ML-DSA is the better default [@fips204].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; XMSS and LMS produce smaller, faster signatures, and it is tempting to reach for them when SLH-DSA&apos;s kilobytes hurt. But choosing statefulness re-imports the exact hazard SLH-DSA was built to remove: a single reused leaf index, from a rollback, a clone, or a restored backup, can enable forgery. Use the stateful schemes only where the signer&apos;s state is tightly controlled, under the rules of SP 800-208 [@sp800208].&lt;/p&gt;
&lt;/blockquote&gt;


No. Shor&apos;s algorithm needs hidden-subgroup or period structure -- the kind found in factoring and discrete logs -- and a hash exposes none, so Shor has nothing to act on [@shor97]. That structural emptiness is exactly why NIST chose a hash-based scheme as its conservative anchor. The only quantum lever is Grover&apos;s generic quadratic speedup, and it is already absorbed by the digest size [@grover96].


No. It rests on hash assumptions -- PRF, SM-TCR, SM-DSPR, and ITSR -- and the shipped simple variant rests on a random-oracle heuristic rather than a tight standard-model proof. It is conservative in its assumptions, not unconditional [@sphincsorg, @ccs19].


No -- and it helps to know where the bytes actually go. The dominant term is the `d` stacked WOTS+ hypertree signatures, one Winternitz signature per hypertree layer, which are 50 to 76% of every signature; FORS is second, and the Merkle authentication paths plus the randomizer are the smallest parts. Size is the price of statelessness and a hash-only construction, not a weakness an attacker exploits [@fips205, @oqs_slh].


That is an out-of-scope hardware fault attack on OpenSSL&apos;s in-memory state, not cryptanalysis of the mathematics. The SLasH-DSA authors themselves call the scheme &quot;theoretically sound&quot; [@slash25].


No. Perlner, Kelsey, and Cooper found a roughly 40-bit margin gap with no practical forgery, tracing to SHA-256&apos;s Merkle-Damgard structure; the degradation is graceful and the SHAKE sets avoid the effect entirely [@pkc22, @kp22].


Security degrades slowly, not off a cliff -- on the order of ten bits per doubling just past the limit, per the coverage formula in Section 8. It is a parameter and usage boundary, not an instant forgery, and staying within the budget avoids it entirely [@kp22, @sphincsspec].


ML-DSA is NIST&apos;s fast, small, general-purpose default, carrying a lattice assumption. SLH-DSA is the conservative, hash-only hedge for long-lived, low-volume, maximally independent keys -- root-of-trust and firmware signing rather than per-request traffic [@fips204, @ir8413].


In 2025, researchers demonstrated SLasH-DSA, a software-only universal forgery against SLH-DSA -- achieved by using Rowhammer to flip bits in OpenSSL&apos;s in-memory state, not by cryptanalyzing the mathematics [@slash25]. It is a hardware fault attack, and its own abstract calls the scheme &quot;theoretically sound,&quot; adding that even theoretically sound schemes can fail under real-world conditions. That sentence draws this article&apos;s fence for us. Side channels, fault and power attacks, implementation bugs, RNG failures, and protocol misuse are real and consequential -- and out of scope here. They belong to the empirical sibling, *How the NIST Finalists Broke*. This piece asked only whether the mathematics can be broken.
&lt;p&gt;And that answer has been the same at every layer. Drive the analysis down through FORS, through the hypertree of WOTS+, through the tweakable hash, and you never reach an algebraic floor where a forger could set up shop. You reach the hash, and you stop. The only assumption SLH-DSA cannot insure is the security of that hash -- every in-scope wrinkle in fifty years of this lineage, from Lamport&apos;s reuse rule to the category-5 SHA-256 shortfall, traces back to exactly that place. Which is why the whole story compresses to a single line.&lt;/p&gt;

It fails only if the hash falls first.
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;how-slh-dsa-would-break&quot; keyTerms={[
  { term: &quot;SLH-DSA&quot;, definition: &quot;The NIST FIPS 205 stateless hash-based signature standard, built only from tweakable-hash calls.&quot; },
  { term: &quot;Tweakable hash&quot;, definition: &quot;A hash keyed per call by a 32-byte address and public seed, folding multi-target attacks into parameters.&quot; },
  { term: &quot;FORS&quot;, definition: &quot;The few-time signature at the bottom of SLH-DSA: k trees of secret subsets selected by the message.&quot; },
  { term: &quot;Hypertree&quot;, definition: &quot;A tree of Merkle trees, up to 2^68 leaves, whose single top root is the public key; distinct from the 2^64-signature budget.&quot; },
  { term: &quot;SM-TCR, SM-DSPR, ITSR&quot;, definition: &quot;The single-function multi-target hash properties, plus the FORS property, that SLH-DSA&apos;s security reduction invokes.&quot; },
  { term: &quot;Random oracle model&quot;, definition: &quot;The heuristic that treats the hash as a random function; it backs the shipped simple variant.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>post-quantum-cryptography</category><category>digital-signatures</category><category>hash-based-signatures</category><category>slh-dsa</category><category>sphincs-plus</category><category>cryptanalysis</category><category>fips-205</category><category>nist-pqc</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>One Event, Three Assumptions, Five Answers: A Field Guide to the Post-Quantum Toolkit</title><link>https://paragmali.com/blog/one-event-three-assumptions-five-answers-a-field-guide-to-th/</link><guid isPermaLink="true">https://paragmali.com/blog/one-event-three-assumptions-five-answers-a-field-guide-to-th/</guid><description>A field guide to the five NIST post-quantum primitives -- ML-KEM, ML-DSA, SLH-DSA, FN-DSA, HQC: math intuition, exact sizes, failures, and decision rules.</description><pubDate>Tue, 14 Jul 2026 01:32:13 GMT</pubDate><content:encoded>
Shor&apos;s 1994 algorithm condemned RSA, Diffie-Hellman, and elliptic curves [@shor-1994], and &quot;harvest now, decrypt later&quot; means the clock is already running on today&apos;s traffic. NIST&apos;s answer is not one replacement but a **toolkit**: three finalized standards -- ML-KEM for key exchange, ML-DSA and SLH-DSA for signatures, all published on 2024-08-13 [@fips-203] [@fips-204] [@fips-205] -- and two more still on the way, FN-DSA (Falcon) and HQC, both pre-final [@fips-206-perlner-2025] [@nist-ir-8545]. The five are spread deliberately across lattices, hash functions, and codes so that no single mathematical break takes everything down. There is no free lunch: every choice trades size against speed against how conservative the assumption is. And, tellingly, **nothing in the toolkit has been mathematically broken.** Every real-world failure so far has been an implementation leak -- KyberSlash&apos;s secret-dependent division [@kyberslash-site], Falcon&apos;s floating-point hazard [@fouque-gsnorm-2019] -- while the era&apos;s two famous cryptanalytic breaks, SIKE and Rainbow, hit schemes that never made the cut [@castryck-decru-sidh-2022] [@beullens-rainbow-2022].
&lt;h2&gt;1. Somebody Is Already Saving Your Handshake&lt;/h2&gt;
&lt;p&gt;Right now, somewhere, a machine may be recording this very TLS session -- not to read today, but to decrypt on the afternoon a large quantum computer finally boots. That is not a thriller premise. It is the stated design assumption behind a change that is already shipping in production TLS software, where the default key exchange offered is no longer plain X25519 but a hybrid whose second half is called ML-KEM [@openssl-35-notes]. The strange part is not that the field replaced the math. It is that replacing it took &lt;strong&gt;five&lt;/strong&gt; different algorithms, resting on &lt;strong&gt;three&lt;/strong&gt; unrelated hard problems, to answer a &lt;strong&gt;single&lt;/strong&gt; result published in 1994 -- and that, so far, not one of the five has actually been broken.&lt;/p&gt;
&lt;p&gt;The single result is Shor&apos;s algorithm. In 1994 Peter Shor showed that a large, fault-tolerant quantum computer could factor integers and compute discrete logarithms in polynomial time [@shor-1994]. That one capability condemns essentially every public-key system deployed on the internet: RSA rests on factoring, Diffie-Hellman and elliptic-curve cryptography rest on discrete logarithms. (This series covered those primitives directly in &lt;a href=&quot;https://paragmali.com/blog/rsa-is-a-trapdoor-not-a-cryptosystem-oaep-pss-and-the-25-yea/&quot; rel=&quot;noopener&quot;&gt;Part 14 on RSA&lt;/a&gt;, &lt;a href=&quot;https://paragmali.com/blog/the-curve-was-hard-the-gap-was-soft-a-field-guide-to-using-e/&quot; rel=&quot;noopener&quot;&gt;Part 15 on elliptic curves&lt;/a&gt;, and &lt;a href=&quot;https://paragmali.com/blog/nobody-broke-the-discrete-log-a-field-guide-to-diffie-hellma/&quot; rel=&quot;noopener&quot;&gt;Part 18 on Diffie-Hellman&lt;/a&gt;.) The moment a cryptographically relevant quantum computer exists, all three fall together.&lt;/p&gt;

An attack strategy in which an adversary records encrypted traffic today, stores it, and decrypts it years later once a quantum computer becomes available. It means the quantum threat is not purely in the future: any secret that must stay confidential past the arrival of quantum computing is already exposed the moment it crosses the wire.
&lt;p&gt;Harvest now, decrypt later is why this is urgent before any quantum computer exists. If your threat model includes an adversary who can afford disk space and patience, then a session key protecting a 20-year secret is already at risk today [@nist-pqc-project]. That is the reasoning behind migrating key establishment first, and it is why the hybrid X25519MLKEM768 key share now ships as a default key share in OpenSSL 3.5, and was enabled by default in OpenSSH 9.9 before becoming the default key exchange in OpenSSH 10.0 [@openssl-35-notes] [@openssh-99-notes] [@openssh-pq].&lt;/p&gt;
&lt;p&gt;So the threat is one thing, sharp and singular. Why is the answer five things? NIST did not standardize one post-quantum cipher; it assembled a &lt;strong&gt;toolkit&lt;/strong&gt; -- three finalized standards and two more in progress -- and spread it across three unrelated families of hard problem: structured lattices, hash functions, and error-correcting codes. The bet is that a mathematical breakthrough against one family is unlikely to touch the others. To see why the answer is a toolkit, not a single cipher: its parts are older than the threat they answer.&lt;/p&gt;
&lt;h2&gt;2. The Threat, and the Three Old Ideas That Outlived It&lt;/h2&gt;
&lt;p&gt;Here is the twist that makes the whole story make sense: the replacements predate the threat. The oldest members of the toolkit were invented for reasons that had nothing to do with quantum computers, and they turned out to be quantum-safe by accident.&lt;/p&gt;
&lt;p&gt;Robert McEliece published a code-based public-key cryptosystem in 1978, hiding a secret, efficiently decodable error-correcting code (a binary Goppa code) behind a scrambled generator matrix so that an attacker faces the task of decoding a random-looking linear code [@mceliece-1978]. One year later, Ralph Merkle showed how to build digital signatures out of nothing but a hash function, chaining one-time keys under a binary hash tree whose root is the public key [@merkle-thesis-1979]; he polished the construction a decade later as &quot;A Certified Digital Signature&quot; [@merkle-cds-1989]. Both predate Shor by fifteen-plus years. Both are still standing.&lt;/p&gt;
&lt;p&gt;Then, in 1994, the threat arrived. Shor&apos;s quantum algorithm solves factoring and discrete logarithm in polynomial time, condemning RSA, Diffie-Hellman, and elliptic curves the moment a large quantum computer runs it [@shor-1994]. Two years later Lov Grover found a quantum search algorithm with a quadratic speedup [@grover-1996]. Grover is the good news that bounds the damage: a mere square-root speedup means doubling a symmetric key or hash-output length restores the security margin, which is exactly why hash-based signatures are considered the most conservative branch of the toolkit.Shor is catastrophic (exponential to polynomial); Grover is survivable (a square-root factor). The asymmetry is the reason symmetric ciphers and hash functions merely need bigger parameters, while public-key cryptography needed entirely new hard problems.&lt;/p&gt;
&lt;p&gt;Lattices arrived on a separate track, and again for their own reasons. In 1996 Miklos Ajtai proved a startling worst-case-to-average-case reduction: breaking a &lt;em&gt;random&lt;/em&gt; instance of a certain lattice problem is as hard as breaking the &lt;em&gt;worst&lt;/em&gt; case [@ajtai-1996]. That single result promoted lattices from a curiosity to a rigorous foundation. In 1998 Hoffstein, Pipher, and Silverman published NTRU, the first lattice scheme compact and fast enough to consider deploying, working over a small polynomial ring with tiny coefficients [@ntru-1998].NTRU was first announced at the CRYPTO 1996 rump session but formally published at ANTS-III in 1998, so you will see both dates in the literature. Merkle&apos;s hash-tree work has the same two-date character: the 1979 thesis, then the 1989 CRYPTO paper.&lt;/p&gt;
&lt;p&gt;Oded Regev tied the knot in 2005 with Learning With Errors (LWE), a versatile assumption whose hardness reduces (quantumly) to worst-case lattice problems and whose one-sentence intuition -- add noise to linear algebra -- runs through every lattice member of the toolkit [@regev-lwe-2005].&lt;/p&gt;
&lt;p&gt;The last pieces are the mechanisms that make these foundations into safe schemes. The Fujisaki-Okamoto transform (1999) upgrades a weak encryption scheme into a strong one by re-encrypting on decryption and checking consistency [@fo-1999]. The GPV framework (2008) showed how to build lattice hash-and-sign signatures using a trapdoor and discrete-Gaussian sampling [@gpv-2007]. Lyubashevsky&apos;s &quot;Fiat-Shamir with aborts&quot; (2009) offered a rival way to sign, rejecting and restarting whenever a candidate would leak the key [@lyubashevsky-fswa-2009]. Ring-LWE (2010) moved LWE into polynomial rings for compact keys and fast arithmetic [@lpr-ringlwe-2010]. And in 2015, SPHINCS made hash-based signatures &lt;em&gt;stateless&lt;/em&gt;, removing the operational footgun that had kept Merkle&apos;s idea out of ordinary hands [@sphincs-2015].&lt;/p&gt;

timeline
    title Post-quantum foundations predate the 1994 threat
    1978 : McEliece code-based encryption
    1979 : Merkle hash-based signatures
    1994 : Shor algorithm breaks RSA and ECC
    1996 : Grover search : Ajtai hard lattices
    1998 : NTRU ring lattices
    2005 : Regev Learning With Errors
    2008 : GPV lattice hash-and-sign
    2009 : Fiat-Shamir with aborts
    2010 : Ring-LWE efficiency
    2015 : SPHINCS stateless hashing
&lt;p&gt;Read the timeline as three columns hiding in one line. Codes and hashes (1978, 1979) are the ancient, conservative branches. Lattices (1996 to 2010) are the young, efficient branch that took the most theoretical work to make safe. The mechanisms (FO, GPV, Fiat-Shamir-with-aborts) are the connective tissue that turns a hard problem into a usable cipher.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Who&lt;/th&gt;
&lt;th&gt;Idea&lt;/th&gt;
&lt;th&gt;Why it mattered&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;1978&lt;/td&gt;
&lt;td&gt;McEliece&lt;/td&gt;
&lt;td&gt;Code-based encryption&lt;/td&gt;
&lt;td&gt;Oldest surviving PQC family; ancestor of HQC [@mceliece-1978]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1979&lt;/td&gt;
&lt;td&gt;Merkle&lt;/td&gt;
&lt;td&gt;Hash-based signatures&lt;/td&gt;
&lt;td&gt;Weakest possible assumption; ancestor of SLH-DSA [@merkle-thesis-1979]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1994&lt;/td&gt;
&lt;td&gt;Shor&lt;/td&gt;
&lt;td&gt;Quantum factoring and discrete log&lt;/td&gt;
&lt;td&gt;The single threat the toolkit answers [@shor-1994]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1996&lt;/td&gt;
&lt;td&gt;Ajtai&lt;/td&gt;
&lt;td&gt;Worst-case lattice hardness&lt;/td&gt;
&lt;td&gt;Made lattices a rigorous foundation [@ajtai-1996]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2005&lt;/td&gt;
&lt;td&gt;Regev&lt;/td&gt;
&lt;td&gt;Learning With Errors&lt;/td&gt;
&lt;td&gt;The assumption under ML-KEM and ML-DSA [@regev-lwe-2005]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2015&lt;/td&gt;
&lt;td&gt;Bernstein et al.&lt;/td&gt;
&lt;td&gt;Stateless hash signatures&lt;/td&gt;
&lt;td&gt;Made hash signatures deployable [@sphincs-2015]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Each of these old ideas was quantum-safe. And none was deployable as written. To see why, watch each one walk straight into a different wall.&lt;/p&gt;
&lt;h2&gt;3. Three Walls: Why the Old Ideas Could Not Ship&lt;/h2&gt;
&lt;p&gt;A cipher can be perfectly correct -- decrypting every honest message, verifying every honest signature -- and still be unusable, or worse, still hand over its secret key. The first generation of post-quantum schemes taught that lesson three times, each on a different axis.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The first wall is size.&lt;/strong&gt; McEliece&apos;s cryptosystem has resisted cryptanalysis for more than forty-five years, which is a stronger track record than RSA has. But its public key is an entire generator matrix. In the modern Classic McEliece parameter sets, that means a public key from roughly 261 KB (for the &lt;code&gt;mceliece348864&lt;/code&gt; set) up to about 1.36 MB (for &lt;code&gt;mceliece8192128&lt;/code&gt;) [@classic-mceliece]. A megabyte of key material per connection is a non-starter for a TLS handshake that budgets a few kilobytes. McEliece is not broken; it is simply too big to carry. Its security was never the problem. Its shape was.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The second wall is state.&lt;/strong&gt; Merkle&apos;s hash-tree signatures, engineered into the modern XMSS and LMS schemes and standardized by NIST in SP 800-208, are compact and rest on the most conservative assumption in cryptography [@nist-sp-800-208]. But they are &lt;em&gt;stateful&lt;/em&gt;: the signer must advance a one-time-key index after every signature and must never, ever reuse one.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; NIST SP 800-208 warns that if an attacker obtains two signatures made with the same one-time key, &quot;it would become computationally feasible for that attacker to forge signatures on arbitrary messages&quot; [@nist-sp-800-208]. Restore a virtual machine from a snapshot, clone a key into a backup, or run two signer replicas, and you can silently reuse an index. The math is impeccable; the operational requirement -- perfect, rollback-proof, monotonic state, forever -- is what ordinary systems cannot guarantee.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;The third wall is the subtle one, and it reframes the whole problem: leakage.&lt;/strong&gt; The natural way to sign with a lattice is hash-and-sign in the style of GGH and its NTRU instantiation, NTRUSign: hash the message to a target point, then use your secret &quot;good&quot; basis to round to a nearby lattice point. A verifier checks the point is on the lattice and close to the target. It verifies perfectly. It is also fatally broken.&lt;/p&gt;
&lt;p&gt;In 2006, Phong Nguyen and Oded Regev showed why in a paper with a wonderful title: &quot;Learning a Parallelepiped&quot; [@nguyen-regev-2006]. Every signature is the difference between the hashed target and a lattice point, and those differences are distributed over the &lt;em&gt;fundamental parallelepiped&lt;/em&gt; of the secret basis. Collect a few hundred signatures, and you can reconstruct the shape of that parallelepiped -- which is to say, you can recover the secret key. The signer was leaking the key a little at a time, in the statistical shape of its own outputs, while every individual signature passed verification.&lt;/p&gt;

When the distribution of a scheme&apos;s public outputs (its signatures or its decryption behavior) depends on the secret key, an attacker who collects enough outputs can infer the key -- even though each individual output is valid. The break is statistical, not logical: nothing is forged, yet the key is recovered from the shape of honest data.
&lt;p&gt;Put the three walls side by side and a pattern appears. McEliece fails on size, stateful hashes fail on operational state, and NTRUSign fails on leakage -- three completely different axes. The naive strategy of &quot;pick the oldest unbroken idea and ship it&quot; runs aground because being unbroken is not the same as being safe to deploy. The NTRUSign failure is the sharpest version of the lesson, because it severs two ideas most people treat as one.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Correctness is not security. A scheme can verify every honest signature and still surrender its secret key through the statistical shape of a few hundred outputs. The real design goal is not &quot;find math no one has broken.&quot; It is &quot;make the outputs reveal nothing about the secret.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That reframing is the hinge of the entire toolkit. Once you decide the enemy is any correlation between your public outputs and your private key, the design problem becomes concrete: engineer the transcript, the ciphertext, and the failure behavior so they are provably independent of the secret. That single idea, applied four different ways, is the modern toolkit.&lt;/p&gt;
&lt;h2&gt;4. The Competition: One Fix, Four Times&lt;/h2&gt;
&lt;p&gt;The forcing function was not a single genius. It was an open, adversarial competition. NIST issued its public Call for Proposals in December 2016 and spent the next years pruning dozens of submissions across multiple rounds, documenting the reasoning in status reports as it went [@nistir-8413]. What emerged was not one lineage but four convergent tracks, running inside three unrelated hardness assumptions, each track advancing by fixing the specific flaw that sank its predecessor.&lt;/p&gt;

flowchart LR
    subgraph TA[&quot;Track A -- codes&quot;]
      A1[McEliece 1978] --&amp;gt; A2[Niederreiter] --&amp;gt; A3[QC-MDPC BIKE] --&amp;gt; A4[HQC]
    end
    subgraph TB[&quot;Track B -- hashes&quot;]
      B1[Lamport OTS] --&amp;gt; B2[Merkle WOTS] --&amp;gt; B3[XMSS LMS] --&amp;gt; B4[SPHINCS+]
    end
    subgraph TC[&quot;Track C -- lattice KEM&quot;]
      C1[NTRU] --&amp;gt; C2[LWE] --&amp;gt; C3[Ring-LWE] --&amp;gt; C4[Module-LWE]
    end
    subgraph TD[&quot;Track D -- lattice signatures&quot;]
      D1[GGH NTRUSign] --&amp;gt; D2[GPV Falcon]
      D1 --&amp;gt; D3[Fiat-Shamir Dilithium]
    end
    A4 --&amp;gt; TK[Five toolkit tips]
    B4 --&amp;gt; TK
    C4 --&amp;gt; TK
    D2 --&amp;gt; TK
    D3 --&amp;gt; TK
    P1[SIKE isogeny] -.broke 2022.-&amp;gt; XX[Pruned families]
    P2[Rainbow multivariate] -.broke 2022.-&amp;gt; XX
&lt;p&gt;&lt;strong&gt;Track A, codes, is a war on key size.&lt;/strong&gt; McEliece&apos;s matrix is enormous, so Niederreiter published the &quot;dual&quot; version that sends a compact syndrome instead of a full codeword -- smaller ciphertext, but the public key is still a matrix. Quasi-cyclic MDPC codes then collapsed that key to a few kilobytes by making the matrix reconstructable from a single row, an idea realized in the BIKE scheme [@mdpc-mceliece-2013].&lt;/p&gt;

The hard problem under every code-based scheme: given a random-looking parity-check matrix and a syndrome (the matrix applied to an unknown low-weight error), recover the error. Decoding a general random linear code is NP-hard; a code-based cryptosystem hides a secret, efficiently decodable code so that only the key holder can decode, while an attacker faces the random-code version.
&lt;p&gt;But BIKE walked into a wall of its own. Its iterative bit-flipping decoder occasionally fails, and -- this is the trap -- &lt;em&gt;those failures depend on the secret key&lt;/em&gt;. In 2016 Guo, Johansson, and Stankovski turned that into a full reaction attack: feed the decoder crafted ciphertexts, watch which ones fail, and recover the private key from the pattern of failures [@gjs-mdpc-2016]. The very feature that shrank the key opened a side channel.&lt;/p&gt;

The probability that correct decapsulation fails on an honest ciphertext. For post-quantum KEMs this is not merely a correctness nuisance: if the failure rate is non-negligible and correlated with the secret, each failure leaks information, and enough failures recover the key. DFR is therefore a security parameter, and a good scheme drives it to a cryptographically negligible level with a bound that does not depend on the secret.
&lt;p&gt;HQC is the fix: keep the quasi-cyclic key size, but decode with a &lt;em&gt;public&lt;/em&gt;, fixed code whose failure rate can be bounded analytically and does not depend on the secret. That is precisely why NIST chose HQC over BIKE -- its DFR analysis was judged more mature [@nist-ir-8545].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Track B, hashes, is a war on state&lt;/strong&gt;, and the whole story is the fight against one number: the leaf index. Lamport&apos;s one-time signature signs once per key; Merkle put many one-time keys under a tree so one root signs many messages; XMSS and LMS engineered that into standardized, stateful schemes [@nist-sp-800-208]; and SPHINCS removed the state entirely by choosing a random leaf from a space so vast that collisions are negligible, backed by a few-time signature to absorb the rare clash [@sphincs-2015]. SPHINCS+ then hardened it with tweakable hashes and a tighter few-time scheme called FORS [@sphincs-plus-framework-2019].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Track C, lattice KEMs, is a war over structure.&lt;/strong&gt; NTRU was fast but rested on a heuristic assumption; LWE bought a worst-case hardness reduction but needed a full random matrix as its key; Ring-LWE compressed that matrix to a single polynomial with fast NTT arithmetic [@lpr-ringlwe-2010]; and Module-LWE dialed the ring structure partway back down, trading a sliver of efficiency for a hedge against the possibility that too much algebraic structure helps the attacker [@crystals-kyber].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Track D, lattice signatures, is where the tree forks and both branches survive.&lt;/strong&gt; The GGH/NTRUSign transcript leak forced a choice, and the field kept two answers: GPV hash-and-sign, which samples from a discrete Gaussian whose shape is provably independent of the secret basis (this becomes Falcon), and Fiat-Shamir with aborts, which rejects and restarts until the transcript is key-independent (this becomes Dilithium) [@gpv-2007] [@lyubashevsky-fswa-2009].&lt;/p&gt;
&lt;p&gt;Stare at those four tracks and the same move appears in every one.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Every surviving generation makes the transcript or the failure channel provably independent of the secret. Gaussian sampling and rejection sampling remove the signature-transcript leak; the Fujisaki-Okamoto transform removes the decryption-failure oracle; statelessness removes the operational-state leak; HQC&apos;s public decoder removes BIKE&apos;s secret-dependent failures. The toolkit is not five unrelated tricks. It is one principle instantiated five ways.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The competition also pruned in public, and the prunings are the best argument for the whole strategy.&lt;/p&gt;

Two schemes that had survived years of scrutiny fell in 2022, within months of each other. Ward Beullens broke Rainbow, a multivariate signature finalist, in what his paper title advertised as a weekend on a laptop [@beullens-rainbow-2022]. Then Wouter Castryck and Thomas Decru broke SIKE, an isogeny-based KEM, with a key-recovery attack that runs in about ten minutes on a single core [@castryck-decru-sidh-2022]. Both schemes had strong theory and years of failed attacks behind them. Both were destroyed by a single new idea. And both were *outside* the final toolkit -- Rainbow was not selected, and SIKE advanced to NIST&apos;s fourth round only to be broken before it could be selected. That is the empirical case for diversity in one sentence: no amount of survived cryptanalysis is a proof, so you hedge across unrelated assumptions rather than bet everything on one.
&lt;p&gt;This is the moment to state the honest ending up front -- the argument the rest of the article defends.&lt;/p&gt;

Nothing in the toolkit has been mathematically broken. Every real-world failure so far has been an implementation leak -- and the two famous algorithmic breaks of the era hit schemes that never made the cut.
&lt;p&gt;It helps to see every notable failure of the era in one place, sorted by what actually went wrong. Two of these are implementation leaks in surviving schemes (the math is intact); two are historical breaks of superseded designs; and two are the non-toolkit cryptanalytic breaks that justify the hedge.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Failure&lt;/th&gt;
&lt;th&gt;Scheme&lt;/th&gt;
&lt;th&gt;Root cause&lt;/th&gt;
&lt;th&gt;Lesson&lt;/th&gt;
&lt;th&gt;In the toolkit?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Parallelepiped leak&lt;/td&gt;
&lt;td&gt;GGH / NTRUSign&lt;/td&gt;
&lt;td&gt;Signature distribution depends on the secret basis [@nguyen-regev-2006]&lt;/td&gt;
&lt;td&gt;Make the transcript key-independent&lt;/td&gt;
&lt;td&gt;No -- superseded ancestor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reaction attack&lt;/td&gt;
&lt;td&gt;QC-MDPC / BIKE&lt;/td&gt;
&lt;td&gt;Secret-dependent decoding failures form an oracle [@gjs-mdpc-2016]&lt;/td&gt;
&lt;td&gt;Bound the DFR with a public decoder&lt;/td&gt;
&lt;td&gt;No -- not selected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SIKE key recovery&lt;/td&gt;
&lt;td&gt;SIDH isogenies&lt;/td&gt;
&lt;td&gt;Torsion-point structure enables recovery [@castryck-decru-sidh-2022]&lt;/td&gt;
&lt;td&gt;A decade unbroken is not a proof&lt;/td&gt;
&lt;td&gt;No -- non-toolkit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rainbow weekend break&lt;/td&gt;
&lt;td&gt;Multivariate&lt;/td&gt;
&lt;td&gt;Structural attack on the oil-and-vinegar map [@beullens-rainbow-2022]&lt;/td&gt;
&lt;td&gt;Diversify assumptions&lt;/td&gt;
&lt;td&gt;No -- non-toolkit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KyberSlash&lt;/td&gt;
&lt;td&gt;ML-KEM (Kyber)&lt;/td&gt;
&lt;td&gt;Secret-dependent division timing [@kyberslash-site]&lt;/td&gt;
&lt;td&gt;Constant-time reduction; math untouched&lt;/td&gt;
&lt;td&gt;Yes -- implementation leak&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gram-Schmidt leak&lt;/td&gt;
&lt;td&gt;FN-DSA (Falcon)&lt;/td&gt;
&lt;td&gt;Floating-point sampler leaks basis norms [@fouque-gsnorm-2019]&lt;/td&gt;
&lt;td&gt;Use a vetted constant-time sampler&lt;/td&gt;
&lt;td&gt;Yes -- implementation hazard&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Notice that the bottom two rows -- the only failures inside the toolkit -- are both in the &quot;implementation&quot; column, never the &quot;math&quot; column. That distinction is the spine of everything that follows. By 2024 the pruned tree had five surviving tips. Three of them became law on a single day.&lt;/p&gt;
&lt;h2&gt;5. Three Standards in One Day&lt;/h2&gt;
&lt;p&gt;On 2024-08-13, NIST published three Federal Information Processing Standards at once: FIPS 203 (ML-KEM) for key encapsulation, FIPS 204 (ML-DSA) and FIPS 205 (SLH-DSA) for signatures [@fips-203] [@fips-204] [@fips-205]. That single date is when post-quantum cryptography crossed from an open competition into the law of the land, the thing an auditor can require and a protocol can mandate.&lt;/p&gt;
&lt;p&gt;Each standard is the hardened descendant of a competition submission, and each carries one defining idea forward.&lt;/p&gt;

A KEM is a three-function object -- key generation, encapsulate, decapsulate -- that lets two parties agree on a random shared secret. Encapsulate takes a public key and returns a ciphertext plus a shared secret; decapsulate takes the ciphertext and the private key and returns the same shared secret. It is the post-quantum replacement for the key-exchange half of Diffie-Hellman, and it composes with a symmetric cipher through the KEM-DEM pattern this series covered in [Part 19 on HPKE](/blog/the-standard-was-boring-that-was-the-point-a-field-guide-to-/). Crucially, a KEM is not a drop-in for a static-static Diffie-Hellman handshake -- a distinction we return to in the limits.
&lt;p&gt;&lt;strong&gt;ML-KEM&lt;/strong&gt; is Module-LWE encryption wrapped in a Fujisaki-Okamoto transform with &lt;em&gt;implicit rejection&lt;/em&gt;, so that an invalid ciphertext yields a pseudo-random shared secret rather than an error -- there is no decapsulation-failure oracle to probe [@fips-203]. &lt;strong&gt;ML-DSA&lt;/strong&gt; is a Fiat-Shamir-with-aborts signature built entirely from uniform integers, chosen deliberately so the implementation needs no floating point and is easy to make constant-time [@fips-204]. &lt;strong&gt;SLH-DSA&lt;/strong&gt; is a stateless hash-based signature whose security rests on nothing but its hash function -- the conservative backstop [@fips-205].&lt;/p&gt;
&lt;p&gt;ML-KEM is the standardized CRYSTALS-Kyber; ML-DSA is Dilithium; SLH-DSA is SPHINCS+. These are the same schemes under new NIST names, with standardization edits (tweaked hashing, encodings, and parameter cleanups), not fresh designs. If you have working knowledge of Kyber, you already understand ML-KEM.&lt;/p&gt;
&lt;p&gt;Two things follow that people routinely get wrong. First, the renaming is not a redesign: &quot;Kyber&quot; and &quot;ML-KEM&quot; are essentially the same scheme [@crystals-kyber]. Second, the toolkit is not finished -- only three of the five are standardized, and the fourth and fifth are genuinely pre-final.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; FN-DSA (Falcon), destined for FIPS 206, was still in development as of this writing, with a final expected around late 2026 or 2027 [@fips-206-perlner-2025]. HQC was only &lt;em&gt;selected&lt;/em&gt; for standardization on 2025-03-11, with a draft FIPS still pending [@nist-ir-8545]. Do not deploy either in production yet. Every FN-DSA and HQC size in this article is pre-final and may change.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The migration is already underway on the finalized three. But a standard is a promise about an interface, not a proof of security. To defend a design in a review, you need what is under each name: the math, the exact sizes, and the specific way each one can still fail.&lt;/p&gt;
&lt;h2&gt;6. The Five Primitives in Depth&lt;/h2&gt;
&lt;p&gt;One workhorse, one default, one backstop, one compact hopeful, one insurance policy. That is the toolkit in five phrases: ML-KEM is the workhorse KEM, ML-DSA the default signature, SLH-DSA the conservative backstop, FN-DSA the compact hopeful, and HQC the non-lattice insurance policy. Three of the five are lattice schemes, so learn the lattice intuition once and reuse it three times.&lt;/p&gt;

LWE is &quot;add noise to linear algebra.&quot; Given a random matrix $A$ and the product $b = A\mathbf{s} + \mathbf{e}$ where $\mathbf{e}$ is small random noise, recovering the secret $\mathbf{s}$ is believed hard, classically and quantumly. Module-LWE is the same idea over a small polynomial ring, arranged as a rank-$k$ module so the security level is set by $k$ rather than by resizing everything. Raising $k$ adds structure-diluting hedge; lowering it saves bytes. ML-KEM and ML-DSA both live here; only the rank and the noise change.
&lt;p&gt;All byte sizes below are exact for the finalized three and explicitly pre-final for FN-DSA and HQC. Cycle counts come from the pqm4 Cortex-M4 benchmark harness unless labeled otherwise [@pqm4-benchmarks].Never compare a Cortex-M4 cycle count against an AVX2 desktop number directly -- they are different machines. HQC&apos;s own figures are measured on an Intel i7-11850H and Falcon&apos;s on an Intel i5-8259U, so those live on a different scale than the M4 numbers used for cross-scheme comparison.&lt;/p&gt;
&lt;h3&gt;6.1 ML-KEM (FIPS 203): the workhorse&lt;/h3&gt;
&lt;p&gt;ML-KEM is the standardization of CRYSTALS-Kyber, finalized as FIPS 203, and it is the only post-quantum primitive deployed at scale today [@fips-203] [@crystals-kyber]. Its security rests on Module-LWE over the ring $R_q = \mathbb{Z}_q[X]/(X^{256}+1)$ with modulus $q = 3329$; the module rank $k \in {2,3,4}$ selects ML-KEM-512, ML-KEM-768, and ML-KEM-1024.&lt;/p&gt;
&lt;p&gt;The scheme has two layers. The inner layer is an IND-CPA encryption scheme over the ring. The outer layer upgrades it to a CCA-secure KEM using the Fujisaki-Okamoto transform.&lt;/p&gt;

The FO transform turns a weak (chosen-plaintext-secure) encryption scheme into a strong (chosen-ciphertext-secure) KEM by re-encrypting on decapsulation and checking the result. The modern twist -- *implicit rejection* -- is that a failed check returns a deterministic pseudo-random shared secret derived from a secret seed $z$, never an error. Because every ciphertext yields a well-formed key, an attacker who submits tampered ciphertexts learns nothing from the response, closing the decapsulation-failure oracle that broke earlier schemes [@fo-1999] [@hhk-fo-2017].

sequenceDiagram
    participant S as Sender
    participant R as Receiver
    R-&amp;gt;&amp;gt;S: public encapsulation key ek
    Note over S: pick random m, derive shared key K and coins r
    S-&amp;gt;&amp;gt;R: ciphertext c that encapsulates m
    Note over R: decrypt c to m-prime, re-derive K-prime and r-prime
    Note over R: re-encrypt m-prime to c-prime and compare
    alt c-prime equals c
        Note over R: return true shared secret K-prime
    else mismatch
        Note over R: return pseudo-random key from secret z, no error
    end
&lt;p&gt;That implicit-rejection branch is the load-bearing idea. It is worth seeing in code just how little a tampered ciphertext reveals.&lt;/p&gt;
&lt;p&gt;{`
// Illustrative only -- NOT production crypto.
// ML-KEM decapsulation never reports &quot;invalid&quot;. On a re-encryption mismatch it
// returns a pseudo-random key derived from a per-key secret z, so a tampered
// ciphertext produces a well-formed but useless key -- no distinguishable signal.&lt;/p&gt;
&lt;p&gt;function toyHash(s) {
  let h = 2166136261 &amp;gt;&amp;gt;&amp;gt; 0;
  for (const c of String(s)) h = Math.imul(h ^ c.charCodeAt(0), 16777619) &amp;gt;&amp;gt;&amp;gt; 0;
  return (h &amp;gt;&amp;gt;&amp;gt; 0).toString(16).padStart(8, &apos;0&apos;);
}&lt;/p&gt;
&lt;p&gt;const z = &apos;per-key-secret-z&apos;; // implicit-rejection secret, never leaves the device&lt;/p&gt;
&lt;p&gt;// Receiver decrypts c to m&apos;, re-encrypts m&apos;, and compares the result to c.
function decapsulate(c, mDecrypted, cReencrypted) {
  if (cReencrypted === c) {
    return toyHash(&apos;real-shared-secret:&apos; + mDecrypted); // the genuine key
  }
  return toyHash(z + &apos;:&apos; + c);                           // pseudo-random reject key
}&lt;/p&gt;
&lt;p&gt;// Honest ciphertext: re-encryption matches, real key returned.
console.log(&apos;honest   :&apos;, decapsulate(&apos;c123&apos;, &apos;m&apos;, &apos;c123&apos;));
// Tampered ciphertext: mismatch -&amp;gt; still a key, still no error.
console.log(&apos;tampered :&apos;, decapsulate(&apos;c999&apos;, &apos;m-garbled&apos;, &apos;c123&apos;));
// The reject key is deterministic per (z, c) and looks like any other key,
// so the attacker cannot tell rejection from success. The oracle is closed.
`}&lt;/p&gt;
&lt;p&gt;The exact bytes are what a protocol actually carries. For ML-KEM the encapsulation key / decapsulation key / ciphertext / shared secret sizes are 800 / 1632 / 768 / 32 for ML-KEM-512, 1184 / 2400 / 1088 / 32 for ML-KEM-768, and 1568 / 3168 / 1568 / 32 for ML-KEM-1024 [@fips-203]. The decryption-failure rates are $2^{-138.8}$, $2^{-164.8}$, and $2^{-174.8}$ respectively -- negligible by design, which as we saw is a security requirement, not a mere nicety [@fips-203]. On Cortex-M4, ML-KEM-768 costs roughly 642k / 659k / 708k cycles for keygen / encapsulate / decapsulate [@pqm4-benchmarks].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Several Kyber implementations divided a &lt;em&gt;secret&lt;/em&gt; numerator by the public modulus $q = 3329$ inside compression, and on many CPUs division time depends on the inputs -- so the timing leaked secret data. That is KyberSlash [@kyberslash-site] [@kyberslash-eprint-2024]. The FIPS 203 mathematics was never in question; the fix is constant-time (Barrett-style) reduction. It is the toolkit&apos;s headline real-world failure, and it is an implementation bug, exactly as the thesis predicts.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The three small prime moduli to remember: $q = 3329$ for ML-KEM, $q = 8380417$ for ML-DSA, and $q = 12289$ for Falcon. KyberSlash lived in the division by 3329.&lt;/p&gt;
&lt;p&gt;ML-KEM excels because it is small, fast, and easy to implement over small integers mod a fixed prime. It is the default post-quantum KEM in shipping software: the X25519MLKEM768 hybrid is a default key share in OpenSSL 3.5, and it was enabled by default in OpenSSH 9.9 before becoming the default key exchange in OpenSSH 10.0 [@openssl-35-notes] [@openssh-99-notes] [@openssh-pq]. Where it is least comfortable is its assumption: Module-LWE is younger and more structured than code- or hash-based hardness, which is the entire reason the field wants a non-lattice KEM in reserve.&lt;/p&gt;
&lt;h3&gt;6.2 ML-DSA (FIPS 204): the default signature&lt;/h3&gt;
&lt;p&gt;ML-DSA is the standardized CRYSTALS-Dilithium, and it is the signature you should reach for by default [@fips-204] [@crystals-dilithium]. It builds on the same Module-LWE ring world as ML-KEM (here with $q = 8380417$), but it signs by a completely different route than the hash-and-sign that leaked in NTRUSign.&lt;/p&gt;

Turn an interactive identification protocol into a signature by replacing the verifier&apos;s challenge with a hash (Fiat-Shamir), then add a rejection step: whenever the candidate signature would correlate with the secret, discard it and restart with fresh randomness. The signatures that survive are, by construction, distributed independently of the secret key. The cost is that signing runs a variable number of attempts [@lyubashevsky-fswa-2009].
&lt;p&gt;The signer commits to a masking vector $\mathbf{y}$, derives a sparse challenge $c$ by hashing the commitment together with the message, and forms $\mathbf{z} = \mathbf{y} + c\mathbf{s}_1$. If $\mathbf{z}$ strays outside a safe range, releasing it would leak the secret, so the signer aborts and tries again.&lt;/p&gt;

flowchart TD
    A[Sample fresh masking vector y] --&amp;gt; B[Derive sparse challenge c by hashing commitment and message]
    B --&amp;gt; C[Form candidate z as y plus c times secret s1]
    C --&amp;gt; D{&quot;Is z inside the safe range?&quot;}
    D -- No, would leak the secret --&amp;gt; A
    D -- Yes --&amp;gt; E[Publish signature challenge, z, hint]
&lt;p&gt;You can watch the loop behave. The number of attempts varies from signature to signature, and every released value stays inside the safe bound -- the mechanism that makes the transcript reveal nothing about the key.&lt;/p&gt;
&lt;p&gt;{`
// Illustrative only -- NOT production crypto.
// Keep sampling a masking value y until z = y + c*s1 lands in a safe range.
// Candidates that would correlate z with the secret are rejected; only
// key-independent z escape. Signing time therefore varies run to run.&lt;/p&gt;
&lt;p&gt;const GAMMA1 = 100;   // masking range
const BETA   = 20;    // how far c*s1 can push z
const secret = 37;    // s1, unknown to the verifier
const c = 1;          // toy sparse challenge
const rand = (n) =&amp;gt; Math.floor(Math.random() * n);&lt;/p&gt;
&lt;p&gt;function signOnce() {
  let attempts = 0;
  while (true) {
    attempts++;
    const y = rand(2 * GAMMA1) - GAMMA1;       // uniform masking
    const z = y + c * secret;
    if (Math.abs(z) &amp;lt; GAMMA1 - BETA) return { z, attempts }; // safe -&amp;gt; release
    // otherwise abort and retry with fresh y
  }
}&lt;/p&gt;
&lt;p&gt;let total = 0, n = 20000, maxAbsZ = 0;
for (let i = 0; i &amp;lt; n; i++) {
  const r = signOnce();
  total += r.attempts;
  maxAbsZ = Math.max(maxAbsZ, Math.abs(r.z));
}
console.log(&apos;avg attempts / signature:&apos;, (total / n).toFixed(2));
console.log(&apos;max |z| ever released   :&apos;, maxAbsZ, &apos;bound is&apos;, GAMMA1 - BETA);
console.log(&apos;variable attempt count is why ML-DSA signing time is not constant&apos;);
`}&lt;/p&gt;
&lt;p&gt;The Dilithium team chose this uniform-integer, rejection-based route deliberately, rather than Falcon&apos;s Gaussian sampler, and they were blunt about why.&lt;/p&gt;

&quot;Gaussian sampling is hard to implement securely and efficiently.&quot; -- the CRYSTALS-Dilithium team, on why ML-DSA uses uniform integers and no floating point [@crystals-dilithium].
&lt;p&gt;The private key / public key / signature sizes are 2560 / 1312 / 2420 for ML-DSA-44, 4032 / 1952 / 3309 for ML-DSA-65, and 4896 / 2592 / 4627 for ML-DSA-87, targeting NIST categories 2, 3, and 5 [@fips-204]. Verification is fast and constant-time; signing is fast but variable-time because of the abort loop, which is the single most important operational fact about the scheme. On Cortex-M4, ML-DSA-65 signing averages near 6.19M cycles but ranges from about 2.92M to 26.0M across a thousand runs [@pqm4-benchmarks].&lt;/p&gt;
&lt;p&gt;FIPS 204 supports both hedged (randomized) and deterministic signing; the hedged mode is the default and is more resilient to fault and bad-randomness mishaps. It also adds a context string of up to 255 bytes so applications can domain-separate their signatures and prevent cross-protocol reuse.&lt;/p&gt;
&lt;p&gt;ML-DSA excels as the general-purpose default: no floating point, easy constant-time code, moderate sizes, fast verification. Its weak spot is the signature-size wall this series flagged for interfaces in &lt;a href=&quot;https://paragmali.com/blog/the-math-held-the-interface-leaked-a-field-guide-to-digital-/&quot; rel=&quot;noopener&quot;&gt;Part 17 on digital signatures&lt;/a&gt; -- a 3309-byte signature is roughly fifty times an Ed25519 signature, and that multiplies through certificate chains.&lt;/p&gt;
&lt;h3&gt;6.3 SLH-DSA (FIPS 205): the conservative backstop&lt;/h3&gt;
&lt;p&gt;SLH-DSA is the standardized SPHINCS+, and it makes the most conservative bet in the toolkit: its security rests on nothing but the properties of its hash function, the same primitives this series covered in &lt;a href=&quot;https://paragmali.com/blog/the-fingerprint-two-files-shared-a-field-guide-to-cryptograp/&quot; rel=&quot;noopener&quot;&gt;Part 10 on cryptographic hashes&lt;/a&gt; [@fips-205] [@sphincs-plus-spec]. If every lattice and code assumption fell tomorrow, a signature that depends only on a hash would still stand.&lt;/p&gt;

SLH-DSA composes three hash-based gadgets. WOTS+ is a one-time signature that signs by revealing points along hash chains. FORS (&quot;Forest Of Random Subsets&quot;) is a *few-time* signature that signs the message digest and tolerates rare index collisions. A hypertree stacks many layers of Merkle trees, each layer&apos;s WOTS+ keys authenticating the roots below, up to one public root. Picking the FORS instance pseudo-randomly from the message removes the state that made XMSS dangerous [@sphincs-plus-framework-2019].

flowchart TD
    M[Message digest] --&amp;gt; R[Randomizer picks a FORS instance pseudo-randomly]
    R --&amp;gt; F[FORS few-time signature over the digest]
    F --&amp;gt; W[WOTS+ one-time key authenticates the FORS root]
    W --&amp;gt; H[Hypertree of Merkle layers, each signs the layer below]
    H --&amp;gt; PK[Single long-lived public root]
&lt;p&gt;The trade is stark. Public keys are tiny (32 to 64 bytes), but signatures are enormous and signing is slow. FIPS 205 defines twelve parameter sets -- three security levels, each with a &quot;small&quot; (&lt;code&gt;s&lt;/code&gt;) and &quot;fast&quot; (&lt;code&gt;f&lt;/code&gt;) variant, over SHA-2 and SHAKE. The public key / signature sizes run 32 / 7856 for 128s, 32 / 17088 for 128f, 48 / 16224 for 192s, 48 / 35664 for 192f, 64 / 29792 for 256s, and 64 / 49856 for 256f [@fips-205]. Signing hashes whole subtrees and costs hundreds of millions to billions of Cortex-M4 cycles, orders of magnitude slower than lattice signing [@pqm4-benchmarks]. The &lt;code&gt;s&lt;/code&gt;/&lt;code&gt;f&lt;/code&gt; knob only trades one pain for the other: smaller signatures mean slower signing.&lt;/p&gt;
&lt;p&gt;That profile makes SLH-DSA the right tool for low-volume, high-assurance signing -- firmware, boot chains, and software-update roots -- where you sign rarely, verify occasionally, and value a rock-bottom assumption over compactness.&lt;/p&gt;

If you can guarantee perfect state, the stateful hash signatures XMSS and LMS (NIST SP 800-208) are markedly smaller than SLH-DSA [@nist-sp-800-208]. The catch is the catch from Section 3: reuse a one-time leaf index and you enable forgery. They are the right call only in a tightly controlled setting -- a hardware security module or a firmware signer that can enforce monotonic, rollback-proof state. For everyone else, SLH-DSA trades bytes for the removal of that footgun, which is usually the better deal.
&lt;h3&gt;6.4 FN-DSA / Falcon: the compact hopeful (pre-final)&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Falcon is destined to become FIPS 206, but that document was still in development as of this writing, with a final expected around late 2026 or 2027 [@fips-206-perlner-2025] [@digicert-fndsa]. Every name and size below is pre-final and comes from the Falcon specification, not from a FIPS [@falcon-spec]. Do not ship FN-DSA in production yet.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Falcon instantiates the GPV hash-and-sign framework over NTRU lattices ($q = 12289$, dimension $n = 512$ or $1024$), and it produces the smallest signatures and keys of any standardized-track scheme [@falcon-spec] [@gpv-2007].&lt;/p&gt;

The safe way to do lattice hash-and-sign. A secret trapdoor lets the signer sample a short lattice vector near a hashed target from a discrete Gaussian whose distribution is provably independent of the secret basis. That independence is exactly what NTRUSign lacked -- it closes the parallelepiped leak by construction, rather than hoping the outputs happen not to correlate with the key.

flowchart LR
    M[Message] --&amp;gt; HP[Hash message to a point c in the ring]
    HP --&amp;gt; TS[Use NTRU trapdoor basis to target c]
    TS --&amp;gt; GS[Fast-Fourier Gaussian sampling, the delicate floating-point step]
    GS --&amp;gt; SV[Short vector s1, s2 near the lattice]
    SV --&amp;gt; SIG[Signature is a salt plus compressed s2]
&lt;p&gt;The payoff is compactness. Falcon-512 has an 897-byte public key and a 666-byte signature (roughly RSA-2048&apos;s classical security level, as this series discussed in Part 14, at a fraction of the byte size); Falcon-1024 is 1793 / 1280 [@falcon-spec]. On a desktop i5-8259U the reference code signs about 5948 times per second and verifies about 27933 times per second for Falcon-512 [@falcon-spec]. A Falcon-512 signature is under a third the size of ML-DSA-44&apos;s.&lt;/p&gt;
&lt;p&gt;So why is it the last of the five to standardize? Because the Gaussian sampler runs on floating-point arithmetic, and making floating point constant-time across compilers and CPUs is genuinely hard. Timing or precision leakage of the sampler&apos;s Gram-Schmidt norms can recover the secret key [@fouque-gsnorm-2019]. Mitigations exist -- Pornin&apos;s constant-time integer implementation and isochronous Gaussian sampling among them -- but they are intricate and platform-sensitive [@pornin-ctfalcon-2019] [@howe-isochronous-2019].&lt;/p&gt;
&lt;p&gt;Want concrete evidence that FN-DSA is pre-final? When researchers fetched the expected FIPS 206 Initial Public Draft URL during the source verification for this article, it returned HTTP 404 -- the draft was not yet published. The compact math is done; the standardization and safe-implementation work is not.&lt;/p&gt;
&lt;p&gt;Falcon is the right tool when signature and key bandwidth is the binding constraint &lt;em&gt;and&lt;/em&gt; you can guarantee a vetted constant-time implementation -- and even then, not before FIPS 206 lands. Until it does, prefer ML-DSA.&lt;/p&gt;
&lt;h3&gt;6.5 HQC: the non-lattice insurance policy (pre-final)&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; NIST selected HQC on 2025-03-11 as a code-based KEM to stand alongside ML-KEM, with a draft FIPS expected in 2026 and a final around 2027 [@nist-ir-8545]. The parameters below come from the HQC specification and are pre-final [@hqc-spec]. Do not deploy it in production yet.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;HQC (&quot;Hamming Quasi-Cyclic&quot;) is the toolkit&apos;s deliberate non-lattice hedge. Its security rests on the hardness of decoding random quasi-cyclic codes -- syndrome decoding, unrelated to lattices -- so a future lattice break would leave it untouched [@hqc-spec]. It solves the problem that sank BIKE by separating the secret from the decoder: HQC encrypts by adding a low-weight error and decodes with a &lt;em&gt;public&lt;/em&gt;, fixed code (a concatenation of Reed-Muller and Reed-Solomon codes) whose decoding-failure rate can be bounded analytically and does not depend on the secret. That bounded, secret-independent DFR is exactly why NIST preferred it over BIKE [@nist-ir-8545] [@gjs-mdpc-2016].&lt;/p&gt;
&lt;p&gt;The cost is bandwidth. The encapsulation key / decapsulation key / ciphertext / shared secret sizes are 2241 / 2321 / 4433 / 32 for HQC-1, 4514 / 4602 / 8978 / 32 for HQC-3, and 7237 / 7333 / 14421 / 32 for HQC-5 [@hqc-spec]. The ciphertext is roughly four to nine times ML-KEM&apos;s. HQC is the reserve KEM, not the first choice: you carry the extra kilobytes precisely because its assumption is unrelated to everything else in the box.&lt;/p&gt;
&lt;h3&gt;6.6 Tier C: the signposts&lt;/h3&gt;
&lt;p&gt;Four more schemes sit just outside the toolkit and are worth knowing by name.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Classic McEliece&lt;/strong&gt; is the most conservative code-based KEM, unbroken since 1978, but with public keys from roughly 261 KB to over a megabyte [@classic-mceliece]. It was not selected for the FIPS set and is advancing on an ISO track; choose it only where a huge, static, long-lived key is acceptable and maximal conservatism is the goal.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;BIKE&lt;/strong&gt; is the quasi-cyclic KEM that HQC beat out; its secret-dependent decoding-failure rate was judged less mature than HQC&apos;s bounded public decoder, so NIST did not select it [@bike-suite] [@nist-ir-8545].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;XMSS and LMS&lt;/strong&gt; are the standardized stateful hash signatures -- compact, conservative, and safe only where perfect state is guaranteed [@nist-sp-800-208].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CSIDH&lt;/strong&gt; is the one post-quantum candidate for a non-interactive Diffie-Hellman-style shared key, but its quantum security is contested -- subexponential quantum attacks push it toward much larger parameters [@peikert-csieves-2019] -- and its isogeny cousin SIKE was broken in 2022 [@castryck-decru-sidh-2022]. Treat it as research, not deployment.&lt;/p&gt;
&lt;p&gt;Now the exact bytes, all in one place. The table below is the empirical anchor for every trade discussed next -- the literal number of bytes a protocol must carry for each choice.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Primitive&lt;/th&gt;
&lt;th&gt;Param set&lt;/th&gt;
&lt;th&gt;Family&lt;/th&gt;
&lt;th&gt;Public/enc key (B)&lt;/th&gt;
&lt;th&gt;Ciphertext or signature (B)&lt;/th&gt;
&lt;th&gt;NIST cat&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;ML-KEM&lt;/td&gt;
&lt;td&gt;512&lt;/td&gt;
&lt;td&gt;lattice KEM&lt;/td&gt;
&lt;td&gt;800&lt;/td&gt;
&lt;td&gt;768&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Final [@fips-203]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ML-KEM&lt;/td&gt;
&lt;td&gt;768&lt;/td&gt;
&lt;td&gt;lattice KEM&lt;/td&gt;
&lt;td&gt;1184&lt;/td&gt;
&lt;td&gt;1088&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Final [@fips-203]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ML-KEM&lt;/td&gt;
&lt;td&gt;1024&lt;/td&gt;
&lt;td&gt;lattice KEM&lt;/td&gt;
&lt;td&gt;1568&lt;/td&gt;
&lt;td&gt;1568&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Final [@fips-203]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HQC&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;code KEM&lt;/td&gt;
&lt;td&gt;2241&lt;/td&gt;
&lt;td&gt;4433&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Pre-final [@hqc-spec]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HQC&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;code KEM&lt;/td&gt;
&lt;td&gt;4514&lt;/td&gt;
&lt;td&gt;8978&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Pre-final [@hqc-spec]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HQC&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;code KEM&lt;/td&gt;
&lt;td&gt;7237&lt;/td&gt;
&lt;td&gt;14421&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Pre-final [@hqc-spec]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ML-DSA&lt;/td&gt;
&lt;td&gt;44&lt;/td&gt;
&lt;td&gt;lattice sig&lt;/td&gt;
&lt;td&gt;1312&lt;/td&gt;
&lt;td&gt;2420&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Final [@fips-204]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ML-DSA&lt;/td&gt;
&lt;td&gt;65&lt;/td&gt;
&lt;td&gt;lattice sig&lt;/td&gt;
&lt;td&gt;1952&lt;/td&gt;
&lt;td&gt;3309&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Final [@fips-204]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ML-DSA&lt;/td&gt;
&lt;td&gt;87&lt;/td&gt;
&lt;td&gt;lattice sig&lt;/td&gt;
&lt;td&gt;2592&lt;/td&gt;
&lt;td&gt;4627&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Final [@fips-204]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FN-DSA/Falcon&lt;/td&gt;
&lt;td&gt;512&lt;/td&gt;
&lt;td&gt;lattice sig&lt;/td&gt;
&lt;td&gt;897&lt;/td&gt;
&lt;td&gt;666&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Pre-final [@falcon-spec]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FN-DSA/Falcon&lt;/td&gt;
&lt;td&gt;1024&lt;/td&gt;
&lt;td&gt;lattice sig&lt;/td&gt;
&lt;td&gt;1793&lt;/td&gt;
&lt;td&gt;1280&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Pre-final [@falcon-spec]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SLH-DSA&lt;/td&gt;
&lt;td&gt;128s&lt;/td&gt;
&lt;td&gt;hash sig&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;7856&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Final [@fips-205]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SLH-DSA&lt;/td&gt;
&lt;td&gt;128f&lt;/td&gt;
&lt;td&gt;hash sig&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;17088&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Final [@fips-205]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SLH-DSA&lt;/td&gt;
&lt;td&gt;192s&lt;/td&gt;
&lt;td&gt;hash sig&lt;/td&gt;
&lt;td&gt;48&lt;/td&gt;
&lt;td&gt;16224&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Final [@fips-205]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SLH-DSA&lt;/td&gt;
&lt;td&gt;192f&lt;/td&gt;
&lt;td&gt;hash sig&lt;/td&gt;
&lt;td&gt;48&lt;/td&gt;
&lt;td&gt;35664&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Final [@fips-205]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SLH-DSA&lt;/td&gt;
&lt;td&gt;256s&lt;/td&gt;
&lt;td&gt;hash sig&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;29792&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Final [@fips-205]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SLH-DSA&lt;/td&gt;
&lt;td&gt;256f&lt;/td&gt;
&lt;td&gt;hash sig&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;49856&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Final [@fips-205]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Two footnotes complete the picture. For the KEMs, the decapsulation (secret) keys are larger than the encapsulation keys -- 1632 / 2400 / 3168 bytes for ML-KEM and 2321 / 4602 / 7333 bytes for HQC -- and both produce a 32-byte shared secret [@fips-203] [@hqc-spec]. For ML-DSA, the private keys are 2560 / 4032 / 4896 bytes [@fips-204]. Now the uncomfortable question: given all five, which do you actually deploy, and what do you give up to get it?&lt;/p&gt;
&lt;h2&gt;7. Choosing Inside the Toolkit&lt;/h2&gt;
&lt;p&gt;There is no universal winner, and looking for one is the wrong frame. In practice you make two decisions -- which KEM, and which signature -- plus one deployment choice about hybrids. Everything else follows from the bytes in the master table and the assumption you are willing to trust.&lt;/p&gt;
&lt;p&gt;The KEM decision is really ML-KEM versus HQC, because the other code-based options are signposts rather than shipping choices.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;ML-KEM-768 (final)&lt;/th&gt;
&lt;th&gt;HQC-3 (pre-final)&lt;/th&gt;
&lt;th&gt;Classic McEliece (signpost)&lt;/th&gt;
&lt;th&gt;BIKE (signpost)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Assumption&lt;/td&gt;
&lt;td&gt;Module-LWE (lattice)&lt;/td&gt;
&lt;td&gt;quasi-cyclic syndrome decoding (code)&lt;/td&gt;
&lt;td&gt;Goppa-code decoding&lt;/td&gt;
&lt;td&gt;QC-MDPC decoding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enc. key&lt;/td&gt;
&lt;td&gt;1184 B&lt;/td&gt;
&lt;td&gt;4514 B&lt;/td&gt;
&lt;td&gt;261 KB to ~1.36 MB&lt;/td&gt;
&lt;td&gt;few KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ciphertext&lt;/td&gt;
&lt;td&gt;1088 B&lt;/td&gt;
&lt;td&gt;8978 B&lt;/td&gt;
&lt;td&gt;~100 to 200 B&lt;/td&gt;
&lt;td&gt;few KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best-known attack&lt;/td&gt;
&lt;td&gt;lattice sieving $\approx 2^{0.292\beta}$&lt;/td&gt;
&lt;td&gt;information-set decoding (exp.)&lt;/td&gt;
&lt;td&gt;information-set decoding (exp.)&lt;/td&gt;
&lt;td&gt;ISD, plus a reaction attack given a failure oracle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DFR&lt;/td&gt;
&lt;td&gt;$2^{-164.8}$&lt;/td&gt;
&lt;td&gt;bounded, secret-independent&lt;/td&gt;
&lt;td&gt;negligible&lt;/td&gt;
&lt;td&gt;secret-dependent (the problem)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maturity&lt;/td&gt;
&lt;td&gt;final and deployed&lt;/td&gt;
&lt;td&gt;selected 2025, pre-final&lt;/td&gt;
&lt;td&gt;ISO track, not in FIPS&lt;/td&gt;
&lt;td&gt;not selected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best suited for&lt;/td&gt;
&lt;td&gt;default KEM everywhere&lt;/td&gt;
&lt;td&gt;non-lattice diversity backup&lt;/td&gt;
&lt;td&gt;huge static keys, max conservatism&lt;/td&gt;
&lt;td&gt;superseded by HQC&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;ML-KEM wins on size and ubiquity. HQC&apos;s entire reason to exist is that its assumption is unrelated to ML-KEM&apos;s, so a lattice break would not take both down -- and you pay roughly eight times the ciphertext for that insurance [@fips-203] [@hqc-spec] [@nist-ir-8545].&lt;/p&gt;
&lt;p&gt;The signature decision spans three finalists on very different paradigms.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;ML-DSA-65 (final)&lt;/th&gt;
&lt;th&gt;FN-DSA / Falcon-512 (pre-final)&lt;/th&gt;
&lt;th&gt;SLH-DSA-128s (final)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Construction&lt;/td&gt;
&lt;td&gt;Fiat-Shamir with aborts&lt;/td&gt;
&lt;td&gt;GPV hash-and-sign over NTRU&lt;/td&gt;
&lt;td&gt;stateless hash-based&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Assumption&lt;/td&gt;
&lt;td&gt;Module-LWE and Module-SIS&lt;/td&gt;
&lt;td&gt;NTRU and SIS (lattice)&lt;/td&gt;
&lt;td&gt;hash function only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Public key&lt;/td&gt;
&lt;td&gt;1952 B&lt;/td&gt;
&lt;td&gt;897 B&lt;/td&gt;
&lt;td&gt;32 B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Signature&lt;/td&gt;
&lt;td&gt;3309 B&lt;/td&gt;
&lt;td&gt;666 B&lt;/td&gt;
&lt;td&gt;7856 B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Signing&lt;/td&gt;
&lt;td&gt;fast, variable-time&lt;/td&gt;
&lt;td&gt;fast, floating-point sampler&lt;/td&gt;
&lt;td&gt;very slow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Implementation risk&lt;/td&gt;
&lt;td&gt;low (no floating point)&lt;/td&gt;
&lt;td&gt;high (constant-time floating point is hard)&lt;/td&gt;
&lt;td&gt;low (hashing only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maturity&lt;/td&gt;
&lt;td&gt;final, the default&lt;/td&gt;
&lt;td&gt;FIPS 206 in development&lt;/td&gt;
&lt;td&gt;final&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best suited for&lt;/td&gt;
&lt;td&gt;general-purpose default&lt;/td&gt;
&lt;td&gt;size-critical, constant-time guaranteed&lt;/td&gt;
&lt;td&gt;firmware and roots, low volume&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;There is no free lunch in that table [@fips-204] [@falcon-spec] [@fips-205]. Falcon is smallest but hardest to implement safely and not yet final; SLH-DSA is the safest to trust but by far the largest and slowest; ML-DSA is the sensible middle and the recommended default.&lt;/p&gt;
&lt;p&gt;To feel the gap, anchor on the classical world this series has used throughout. An Ed25519 signature is 64 bytes; an X25519 public key is 32. Nothing in the post-quantum toolkit comes close, as Part 15 on elliptic curves makes vivid.&lt;/p&gt;
&lt;p&gt;The smallest post-quantum signature, Falcon-512 at 666 bytes, is about ten times larger and carries a floating-point hazard; the most conservative, SLH-DSA-128s at 7856 bytes, is about one hundred and twenty times larger; and the default KEM ciphertext, ML-KEM-768 at 1088 bytes, is about thirty-four times an X25519 share [@falcon-spec] [@fips-205] [@fips-203]. Every column of these tables buys one property -- small size, easy constant-time code, a conservative assumption, or non-lattice diversity -- by giving up another.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; No post-quantum primitive wins on every axis. The five are not a menu awaiting a single winner; they are deliberate coverage of a trade surface, chosen so that whatever your binding constraint -- bytes, speed, assumption conservatism, or implementation safety -- one of them is the defensible answer.&lt;/p&gt;
&lt;/blockquote&gt;

The toolkit is five points on a trade surface, not an arbitrary menu.
&lt;p&gt;One more choice cuts across both decisions: hybrid versus pure. The shipping default, X25519MLKEM768, runs a classical X25519 exchange and a post-quantum ML-KEM-768 encapsulation together and combines both shared secrets, so the session stays secure as long as &lt;em&gt;either&lt;/em&gt; half holds [@openssl-35-notes]. During a migration that is the conservative posture: it defends against a future quantum computer and against an implementation bug in the young post-quantum half at once -- a belt-and-suspenders design, the security-definition thinking of Part 1 made concrete. These trades feel like engineering. Underneath them sits something humbler: we cannot prove any of it is hard.&lt;/p&gt;
&lt;h2&gt;8. What We Cannot Prove&lt;/h2&gt;
&lt;p&gt;Here is the headline most readers do not expect: none of the five rests on an unconditional hardness proof. &quot;Standardized by NIST&quot; does not mean &quot;proven secure.&quot; It means &quot;no efficient attack is known, backed by decades of failed attempts and, for lattices, an unusually strong reduction.&quot; That is a different and more honest claim.&lt;/p&gt;
&lt;p&gt;The lattice story is the one people most often overstate. Ajtai and then Regev proved worst-case-to-average-case reductions: breaking random instances is as hard as breaking the worst case [@ajtai-1996] [@regev-lwe-2005]. That is remarkable, and it is genuinely reassuring.&lt;/p&gt;
&lt;p&gt;But three caveats matter. First, those reductions are cleanest for &lt;em&gt;plain&lt;/em&gt; LWE, while the standards use &lt;em&gt;structured&lt;/em&gt; Module-LWE and NTRU, whose reductions are weaker or looser. Second, the actual parameters are not chosen from the reduction at all; they are sized against the best-known attack, lattice sieving, whose cost is heuristically $\approx 2^{0.292\beta}$ classically and roughly $2^{0.265\beta}$ quantumly under debated memory assumptions [@bdgl-sieving-2015]. Third, at the approximation factors these schemes use, the underlying lattice problems sit in $\mathsf{NP} \cap \mathsf{coNP}$, so they are not NP-hard under standard assumptions [@aharonov-regev-2005]. A genuine super-polynomial lower bound for any of them would prove $\mathsf{P} \neq \mathsf{NP}$ -- which no one can currently do.&lt;/p&gt;
&lt;p&gt;Codes and hashes are no different in kind. General syndrome decoding is NP-hard, but HQC&apos;s security depends on the &lt;em&gt;average-case&lt;/em&gt; hardness of decoding random quasi-cyclic codes, which is an assumption, not a theorem [@hqc-spec]. SLH-DSA reduces tightly to standard properties of its hash function, with no algebraic structure to exploit -- the most conservative bet in the box, but still a bet [@fips-205].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Realize what this means taken together: the security of the entire toolkit is a &lt;em&gt;monitored cryptanalytic bet&lt;/em&gt;, not a proof. The strong lattice reductions do not cover the structured schemes actually deployed; the parameters are justified empirically; and a real hardness proof for any of them would settle the biggest open question in computer science. This is precisely why the field standardized a diversified portfolio and keeps a non-lattice spare. The humility is not a weakness in the design -- it &lt;em&gt;is&lt;/em&gt; the design.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Two results in this area are not assumptions but hard walls, and they pull in opposite directions. The first is Shor&apos;s algorithm itself: no choice of RSA, Diffie-Hellman, or elliptic-curve parameters can ever be post-quantum, because the attack is a capability of the adversary, not a bound you can tune [@shor-1994]. The second constrains the replacements.&lt;/p&gt;

A NIKE lets two parties who know only each other&apos;s long-term public keys compute a shared secret with no interaction -- the static-static magic of Diffie-Hellman, where two published keys silently agree. A KEM does not provide this: encapsulation produces a fresh ciphertext that must be sent, so at least one message is required. There is no efficient, well-trusted post-quantum NIKE (the only candidate, CSIDH, has contested quantum security under subexponential quantum attack [@peikert-csieves-2019]).
&lt;p&gt;That second wall -- KEM is not NIKE -- is why post-quantum migration is not a mechanical find-and-replace. Any protocol that relied on Diffie-Hellman&apos;s non-interactive static-static agreement has to be redesigned around an interactive KEM handshake, as Part 18 on Diffie-Hellman foreshadowed. It is a design-level impossibility, not a tuning problem.&lt;/p&gt;
&lt;p&gt;One more subtlety links two sections: for the FO-transformed KEMs, the decryption-failure rate is a &lt;em&gt;security&lt;/em&gt; bound, not merely a correctness figure. A noticeable, secret-correlated failure rate is an oracle -- the exact mechanism behind the BIKE reaction attack -- which is why ML-KEM specifies rates like $2^{-164.8}$ and HQC insists on an analytically bounded one [@gjs-mdpc-2016].&lt;/p&gt;
&lt;p&gt;Put it all together and the shape of the toolkit becomes inevitable. The theoretically perfect primitive would have elliptic-curve-sized keys and signatures, fast constant-time software with no floating point, a conservative and well-understood assumption, and strong chosen-ciphertext or unforgeability guarantees. No known construction reaches all four corners at once: lattices are small and fast on a young, structured assumption; hashes are conservative but huge; codes offer diversity but cost kilobytes. The five primitives are the field&apos;s best simultaneous coverage of that surface. If we cannot prove hardness, the honest posture is to keep asking what we still cannot do -- and to keep a spare.&lt;/p&gt;
&lt;h2&gt;9. The Frontier the Toolkit Does Not Close&lt;/h2&gt;
&lt;p&gt;A field guide should be honest about what remains open. Seven problems sit on the near horizon, and together they explain why the toolkit is best understood as a monitored bet with an insurance policy attached.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The signature-size wall.&lt;/strong&gt; No post-quantum signature reaches the 64-byte classical world while keeping a conservative assumption &lt;em&gt;and&lt;/em&gt; an easy constant-time implementation. Falcon-512 is 666 bytes but floating-point; ML-DSA-44 is 2420 bytes; SLH-DSA-128s is 7856 bytes and up. Certificate chains, TLS handshakes, DNSSEC responses, and firmware manifests all multiply signature size by depth, so a few-kilobyte signature reshapes protocols. NIST&apos;s ongoing &quot;Additional Digital Signature Schemes&quot; on-ramp is the active response, hunting for small-signature options on different assumptions [@nist-pqc-project].This on-ramp is deliberately looking beyond lattices -- for schemes whose assumptions differ from ML-DSA and Falcon -- so that a future small-signature standard also widens the toolkit&apos;s assumption diversity rather than deepening its lattice exposure.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Constant-time Falcon without floating point.&lt;/strong&gt; Falcon&apos;s fast-Fourier Gaussian sampler is defined over floating-point arithmetic, and a portable, high-precision, provably constant-time sampler is hard to guarantee across compilers and CPUs. This is the chief obstacle to shipping FN-DSA safely and the reason it standardizes last [@pornin-ctfalcon-2019] [@howe-isochronous-2019]. The motivating attack -- key recovery from Gram-Schmidt norm leakage -- is concrete, not hypothetical [@fouque-gsnorm-2019].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Shrinking code-based ciphertexts.&lt;/strong&gt; HQC buys assumption diversity at 4.4 to 14.4 KB ciphertexts, and the smaller-key alternative (BIKE) was set aside precisely because its secret-dependent failure rate is a reaction-attack surface. An open goal is a code-based KEM with McEliece-like conservatism, ML-KEM-like size, and a provable secret-independent DFR [@nist-ir-8545].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Formally verified, side-channel-hardened implementations of all five.&lt;/strong&gt; KyberSlash showed that even widely used reference code can leak through timing [@kyberslash-site]. Machine-checked constant-time implementations of ML-KEM exist, but ML-DSA&apos;s variable-time abort loop and FN-DSA&apos;s floating point are materially harder to verify end to end. The standards are only as safe as the code that runs them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Is the algebraic structure free?&lt;/strong&gt; Ring-LWE, Module-LWE, and NTRU all add ring structure for compact keys and fast transforms. No attack exploits that structure at the standardized parameters, but there is no proof it is as hard as unstructured LWE -- and all three lattice primitives share the exposure, so a structural breakthrough could touch most of the toolkit at once. The Module-LWE design dilutes structure as a hedge, but the conjecture that it is essentially as hard as plain LWE remains believed and unproven.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Migrating static-static protocols.&lt;/strong&gt; Because a KEM is not a NIKE, any protocol that assumed non-interactive Diffie-Hellman agreement must be redesigned, not reconfigured. Interactive hybrid handshakes cover key establishment well; a practical, trusted post-quantum NIKE does not exist.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The real quantum cost of sieving.&lt;/strong&gt; The quantum sieving exponent near $2^{0.265\beta}$ depends on memory and qRAM models whose real-world cost is uncertain, and NIST&apos;s security categories inherit that uncertainty [@bdgl-sieving-2015]. Conservative defaults -- recommending Category-3 ML-KEM-768 rather than the smaller set -- absorb the doubt, but a settled cost model would tighten every lattice parameter.&lt;/p&gt;
&lt;p&gt;None of that blocks you from shipping the right thing today. Here is exactly what to ship.&lt;/p&gt;
&lt;h2&gt;10. Exact Decision Rules&lt;/h2&gt;
&lt;p&gt;Enough theory. Here are defensible defaults you can carry into a design review, phrased as &quot;use X with these parameters in case Y.&quot;&lt;/p&gt;

flowchart TD
    Q1{&quot;Signing or key exchange?&quot;}
    Q1 -- Key exchange --&amp;gt; K1{&quot;Bandwidth very tight and Category 1 acceptable?&quot;}
    K1 -- Yes --&amp;gt; KEM512[ML-KEM-512 in a hybrid]
    K1 -- No --&amp;gt; K2{&quot;Long-term or Category 5 secret?&quot;}
    K2 -- Yes --&amp;gt; KEM1024[ML-KEM-1024 in a hybrid]
    K2 -- No --&amp;gt; KEM768[ML-KEM-768 hybrid, the default]
    Q1 -- Signing --&amp;gt; S1{&quot;Low-volume firmware or root of trust?&quot;}
    S1 -- Yes --&amp;gt; SLH[SLH-DSA-128s or 128f]
    S1 -- No --&amp;gt; S2{&quot;Is signature size the hard limit?&quot;}
    S2 -- No --&amp;gt; MLDSA[ML-DSA-65, the default]
    S2 -- Yes --&amp;gt; FN[Consider FN-DSA, vetted constant-time only, after FIPS 206]
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Key establishment (TLS, SSH, VPN):&lt;/strong&gt; use &lt;strong&gt;ML-KEM-768 in a hybrid&lt;/strong&gt; (X25519MLKEM768). It is the shipping default and the conservative middle category [@openssl-35-notes] [@openssh-99-notes]. Drop to ML-KEM-512 only under tight bandwidth with Category-1 acceptance; step up to ML-KEM-1024 for Category-5 or long-lived secrets.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;General-purpose signatures:&lt;/strong&gt; use &lt;strong&gt;ML-DSA-65&lt;/strong&gt; (Category 3). No floating point, easy constant-time, moderate sizes [@fips-204].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Firmware, boot, root-of-trust (low volume, maximum conservatism):&lt;/strong&gt; use &lt;strong&gt;SLH-DSA-128s&lt;/strong&gt; for smaller signatures or &lt;strong&gt;128f&lt;/strong&gt; for faster signing. You sign rarely, so absorb the large signature in exchange for a hash-only assumption [@fips-205].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;When signature size is the binding constraint:&lt;/strong&gt; consider &lt;strong&gt;FN-DSA / Falcon&lt;/strong&gt; -- but only with a vetted constant-time implementation, and &lt;strong&gt;not in production until FIPS 206 is final&lt;/strong&gt; [@fips-206-perlner-2025]. Until then, prefer ML-DSA.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;For KEM assumption diversity:&lt;/strong&gt; plan for &lt;strong&gt;HQC&lt;/strong&gt; as a standardized non-lattice backup &lt;strong&gt;once its FIPS lands&lt;/strong&gt;, not today [@nist-ir-8545]. If you need maximal conservatism now and can absorb a huge static key, Classic McEliece is the code-based option outside the FIPS set [@classic-mceliece].&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The single most useful thing you can build is an intuition for how many bytes each choice adds. Run the numbers.&lt;/p&gt;
&lt;p&gt;{`
// Illustrative only. Estimate the extra bytes post-quantum adds versus classical
// X25519 / Ed25519, for a KEM share and for a 3-certificate chain.&lt;/p&gt;
&lt;p&gt;const sizes = {
  &apos;Ed25519&apos;:      { sig: 64,   pk: 32 },
  &apos;ML-DSA-65&apos;:    { sig: 3309, pk: 1952 },
  &apos;Falcon-512&apos;:   { sig: 666,  pk: 897 },
  &apos;SLH-DSA-128s&apos;: { sig: 7856, pk: 32 },
};&lt;/p&gt;
&lt;p&gt;// A chain of 3 certificates, each carrying one signature + one public key.
function chainBytes(name) {
  const s = sizes[name];
  return (s.sig + s.pk) * 3;
}&lt;/p&gt;
&lt;p&gt;for (const n of [&apos;Ed25519&apos;,&apos;ML-DSA-65&apos;,&apos;Falcon-512&apos;,&apos;SLH-DSA-128s&apos;]) {
  console.log(n.padEnd(14), String(chainBytes(n)).padStart(6), &apos;bytes over a 3-cert chain&apos;);
}&lt;/p&gt;
&lt;p&gt;console.log(&apos;---&apos;);
const x25519Share = 32 + 32;            // classical key share, round trip
const mlkemAdds   = 1184 + 1088;        // ML-KEM-768 key + ciphertext
console.log(&apos;KEM share, classical X25519 :&apos;, x25519Share, &apos;bytes&apos;);
console.log(&apos;KEM share, ML-KEM-768 hybrid:&apos;, x25519Share + mlkemAdds, &apos;bytes&apos;);
`}&lt;/p&gt;
&lt;p&gt;Rules pick the primitive; discipline keeps it safe. A short pitfall list, drawn straight from the failure catalog:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Do not divide a secret by the modulus in variable time.&lt;/strong&gt; That was KyberSlash; use constant-time (Barrett) reduction and a library whose constant-time behavior has been tested [@kyberslash-site].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prefer hedged (randomized) signing for ML-DSA, and feed it a good RNG.&lt;/strong&gt; The randomized mode is the default and is more resilient to fault and nonce mishaps [@fips-204].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use context strings&lt;/strong&gt; to domain-separate signatures across applications and prevent cross-protocol reuse [@fips-204].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keep implicit rejection constant-time.&lt;/strong&gt; Never let a KEM surface a decapsulation failure as a distinguishable error or timing tell.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Do not hand-roll any of these.&lt;/strong&gt; Every primitive has subtle side channels; use standard libraries.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; During migration, run post-quantum alongside classical (X25519MLKEM768) so a break or bug in either half is survivable, and migrate &lt;em&gt;key establishment&lt;/em&gt; before signatures -- harvest-now-decrypt-later already threatens today&apos;s recorded traffic, while forged signatures require an attacker who is present in the future [@openssl-35-notes].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;On availability: the finalized three are production-ready across the toolchain. OpenSSL 3.5 ships X25519MLKEM768 as a default key share, OpenSSH enabled &lt;code&gt;mlkem768x25519-sha256&lt;/code&gt; by default in 9.9 and made it the default in 10.0, and ML-KEM and ML-DSA are broadly available across open-source libraries -- liboqs, BoringSSL, AWS-LC, Microsoft SymCrypt, Bouncy Castle, and pyca/cryptography -- with formally verified ML-KEM through the libcrux line [@openssl-35-notes] [@openssh-pq] [@open-quantum-safe]. FN-DSA and HQC are experimental only until their FIPS documents are final. For a sense of how this looks in real deployments, this blog&apos;s companion posts trace &lt;a href=&quot;https://paragmali.com/blog/post-quantum-cryptography-on-windows-the-thirty-year-migrati/&quot; rel=&quot;noopener&quot;&gt;the post-quantum migration on Windows&lt;/a&gt; and &lt;a href=&quot;https://paragmali.com/blog/the-thirty-year-migration-ships-in-a-pip-install-how-post-qu/&quot; rel=&quot;noopener&quot;&gt;the moment ML-KEM arrived in an ordinary &lt;code&gt;pip install&lt;/code&gt;&lt;/a&gt;. The forthcoming Part 21 on crypto-agility and cryptographic bills of materials covers how to keep these choices swappable as the toolkit evolves.&lt;/p&gt;

Post-quantum migration now has deadlines attached. NIST&apos;s guidance and its IR 8547 transition plan point toward deprecating quantum-vulnerable algorithms by 2035, and comparable government profiles set similar horizons [@nist-pqc-project]. The practical reading is simple: inventory where you use RSA, Diffie-Hellman, and ECC now, because a decade is not long for a full cryptographic transition, and the harvest-now clock started before the standards were even published.

If you have OpenSSL 3.5 or later installed, you can list its post-quantum groups and signature algorithms with `openssl list -kem-algorithms` and `openssl list -signature-algorithms`. Seeing `ML-KEM-768` and `X25519MLKEM768` in that output is the concrete, on-your-own-machine version of this entire article: the migration is not a forecast, it is already in your crypto library [@openssl-35-notes].
&lt;p&gt;The rules above answer &quot;what.&quot; These next answer the questions that come up in review.&lt;/p&gt;
&lt;h2&gt;11. Questions From the Review Room&lt;/h2&gt;


No. There is no cryptanalytic break of any of the five. The only real-world failures are implementation leaks -- KyberSlash&apos;s secret-dependent division timing [@kyberslash-site] and Falcon&apos;s floating-point Gram-Schmidt leakage [@fouque-gsnorm-2019] -- and both are fixed by better code, not new math. The era&apos;s two famous breaks, SIKE and Rainbow, hit schemes that were never selected for the toolkit [@castryck-decru-sidh-2022] [@beullens-rainbow-2022].


Against a classical attacker, yes. Against harvest-now-decrypt-later, not for long-lived secrets: an adversary can record today&apos;s session and decrypt it once a quantum computer arrives, which is why you migrate key establishment first and why hybrids are already shipping [@nist-pqc-project] [@openssl-35-notes].


Not in general. A KEM is not a non-interactive key exchange -- there is no trusted post-quantum static-static agreement -- so protocols that relied on that property must be redesigned around an interactive KEM handshake rather than reconfigured in place.


No. FN-DSA (Falcon) was still in development toward FIPS 206 as of this writing [@fips-206-perlner-2025], and HQC was only selected on 2025-03-11 with a draft FIPS pending [@nist-ir-8545]. Do not ship either in production yet.


Because no single primitive wins on size, speed, assumption conservatism, and maturity at once, and because spreading the toolkit across three unrelated hard problems -- lattices, hashes, and codes -- means one mathematical break cannot take everything down. The 2022 breaks of SIKE and Rainbow, both outside the toolkit, are the empirical argument for that hedge [@nist-ir-8545] [@castryck-decru-sidh-2022].


Essentially yes. ML-KEM (FIPS 203) is the standardized CRYSTALS-Kyber with standardization edits, and the same relationship holds for Dilithium to ML-DSA and SPHINCS+ to SLH-DSA [@fips-203] [@crystals-kyber]. If you learned Kyber, you already know ML-KEM.


No and no. All five primitives run on ordinary classical hardware today [@nist-pqc-project]. Quantum key distribution is a physics-layer technique that uses quantum hardware to exchange keys; post-quantum cryptography is classical software designed to resist quantum *attacks*. They solve related problems by completely different means.

&lt;p&gt;Step back to the shape of the whole thing. One event in 1994 condemned all deployed public-key cryptography [@shor-1994]. The field&apos;s answer was not a single replacement but a portfolio hedged across three unrelated assumptions and tuned to five different binding constraints, three of them already law and two still in progress. The most striking fact remains the quietest one: after a decade of open, adversarial cryptanalysis, nothing in the toolkit has been broken -- only its early code has leaked.&lt;/p&gt;
&lt;p&gt;The real test is still ahead. When the next break comes, and history suggests one eventually will, the entire point of this design is that it lands on one assumption family while the others carry the load. That is not a promise that the math is unbreakable. It is a bet, made in the open, that diversity outlasts any single idea -- and a spare, HQC, waiting in reserve for the day the bet is called.&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;the-post-quantum-toolkit&quot; keyTerms={[
  { term: &quot;ML-KEM (FIPS 203)&quot;, definition: &quot;The standardized Module-LWE key-encapsulation mechanism; the deployed post-quantum KEM, small and fast, secured by FO with implicit rejection.&quot; },
  { term: &quot;ML-DSA (FIPS 204)&quot;, definition: &quot;The default post-quantum signature; a Fiat-Shamir-with-aborts lattice scheme using uniform integers and no floating point.&quot; },
  { term: &quot;SLH-DSA (FIPS 205)&quot;, definition: &quot;The conservative backstop signature; stateless hash-based, resting only on hash-function security, with tiny keys but very large signatures.&quot; },
  { term: &quot;FN-DSA / Falcon&quot;, definition: &quot;Pre-final (FIPS 206 in development). GPV hash-and-sign over NTRU with the smallest signatures, but a hard-to-implement floating-point sampler.&quot; },
  { term: &quot;HQC&quot;, definition: &quot;Pre-final (selected 2025-03-11). A code-based KEM providing non-lattice assumption diversity, with a public decoder and a bounded, secret-independent failure rate.&quot; },
  { term: &quot;Harvest now, decrypt later&quot;, definition: &quot;Recording encrypted traffic today to decrypt once quantum computers exist; the reason key establishment migrates first.&quot; },
  { term: &quot;Fujisaki-Okamoto with implicit rejection&quot;, definition: &quot;The transform giving KEMs chosen-ciphertext security by returning a pseudo-random key on failure, closing the decapsulation-failure oracle.&quot; },
  { term: &quot;Fiat-Shamir with aborts&quot;, definition: &quot;Signing by reject-and-restart so the released transcript is provably independent of the secret key.&quot; },
  { term: &quot;Transcript leakage&quot;, definition: &quot;When public outputs statistically depend on the secret key, so enough valid outputs recover it, as in the NTRUSign parallelepiped break.&quot; },
  { term: &quot;KEM is not NIKE&quot;, definition: &quot;A key-encapsulation mechanism cannot replace non-interactive static-static Diffie-Hellman, so some protocols need redesign, not a drop-in swap.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>post-quantum-cryptography</category><category>ml-kem</category><category>ml-dsa</category><category>slh-dsa</category><category>falcon</category><category>hqc</category><category>lattice-cryptography</category><category>cryptography</category><author>noreply@paragmali.com (Parag Mali)</author></item></channel></rss>