up:: The New Standards MOC

FIPS 204 (ML-DSA)

FIPS 204 is the NIST standard that specifies ML-DSA, the primary post-quantum algorithm for digital signatures, and the general-purpose replacement for the classical signing (ECDSA and many RSA signature uses) that a quantum computer breaks. Finalized on August 13, 2024 as one of the first three NIST post-quantum standards, it’s the answer to the other half of the migration question: once you’ve replaced the way two systems agree on a secret, how do you prove that a certificate, a software update, or a signed record is authentic and unaltered? ML-DSA is the standardized form of the algorithm known during the NIST competition as CRYSTALS-Dilithium.

The short version:

  • ML-DSA does digital signatures, proving who signed something and that it wasn’t changed afterward. It is not for key establishment. (Key exchange is ML-KEM.)
  • It’s built on lattice math (Module-LWE and Module-SIS), the most deployment-ready post-quantum family.
  • It’s the general-purpose default for signatures. SLH-DSA is the more conservative hash-based alternative, and FN-DSA is the compact one.
  • The real cost is size. Its keys and signatures are much larger than elliptic-curve ones, so the integration work lands on certificates, parsers, and trust stores, not on CPU.
  • NIST defines three parameter sets, ML-DSA-44, ML-DSA-65, and ML-DSA-87, at security categories 2, 3, and 5.

Think of a digital signature like a wax seal on a letter, except it’s mathematically impossible to forge and it changes if anyone edits a single word of what’s inside. The signer holds a private key that stamps the seal; anyone with the matching public key can check that the seal is genuine and the contents are intact. ML-DSA does exactly that job, but the math behind the seal rests on hard lattice problems instead of the factoring and discrete logarithms that Shor’s algorithm destroys, so the seal still holds against a quantum-capable forger.

What problem does ML-DSA solve?

ML-DSA’s job is digital signing and verification: proving that a message, certificate, or software artifact came from the expected signer and was not altered after signing, in a way meant to stay secure against a quantum-capable adversary. It works in the same shape as any signature scheme:

  1. Key generation. The signer generates a public verification key and a private signing key.
  2. Signing. The signer computes a signature over the message (or its digest) using the private key.
  3. Verification. Anyone with the public key checks that the signature is valid for that exact message.

NIST describes the intended uses plainly: detecting unauthorized modifications to data, authenticating the identity of the signer, and supporting non-repudiation, so a signer can’t later credibly deny having signed. That covers software distribution, data storage, electronic transactions, and other integrity-sensitive systems. What’s different from classical signing is the foundation: the signature is built from structured lattice mathematics rather than factoring or discrete logs.

Source: NIST FIPS 204, Module-Lattice-Based Digital Signature Standard, August 2024.

What cryptographic family is ML-DSA?

ML-DSA belongs to lattice-based cryptography, the same broad family as ML-KEM, but it solves the signature problem instead of key establishment. The standard states its security rests on the Module Learning With Errors (MLWE) and Module-SIS problems over a polynomial ring. Structured lattices give it a strong balance of speed, practicality, and manageable artifact size, which is why it’s the general-purpose default rather than a conservative backup.

That same reliance on one math family is why the standardized portfolio deliberately keeps alternatives in play. SLH-DSA rests on hash-based assumptions, a more conservative foundation that trades larger signatures for not depending on lattice hardness at all. Some architects want that alternate-assumption option in reserve for long-lived roots of trust, not because ML-DSA is suspect, but because betting every signature on a single family of assumptions is a concentration worth hedging. That instinct is crypto-agility, and it’s the right one.

What does ML-DSA replace?

FIPS 204 is finalized, published August 13, 2024, one of the first three NIST post-quantum standards alongside ML-KEM (FIPS 203) and SLH-DSA (FIPS 205). It’s a real federal standard, not a draft or a candidate, and in most roadmaps it’s a Phase 1 priority. It takes over the general-purpose signing role that ECDSA and many RSA signatures fill today:

  • Replaces: ECDSA and many RSA signature deployments, everywhere the job is proving authenticity and integrity, in certificates, code and software signing, signed APIs and service identities, document and artifact integrity, and device or platform identity.
  • Does not replace: ECDH, DH, or RSA key transport. Those establish shared secrets, and that’s the KEM side of the transition, handled by ML-KEM.

A common conceptual error is treating “post-quantum” as one switch. Key establishment and signatures are separate jobs with separate standards and separate operational constraints, and a migration has to address both.

What are the parameter sets and sizes?

FIPS 204 defines three parameter sets at increasing security levels, and the sizes are the thing to internalize, because that’s where the engineering cost lives. These figures are verbatim from the standard’s Table 2 (sizes in bytes) and Table 1 (security categories):

Parameter setNIST security categoryPrivate keyPublic keySignature
ML-DSA-44Category 22,560 bytes1,312 bytes2,420 bytes
ML-DSA-65Category 34,032 bytes1,952 bytes3,309 bytes
ML-DSA-87Category 54,896 bytes2,592 bytes4,627 bytes

For scale, an ML-DSA-44 signature is 2,420 bytes and its public key is over a kilobyte, where a classical elliptic-curve public key is 32 bytes and an ECDSA signature is a small fraction of ML-DSA’s. Signing and verification are fast enough for mainstream adoption, which is one reason NIST chose ML-DSA as the general-purpose default. The bytes on the wire and in the certificate are what you plan around, not the compute. Signatures are larger than ECDSA’s but generally more manageable than the conservative hash-based signatures of SLH-DSA. ML-DSA-65 is a typical starting default for category-3 deployments.

Source: NIST FIPS 204, Tables 1 and 2, August 2024.

What does deploying ML-DSA actually look like?

ML-DSA is fast enough to be the default and large enough that you can’t treat it as invisible. The compute is realistic on mainstream hardware; the work is absorbing bigger artifacts into systems that were built around small elliptic-curve signatures. The friction shows up in a few predictable places:

  • Certificates grow. Larger keys and signatures increase certificate size and can stress certificate chains, parsers, transport limits, and validation logic that assumed classical dimensions.
  • Code signing is usually fine, but check the plumbing. Larger signatures are typically tolerable for software updates, but the packaging, manifest, and metadata systems around them still need testing.
  • Verifiers are the long pole. A signature is only useful if every relevant verifier can process it. Trust stores, CAs, HSM workflows, and identity systems often lag the standard.
  • It enters as a provider, not application code. Like ML-KEM, ML-DSA typically arrives through a swappable cryptographic provider (OpenSSL via the Open Quantum Safe provider, or the BouncyCastle provider in Java), so applications don’t usually change directly. That’s crypto-agility doing its job.

On constrained hardware the tradeoff flips in an interesting way. In one 2026 measurement on an ESP32 running DTLS 1.3, certificate verification with ML-DSA-44 was roughly 11 times faster than ECDSA (about 17 ms versus 194 ms), yet ML-DSA-44 was the dominant memory cost, adding several kilobytes of code and about 28 kB of peak heap over the ECDSA build. So on small devices ML-DSA is fast but memory-hungry, and the binding constraint is heap footprint, not speed. See Constrained-Device PQC.

Source: Blanco-Romero et al., arXiv:2603.10274 (2026), Tables 1 and 5.

How does ML-DSA work internally, step by step?

You never touch this layer to deploy ML-DSA, and understanding it is what makes the “no floating-point,” the constant-time-rejection warning, and the retry-loop cost legible. ML-DSA is a Fiat-Shamir with aborts signature: it takes an interactive identification protocol, collapses it into a non-interactive signature by deriving the verifier’s challenge from a hash, and adds a rejection-sampling loop so no signature ever leaks the secret. Its unforgeability rests on Module-LWE together with the signature-side companion problem, Module-SIS, which is what stops an attacker from producing a short vector that satisfies the public equation. Everything below traces to FIPS 204 Algorithms 1 through 8.

Key generation (Algorithm 6). A 32-byte seed is hashed into three seeds. From the public seed rho, ExpandA builds the public matrix A (stored in NTT form so multiplication stays fast). From the private seed, ExpandS samples two short secret vectors, s1 and s2. The public value is t = A·s1 + s2, a noisy Module-LWE instance. To shave bytes off the public key, Power2Round splits every coefficient of t into a high part t1 (published) and a low part t0 (kept private and reconstructed by the verifier through the hint mechanism below). The public key is (rho, t1), the private key holds s1, s2, and t0.

Signing, the rejection-sampling loop (Algorithm 7). This is a while loop that retries until it produces an acceptable signature. Each pass runs the following moves:

  1. Commit. ExpandMask samples a masking vector y with coefficients bounded by the parameter gamma1. The signer computes w = A·y and keeps only its high bits, w1 = HighBits(w). That w1 is the commitment.
  2. Challenge. The commitment and the message digest are hashed into c-tilde, and SampleInBall turns that hash into a small challenge polynomial c with exactly tau nonzero ±1 coefficients. This hash-derived challenge is the Fiat-Shamir move that removes the need for an interactive verifier.
  3. Respond. The signer computes z = y + c·s1. The mask y hides the secret term c·s1, which is the whole reason a fresh y is drawn every attempt.
  4. Reject or accept. The loop restarts ((z, h) ← ⊥) if ‖z‖∞ ≥ gamma1 − beta or if ‖LowBits(w − c·s2)‖∞ ≥ gamma2 − beta, where beta = tau · η. Those bounds are the aborts: they discard any candidate whose distribution would reveal information about s1, so a released signature is statistically independent of the secret. A second check rejects if ‖c·t0‖∞ ≥ gamma2 or the hint carries too many set bits.

Because the loop retries, signing takes a variable number of passes, and both the accept and reject paths must be genuinely constant-time or the timing itself leaks the secret. That is why the gotchas section flags rejection sampling as a side-channel surface.

Hint generation (MakeHint). The verifier recomputes w1 from public data alone, but it lacks the private low part t0, so its arithmetic would land a hair off. MakeHint produces a compact hint h, a sparse bit vector recording exactly which coefficients need a carry correction, and packs it into the signature. The signature is (c-tilde, z, h).

Verification (Algorithm 8). The verifier rebuilds A from rho, derives c from c-tilde, computes w1' = HighBits(A·z − c·t1·2^d) using the hint h to correct for the missing t0, and accepts only if re-hashing its reconstructed commitment reproduces the c-tilde in the signature and z is short enough. A valid short z that satisfies the public equation is precisely a Module-SIS solution tied to the message, which is the forgery an attacker cannot manufacture.

For the three parameter sets (ML-DSA-44 / 65 / 87) the loop bounds are, verbatim from the standard: tau = 39 / 49 / 60, gamma1 = 2^17 / 2^19 / 2^19, gamma2 = (q−1)/88 / (q−1)/32 / (q−1)/32, and beta = 78 / 196 / 120.

Source: NIST FIPS 204, Algorithms 6, 7, and 8, and Table 1 (tau, gamma1, gamma2, beta = tau·η), August 2024.

What are the common gotchas?

ML-DSA is easy to underestimate operationally, because signatures touch far more hidden systems than key exchange does. The ones worth knowing:

  • Signature migration is mostly cert-chain, verifier, tooling, and lifecycle work. The cryptographic substitution is the small part. The harder problem is absorbing the new keys and signatures across PKI, software distribution, logging, and policy.
  • The signing seed is as sensitive as the private key. FIPS 204 requires that the key-generation seed be protected with the same safeguards as a private key, because the seed can regenerate the key.
  • No floating-point arithmetic. The standard explicitly forbids floating-point in ML-DSA implementations, because rounding errors can produce incorrect results. It’s a compliance requirement, not a suggestion.
  • Rejection sampling is a side-channel surface. ML-DSA’s signing loop computes a candidate signature, checks it against acceptance bounds, and retries if it fails. If the accept and reject paths differ in timing or power draw, that leaks secret information, so the rejection step has to be genuinely constant-time. This is harder to get right than constant-time signing of a scheme without rejection sampling.
  • Side channels live in hardware too. Constant-time software is necessary but not sufficient. The silicon that runs ML-DSA (HSMs, signing accelerators, secure elements) can leak through power and electromagnetic traces even when the calling software is clean. Masking, splitting each secret into random shares, is the countermeasure, and it’s worth asking a hardware vendor whether their side-channel resistance was verified on the platform you’ll actually deploy.
  • Fault attacks want a verify-before-release check. A well-known defense against fault-injection on signatures is to verify the signature locally against the public key before releasing it, since a faulted-but-still-valid signature is vanishingly unlikely.

The recurring theme matches ML-KEM’s: switching to ML-DSA is rarely a compile-time change. In real systems it’s a certificate, verifier, and lifecycle project.

Common misconceptions

  • “ML-DSA is the answer to everything post-quantum.” It’s the general-purpose signature default, not a universal answer. Key establishment is ML-KEM’s job, and specialized roles like firmware roots of trust may be better served by SLH-DSA or stateful hash-based signatures like LMS and XMSS.
  • “Finalized standard means fully mature ecosystem.” FIPS 204 is final, but verifier support, CA tooling, and HSM workflows are still catching up. Present in a library isn’t the same as enabled and tested end to end in production.
  • “Dilithium and ML-DSA are different algorithms.” ML-DSA is the standardized successor to the competition scheme CRYSTALS-Dilithium. The canonical, citable name is ML-DSA (FIPS 204); Dilithium is the research-era name.
  • “It’s a drop-in for ECDSA.” Same role, very different dimensions. The larger keys and signatures ripple into certificates, parsers, and trust stores, so it’s a planned migration, not a swap.

Everything here is the map, given freely. When your team needs ML-DSA sized and sequenced into your own signing infrastructure, that’s what an alignment briefing is for.

Last verified 2026-07-12 · Maintained by Addie LaMarr, LaMarr Labs.