Why hybrid post-quantum, not pure ML-KEM

It's a fair question the first time you turn on post-quantum key exchange: if ML-KEM is the quantum-resistant algorithm, why does everyone deploy X25519MLKEM768 — dragging the old, quantum-breakable X25519 along — instead of pure ML-KEM? The answer is a precise risk trade, and you can see exactly what each half buys you in how the two secrets combine on the wire.

What hybrid is, on the wire

X25519MLKEM768 runs both key exchanges inside one handshake. The client sends a single key_share that is two public keys concatenated; the server replies with two; each side computes two shared secrets and concatenates them into one.

# X25519MLKEM768 client key_share (codepoint 0x11ec) — two keys, concatenated
  ML-KEM-768 encapsulation key   1184 bytes
  X25519 public key                32 bytes
                                 ----------
  total                          1216 bytes   # this is the ClientHello's ~1.2 KB

# the secret fed into the TLS 1.3 key schedule = both, concatenated:
  shared_secret = ML-KEM-768 secret (32)  ||  X25519 secret (32)

(A byte-level quirk worth knowing: for the X25519 variant the ML-KEM component comes first in both the share and the secret; the NIST P-curve variants put the ECDHE component first. Get the order wrong and the key schedule silently diverges.) The concatenated secret goes straight into HKDF as the (EC)DHE input — see the full byte-by-byte walk.

Why combine instead of choose

That concatenate-then-KDF construction is secure as long as the KDF is a strong PRF and at least one of the two input secrets is unbroken. To recover the session key, an attacker has to break both X25519 and ML-KEM. That buys two independent failure domains:

• If ML-KEM has an undiscovered weakness — mathematical (lattice cryptanalysis is far younger than the decades of attack ECC has survived), or, more likely in the near term, an implementation bug in brand-new code — X25519 still protects you against today's classical attackers.

• If a cryptographically relevant quantum computer arrives and breaks X25519, ML-KEM still protects you.

You only lose if both fall at once.

Be precise about what each half buys

Here is the part that's easy to get wrong: X25519 provides zero post-quantum protection. Against harvest-now-decrypt-later, an attacker who records the handshake today and owns a future quantum computer breaks the X25519 half with Shor's algorithm. So the quantum resistance of the connection rests entirely on ML-KEM.

X25519's job is the opposite insurance: that adopting a young algorithm doesn't leave you worse than you are today. If ML-KEM turns out to be flawed before the quantum threat materializes, you haven't regressed — you still have X25519's classical security. So hybrid is not "double the quantum security." It is "full quantum security from ML-KEM, plus a guarantee that betting early didn't downgrade your classical security." That asymmetry is the entire point.

Why not pure ML-KEM yet

Maturity, mostly. ML-KEM was standardized in 2024 (FIPS 203); shipping implementations are new. The conservative move during the first deployment wave is to not stake a connection's whole confidentiality on math and code that haven't had ECC's decades of scrutiny. And the cost of the hedge is small: one extra 32-byte X25519 exchange on top of a ~1.2 KB ML-KEM share — the insurance is nearly free relative to what you're already paying for the KEM.

This is why the deployed codepoints — in current browsers, the major CDNs, and OpenSSL 3.5+ — are hybrid, not pure. Pure ML-KEM exists and may well become the default once the algorithm has aged. The exception today is a strict CNSA 2.0 / pure-PQC posture that explicitly mandates it — a specific compliance requirement, not a security improvement over hybrid.

Choosing the right group, and proving every connection actually negotiated it, is the kind of wire-level detail that decides whether a migration is real or just configured. It is one step of the broader migration, and where we work.

← All posts