FIPS 203 (ML-KEM)
FIPS 203 is the NIST standard that specifies ML-KEM, the primary post-quantum algorithm for key establishment, and the direct replacement for the classical key exchange (ECDH, DH, and some RSA key transport) that a quantum computer breaks. Finalized in August 2024 as one of the first three NIST post-quantum standards, it’s the answer to the question almost every migration starts with: what replaces the way two systems agree on a shared secret? ML-KEM is the standardized form of the algorithm known during the NIST competition as CRYSTALS-Kyber.
The short version:
- ML-KEM does key establishment, agreeing on a shared secret over an open network. It is not a signature algorithm. (Signatures are ML-DSA and its siblings.)
- It’s a key encapsulation mechanism built on lattice math (Module-LWE), the most deployment-ready post-quantum family.
- It’s the default answer to “what replaces ECDH,” and it’s the direct fix for the confidentiality half of the quantum threat, HNDL.
- The real cost isn’t speed, it’s size. Its keys and ciphertexts are much larger than elliptic-curve ones, so the integration work is about bandwidth, protocol handling, and rollout, not CPU.
- NIST’s recommended default is ML-KEM-768.
Think of the classical approach (Diffie-Hellman) as two people mixing paint in the open to arrive at the same secret color, which works until someone has the math to un-mix it. A KEM works differently: you publish a special lockbox design (your public key), anyone can drop a freshly generated secret into a box only you can open (encapsulation), and you open it to recover the same secret (decapsulation). Both ends hold the shared secret, and the quantum computer has no shortcut to what’s inside.
What problem does ML-KEM solve?
ML-KEM’s job is key establishment: letting two parties agree on a shared secret over an untrusted network, in a way meant to stay secure against a quantum-capable adversary. A KEM does it in three moves:
- Key generation. The recipient generates a public/private key pair and publishes the public (encapsulation) key.
- Encapsulation. The sender uses that public key to generate a fresh shared secret and a ciphertext, and sends the ciphertext across.
- Decapsulation. The recipient uses the private (decapsulation) key to recover the same shared secret from the ciphertext.
That shared secret then feeds ordinary symmetric cryptography, key derivation and session encryption, exactly as a classical key agreement would. What’s different is the foundation: ML-KEM rests on lattice hardness rather than the discrete logarithms or factoring that Shor’s algorithm destroys.
What cryptographic family is ML-KEM?
ML-KEM belongs to lattice-based cryptography, and its security rests on the Module Learning With Errors problem. Structured lattices give it a strong balance of speed, practicality, and manageable artifact size, which is why it’s the default today rather than a conservative backup. That same reliance on one math family is also why some architects keep a second, non-lattice KEM like HQC on their radar: not because ML-KEM is suspect, but because betting the entire key-establishment future on a single family of assumptions is a concentration they’d rather hedge. That instinct is crypto-agility, and it’s the right one.
What does ML-KEM replace?
FIPS 203 is finalized, published August 13, 2024, one of the first three NIST post-quantum standards. It’s a real federal standard, not a draft or a candidate, and in most roadmaps it’s a Phase 1 priority. It most directly takes over the role ECDH plays in protocols like TLS:
- Replaces: ECDH, DH, and legacy RSA key-transport patterns, everywhere the job is establishing a shared secret.
- Does not replace: ECDSA, RSA signatures, or code and certificate signing. Those are the signature side of the transition, handled by ML-DSA, SLH-DSA, and FN-DSA.
A common conceptual error is treating “post-quantum” as synonymous with “signatures.” ML-KEM solves confidentiality and key establishment. It does nothing for authentication on its own.
What are the ML-KEM parameter sets and sizes?
FIPS 203 defines three parameter sets at increasing security levels. The sizes are the thing to internalize, because they’re where the engineering cost lives. These figures are verbatim from the standard:
| Parameter set | NIST security category | Encapsulation (public) key | Decapsulation (private) key | Ciphertext | Shared secret |
|---|---|---|---|---|---|
| ML-KEM-512 | Category 1 | 800 bytes | 1,632 bytes | 768 bytes | 32 bytes |
| ML-KEM-768 | Category 3 | 1,184 bytes | 2,400 bytes | 1,088 bytes | 32 bytes |
| ML-KEM-1024 | Category 5 | 1,568 bytes | 3,168 bytes | 1,568 bytes | 32 bytes |
NIST recommends ML-KEM-768 as the default, on the basis that it provides a large security margin at reasonable cost, and it advises using the strongest practical parameter set when first establishing protections, to avoid costly upgrades later. For scale: an ML-KEM-768 public key is over a kilobyte, where a classical elliptic-curve public key is 32 bytes. The compute is fast; the bytes on the wire are what you plan around.
Source: NIST FIPS 203, Module-Lattice-Based Key-Encapsulation Mechanism Standard, August 2024.
What does deploying ML-KEM actually look like?
ML-KEM is fast enough to be the default and large enough that you can’t treat it as invisible. In TLS the standard path is hybrid key exchange, running classical X25519 and ML-KEM-768 together (the X25519MLKEM768 group), so the session is safe if either component holds. It enters most stacks as a swappable provider rather than application code: through the Open Quantum Safe provider on OpenSSL, or the BouncyCastle provider in Java, with no application changes. That’s crypto-agility working as intended.
The performance impact in a real deployment is modest and lands mostly on the handshake, not the workload. A 2026 banking proof-of-concept measuring hybrid ML-KEM-512 at the TLS termination layer (Apache plus a Java API gateway, 100 concurrent clients) reported roughly a 23% increase in handshake time, about 1.3% on end-to-end request latency, and zero errors across all runs. Those are point-of-reference numbers from one architecture where connection reuse dominates, not a universal benchmark, but they’re representative of the pattern: the handshake costs more, the overall request barely notices.
Source: Balaji et al., “Operationalising Post-Quantum TLS,” arXiv:2605.17955 (2026).
How does ML-KEM work internally, step by step?
You never have to touch this layer to deploy ML-KEM, and understanding it is what makes the size numbers, the implicit-rejection warning, and the Module-LWE hardness claim legible instead of mysterious. The whole scheme is built in two layers. Underneath sits a simpler public-key encryption routine that FIPS 203 calls K-PKE, which is fast but only safe against a passive eavesdropper. Wrapped around it is the Fujisaki-Okamoto (FO) transform, which upgrades that inner routine into a full KEM that stands up to an attacker who gets to submit chosen ciphertexts. Everything below traces to FIPS 203 Algorithms 13 through 21.
K-PKE key generation (Algorithm 13). A single 32-byte seed d is hashed with G (which is SHA3-512) into two seeds, rho and sigma. From rho, the routine builds a k-by-k matrix A of polynomials, one entry at a time, by running SampleNTT on rho concatenated with the row and column indices. That matrix is public and never stored whole; the seed regenerates it on demand. From sigma, it samples a short secret vector s and a short error vector e, each drawn coordinate by coordinate from a centered binomial distribution via SamplePolyCBD (the small, controlled noise that is the LWE trapdoor). It then computes the noisy system t = A ∘ s + e in the NTT domain, where the ∘ is fast pointwise multiplication rather than schoolbook convolution. The public key is (t, rho), the private key is s. This is the LWE picture made concrete: the public key is a batch of noisy linear equations, and s is the hidden solution.
K-PKE encryption (Algorithm 14). To encrypt a 32-byte message m, the sender regenerates A from the public seed rho, samples its own fresh short vectors y, e1, and a short scalar e2 from the binomial distribution, and produces two ciphertext parts: one that carries A combined with y plus noise, and one that carries t combined with y plus noise plus the message bits scaled up to the top of the modulus. The recipient’s short secret s cancels almost all of that noise on decryption, leaving the message recoverable as long as the accumulated error stays under a threshold (which is why lattice KEMs carry a tiny, quantified decryption-failure probability).
The FO wrapper: encapsulation (Algorithms 17, 20). ML-KEM does not let the sender choose the message. Encapsulation generates a random 32-byte value m, then derives both the shared secret and the encryption randomness together as (K, r) = G(m ‖ H(ek)), where H is SHA3-256 and ek is the recipient’s encapsulation key. It encrypts m under K-PKE using that derived r, and ships the ciphertext. Binding the randomness r to m by hashing is the pivotal move: it means a valid ciphertext can only have been produced honestly, which is what closes the door on chosen-ciphertext manipulation.
The FO wrapper: decapsulation with implicit rejection (Algorithm 18). This is the part the gotchas section warns about. The recipient decrypts to recover a candidate m', re-derives (K', r') = G(m' ‖ h), and then re-encrypts m' with r' to get a ciphertext c'. If c' exactly matches the received ciphertext c, the ciphertext was honest and K' is the shared secret. If it does not match, the routine does not return an error. It returns a pseudorandom K-bar = J(z ‖ c), where J is SHAKE256 and z is a secret 32-byte value baked into the decapsulation key at generation time. This is implicit rejection: a bad ciphertext yields a deterministic-but-useless key rather than a distinguishable failure, so an attacker learns nothing from probing. FIPS 203 requires that the internal flag comparing c and c' be destroyed before the routine returns and never be exposed in any form, which is exactly why “correct decapsulation matters for security” is not a style preference.
Source: NIST FIPS 203, Algorithms 13, 14, 17, 18, 20, and 21, and §3.3 (implicit-rejection flag destruction), August 2024. Matrix A from SampleNTT over SHAKE128, s and e from SamplePolyCBD; G = SHA3-512, H = SHA3-256, J = SHAKE256.
What are the common implementation gotchas?
ML-KEM is easy to mishandle if you assume it behaves like classical key agreement. The ones worth knowing:
- A KEM isn’t “post-quantum ECDH.” The object flow is different, generate, encapsulate, decapsulate, with different artifacts to handle. Porting a mental model straight from Diffie-Hellman causes bugs.
- Correct decapsulation matters for security. ML-KEM’s resistance to chosen-ciphertext attacks depends on careful error handling and key-derivation logic around decapsulation. The standard even requires the internal implicit-rejection flag to be destroyed and never returned.
- Hybrid composition has to be done right. Combining the classical and post-quantum shared secrets incorrectly can undercut the whole point of running them together.
- Side channels live in software and hardware. Constant-time software is necessary but not sufficient. The silicon that runs ML-KEM (HSMs, accelerators, secure elements) can leak secret information through power and electromagnetic traces even when the calling software is constant-time. 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, rather than on a reference chip.
- On constrained devices, size is the constraint, not speed. On an ESP32, ML-KEM-512 was actually the fastest key exchange available, faster than elliptic-curve, but its key shares exceed the datagram size limit and it needed more heap than the default build allocated. The work was transport fragmentation and memory tuning, not cryptographic performance. See Constrained-Device PQC.
The recurring theme: switching to ML-KEM is rarely a compile-time change. In real systems it’s a protocol, testing, and lifecycle project.
Everything here is the map, given freely. When your team needs ML-KEM sized and sequenced into your own protocols and estate, that’s what an alignment briefing is for.
Last verified 2026-07-12 · Maintained by Addie LaMarr, LaMarr Labs.