Part 3 of 5 in TLS in 2026. So far we’ve covered the changing cadence of certificates — 47-day lifetimes and the ACME + ARI automation that keeps up with them. This week the subject moves inside the handshake: the cryptography itself.
If you run anything behind a modern CDN or a recent TLS stack, there’s a strong chance you’re already serving post-quantum TLS — and never decided to. By March 2025, roughly 38% of human HTTPS traffic to Cloudflare was using hybrid post-quantum key exchange. Chrome turned it on by default in version 124, back in April 2024. The post-quantum migration didn’t arrive as a project with a kickoff meeting. For the key-exchange half of TLS, it arrived as a software update, and it’s already most of the way deployed.
That’s the good news and the trap in one sentence. The key-exchange migration is nearly a solved problem you should finish deliberately. The signature migration — the certificates themselves — is barely started and genuinely hard. Conflating the two is how teams either panic about nothing or get blindsided by the part that actually matters.
Why this is urgent before quantum computers exist
The instinct is to file “post-quantum” under “deal with it when quantum computers are real.” For authentication, that instinct is roughly fine. For confidentiality, it’s wrong, and the reason is a threat with an ugly name.
This is the asymmetry that should shape your priorities. Key exchange protects confidentiality, and confidentiality is retroactive — break it in 2032 and you unlock everything harvested in 2026. So key exchange has to migrate now. Signatures protect authentication, and authentication is not retroactive — nobody can forge a 2026 handshake in 2032; by then your 2026 certificate expired six years and ~50 renewals ago. That’s why it’s defensible to move key exchange aggressively and certificates more deliberately. Same threat, opposite urgency.
How much runway is there, really?
Nobody can tell you the year a cryptographically relevant quantum computer arrives — estimates range from “a decade out” to “never,” and honest cryptographers will admit the error bars are enormous. But you don’t get to wait for certainty, for two reasons. First, harvest-now-decrypt-later means the relevant deadline isn’t when the machine exists; it’s your data’s secrecy lifetime subtracted from that date. If something you transmit today must stay private for fifteen years, you needed quantum-safe confidentiality fifteen years before the machine, not on the day it boots. Second, the decision is increasingly being made for you: compliance regimes are putting hard dates on the calendar. The US government’s CNSA 2.0 suite sets out a staged transition to post-quantum algorithms for national security systems through the early 2030s, and NIST has signaled timelines for deprecating classical algorithms over the same window. If you sell to anyone in those supply chains, their dates become yours. “When quantum computers are real” is the wrong question. “When does my data, or my biggest customer, require this” is the one with an actual answer.
What actually got standardized
In 2024, NIST finalized the first post-quantum standards, and the naming changed in the process — which trips people up, because the research names and the standard names differ:
- ML-KEM (FIPS 203) — the key-encapsulation mechanism, formerly Kyber. This is the key-exchange piece, and it’s the one already deployed.
- ML-DSA (FIPS 204) — the lattice-based digital signature, formerly Dilithium. This is the certificate piece.
- SLH-DSA (FIPS 205) — a hash-based signature, a conservative backup for signing.
When you see “Kyber” in an older blog post or config flag, read “ML-KEM.” The web runs on ML-KEM-768, the middle security level.
Hybrid key exchange, concretely
The deployed mechanism isn’t pure ML-KEM — it’s a hybrid, and the hybrid
design is the whole reason it was safe to ship this early. It’s called
X25519MLKEM768 (TLS codepoint 0x11ec), and it does exactly what the name
says: run the classical X25519 elliptic-curve exchange and ML-KEM-768, then
combine both shared secrets into the session key.
ClientHello
key_share: X25519 (classical, 32 bytes)
key_share: ML-KEM-768 (post-quantum, ~1 KB)
│
▼
Server does BOTH exchanges, derives two shared secrets
│
▼
session key = KDF( X25519_secret || ML-KEM_secret )
│
secure unless BOTH X25519 AND ML-KEM are broken
The point of carrying both: you inherit the weaker of the two failure modes, not the riskier of them. ML-KEM is new and lattice cryptography could hold a surprise; X25519 is battle-tested but quantum-vulnerable. Combine them and an attacker must break both to win — classical attackers still face X25519, and a future quantum attacker still faces ML-KEM. It’s a hedge, and hedges are the right move when one side of the bet is only a couple of years old.
It isn’t free, but it’s cheap:
| Classical X25519 only | Hybrid X25519MLKEM768 |
|---|---|
| ~32-byte key share | ~1 KB key share (ML-KEM is bigger) |
| Small ClientHello | +~1,088 bytes in the ClientHello |
| Baseline handshake latency | +~10–20 ms median, in practice |
| Quantum-vulnerable to harvest-now-decrypt-later | Quantum-safe key exchange |
For web traffic, ~1 KB and a few milliseconds is comfortably affordable, which is why it could ship to a third of the internet without anyone noticing. There are, however, two operational gotchas worth knowing.
The codepoint that moved
When Chrome first shipped hybrid key exchange in 2024, ML-KEM wasn’t finalized
yet, so it used a pre-standard construction over Kyber with the codepoint
0x6399 (often labeled X25519Kyber768Draft00). When NIST finalized ML-KEM, the
ecosystem moved to the standardized X25519MLKEM768 at 0x11ec. For a stretch,
both were live in the wild, and they do not interoperate: a client offering
only the draft codepoint and a server supporting only the final one fall back to
classical key exchange and silently lose post-quantum protection — no error,
nothing in a casual log, just a quietly downgraded handshake. If you enabled PQC
early, this is the thing to re-check: make sure both ends are on 0x11ec, not
stranded on the old draft. “We turned on post-quantum in 2024” is not the same as
“we’re still negotiating it in 2026.”
A practical migration path
Because key exchange is backward-compatible and incrementally deployable — a hybrid-capable client and a non-hybrid server simply fall back to classical, with no flag day — you can roll it out without drama. The work is mostly inventory and verification, not heroics:
- Find where TLS actually terminates — CDN, load balancer, reverse proxy, app server. That's what needs to support hybrid KEX, and it's often a provider toggle
- Confirm your stack supports it: OpenSSL 3.5+, recent BoringSSL, and the NGINX/HAProxy builds linked against them
- For CDN-fronted traffic, check the provider's PQC setting — for many sites this is the entire migration
- Enable X25519MLKEM768 and watch handshake-failure metrics for the fragmented-ClientHello tail
- Test the middleboxes in your own path — inspection proxies and older load balancers are the usual offenders
- Don't forget east-west traffic: service-to-service mTLS and internal load balancers harvest-now-decrypt-later just as well as the public edge
For most teams the honest version of this project is: confirm your CDN has it on, flip the toggle on your own terminators, watch the dashboards for a week, done. The effort is proportional to how much TLS you terminate yourself.
Verify what you’re actually negotiating
“We enabled it” and “we’re negotiating it” are different claims, and the gap
between them is where the codepoint problem hides. Check the real thing: a recent
openssl s_client will report the negotiated group, and you’re looking for
X25519MLKEM768 rather than a bare x25519 in the key-exchange line. Browsers
expose it too — Chrome’s security panel and connection details name the key
exchange for a given page. The signal that matters is the negotiated group on a
live connection, not a config file that claims support. A config can be right
while the handshake quietly settles on classical because the other end only spoke
the old draft, a middlebox stripped the larger key share, or the build you’re
running linked an older TLS library than you thought. Make “what did this endpoint
actually negotiate, from the outside” a thing you can answer on demand — it’s the
only way to know the toggle did what the changelog promised.
The half nobody has solved
Everything above is the easy half. Here’s the hard one, and it’s the reason this series has a fourth post.
Key exchange migrated quietly because ML-KEM’s sizes, while bigger, are tolerable. Signatures are a different story. A single ML-DSA-44 signature is about 2,420 bytes, versus roughly 64–72 bytes for the ECDSA signatures securing certificates today — call it a 30–40× blowup. Now count how many signatures ride in a single TLS handshake: the leaf certificate’s signature, the intermediate’s signature, and two or three Certificate Transparency SCTs (which are themselves signatures). Make all of those post-quantum and you’re adding many kilobytes to every single handshake — on by far the most latency-sensitive part of the connection, the part that happens before any data flows.
So this is where the two halves of the migration diverge. Turn on hybrid key exchange today — it’s safe, cheap, and most of your traffic is already there. Certificates need something cleverer than a swap, because the web’s handshake simply doesn’t have room for naive post-quantum signatures.
Next week
That “something cleverer” has a name and a working group: Merkle Tree Certificates, the leading proposal for making post-quantum authentication small enough to actually ship. How you sign thousands of certificates with one signature — and ship a tiny proof instead of a giant one — is the next post in the series.