Post-quantum TLS in 5 minutes
This page is the background you need for the rest of the docs. If you already know what X25519MLKEM768 is and why a ClientHello gets split, skip to How pqdoctor works.
Two separate problems
Section titled “Two separate problems”A TLS connection does two cryptographic jobs, and post-quantum migration touches both.
| Key exchange | Authentication | |
|---|---|---|
| What it does | Agrees a secret key for this connection | Proves the server is who it says it is |
| Classical today | X25519 or ECDHE with P-256 | RSA or ECDSA certificates and signatures |
| Post-quantum | ML-KEM (FIPS 203), usually as a hybrid with X25519 | ML-DSA (FIPS 204) certificates and signatures |
| The quantum risk | Harvest now, decrypt later: traffic recorded today can be decrypted once a large quantum computer exists | A forged signature only matters at the time of the connection, so this one can wait longer |
| Urgency | Now | Later; browsers don’t accept ML-DSA from public CAs yet |
That’s why pqdoctor’s main verdict is about key exchange, and the ML-DSA check is a separate section of the report.
Hybrid key exchange: X25519MLKEM768
Section titled “Hybrid key exchange: X25519MLKEM768”The post-quantum key exchange deployed on the web today is a hybrid: the client and server do an X25519 exchange and an ML-KEM-768 exchange together, and combine both secrets. If either one holds, the connection is safe. So a hybrid is never weaker than today’s X25519.
In TLS 1.3 it’s a named group, like X25519 or P-256:
| Group | Codepoint | Status |
|---|---|---|
X25519MLKEM768 |
0x11EC |
The standard hybrid. What browsers and Cloudflare use |
X25519Kyber768Draft00 |
0x6399 |
The pre-standard draft. Browsers have dropped it |
X25519 |
0x001D |
Classical |
secp256r1 (P-256) |
0x0017 |
Classical (NIST) |
A server is post-quantum, for pqdoctor’s purposes, when it negotiates X25519MLKEM768.
How a server picks a group
Section titled “How a server picks a group”In TLS 1.3 the client sends a list of groups it supports and one or more key shares: public keys for some of those groups, so the server can answer in one round trip.
- If the server supports a group the client sent a share for, it answers with a ServerHello for that group.
- If it prefers a group the client listed but didn’t send a share for, it answers with a HelloRetryRequest asking the client to try again with that group.
That second rule is how pqdoctor tells “supports ML-KEM” apart from “prefers ML-KEM”. It sends an X25519 share with ML-KEM listed first. A server that asks for a retry with ML-KEM prefers it (pq-preferred). One that just picks X25519 doesn’t (pq). Browsers send both shares, so the difference rarely matters for them, but it does for clients that only send X25519.
Why post-quantum hellos are big
Section titled “Why post-quantum hellos are big”An ML-KEM-768 public key is 1,184 bytes, so the X25519MLKEM768 key share is 1,216 bytes. A ClientHello carrying it is well over a thousand bytes, often more than fits in one TCP segment, so it’s split across two segments.
Most servers don’t care. But some load balancers, firewalls and TLS-inspecting appliances only look at the first segment, or can’t reassemble a ClientHello that spans two. They drop the connection or reset it. That’s protocol ossification, and it’s why pqdoctor sends a split PQ hello and a classical hello padded to the same size and split the same way. If both die, the size and split are the problem (large-hello-dropped). If only the PQ one dies, the codepoint is (pq-group-rejected).
Where Cloudflare fits
Section titled “Where Cloudflare fits”A request through Cloudflare has two TLS hops:
browser ──TLS──▶ Cloudflare edge ──TLS──▶ your origin server (1) (2)- Browser to edge is Cloudflare’s side, and it’s already post-quantum for most browser traffic.
- Edge to origin depends on your server. Cloudflare’s “Automatic key exchange” uses post-quantum to the origin when the origin supports it, so whether hop 2 is post-quantum comes down to your origin’s TLS stack and config. That’s what pqdoctor diagnoses, and what Flarebox checks for every origin behind your zones.
If you can’t upgrade the origin, Cloudflare Tunnel replaces hop 2 with a tunnel that already uses post-quantum key agreement.
Authentication: ML-DSA
Section titled “Authentication: ML-DSA”For hop 2, Cloudflare accepts ML-DSA certificates from your origin (Cloudflare blog, 2026-07-29), once the zone’s Custom Origin Trust Store holds the CA. ML-DSA-44 is the recommended size. Its public keys and signatures are much bigger than ECDSA’s: in the fix lab, adding an ML-DSA-44 certificate grew the chain from 364 to 3,919 bytes. The usual setup is dual certificates: the server keeps its ECDSA certificate for today’s clients and serves ML-DSA to clients that ask for it.
See ML-DSA readiness and ML-DSA origin certificates.
SSH has its own post-quantum key exchange methods: mlkem768x25519-sha256 (OpenSSH 9.9+, the default from 10.0) and sntrup761x25519-sha512 (OpenSSH’s default from 9.0). See SSH.
Deadlines
Section titled “Deadlines”Governments have set dates for the migration: NIST, the NSA’s CNSA 2.0, the EU, the UK NCSC and Australia’s ASD. Flarebox lists 12 dated milestones, each with its source, against your zone’s results. See Deadlines.
Further reading
Section titled “Further reading”- FIPS 203: ML-KEM
- FIPS 204: ML-DSA
- draft-ietf-tls-ecdhe-mlkem: the hybrid groups in TLS 1.3
- draft-ietf-tls-mldsa: ML-DSA in TLS 1.3
- Cloudflare: Is your domain using post-quantum encryption?