X25519 + ML-KEM-768, in handshake
Two key exchanges, run in parallel, mixed into one shared key. Classical X25519 protects you against everything that's not a quantum computer; ML-KEM-768 protects you against quantum computers but hasn't been deployed long enough to be fully trusted on its own. So we run both. Walk through the six-message handshake, see what's on the wire, and watch HKDF combine the two secrets into one.
why hybrid?
defense-in-depthRecorded today, decrypted later
A passive eavesdropper can record encrypted traffic now and store it. If a sufficiently large quantum computer arrives in 2035, the recording can be decrypted retroactively — every X25519 handshake ever performed is a vulnerable past secret.
For data that needs to stay confidential for more than a few years — health records, classified material, financial fraud history — this is a present-day attack, not a future one. The mitigation has to be deployed now, even though the quantum computer doesn't exist yet.
New algorithms haven't been attacked enough
Lattice cryptography is the leading candidate to resist quantum attacks, but it was standardized in 2024 — only a handful of years of public attack research. AES has had 25 years; RSA has had 45. A subtle flaw in ML-KEM that's discovered in 2030 would compromise everyone who deployed it standalone in 2026.
Meanwhile, the parameter sizes are tuned aggressively: ML-KEM-512 and -768 have failed several side-channel attacks in implementations. The math holds up; specific code paths haven't.
Hybrid key exchange is the answer to both risks at once. Run X25519 and ML-KEM-768 simultaneously, derive a single shared key from both via HKDF, and require both to be broken for the session to leak. An attacker needs a flaw in and a quantum computer.
The cost is small: a slightly larger ClientHello (~1.2 KB extra), a few hundred microseconds of additional CPU per handshake, and a small bandwidth bump. Negligible compared to the asymmetry of the threat.
The internet has been quietly converging on this since 2023. Cloudflare offered hybrid first; Chrome shipped it; AWS, Google, and most major CDNs followed. As of 2026, the X25519MLKEM768 codepoint is the most common post-quantum-touched key exchange on the public web.
the two halves
X25519 — ECDH on Curve25519
A specific elliptic curve (Bernstein, 2006) chosen for speed and side-channel safety. Both parties scalar-multiply a shared generator with their private exponent; the resulting points have identical x-coordinates after a final reciprocal exchange.
ML-KEM-768 — module-LWE KEM
NIST FIPS 203, formerly Kyber. The client publishes a public key derived from a noisy lattice point; the server encapsulates a random 32-byte secret into a ciphertext using that public key; the client decapsulates it with their secret matching key.
These two halves do the same job — produce a 32-byte shared secret between two parties — but through completely different math. The hybrid trick: run them in parallel, then mix the two 32-byte secrets through HKDF-SHA-256 to produce a single 32-byte key for the session.
the handshake, step by step
interactive · toy parameters
Below is the X25519MLKEM768 handshake walked through with toy
parameters small enough to follow on paper. The classical half
uses our toy curve y² = x³ + 2x + 2 (mod 17), generator
G = (5, 1). The post-quantum half uses a 4-dimensional
LWE problem mod 17 — the same Regev scheme as the ML-KEM-DSA app.
The structure is identical to the real protocol; only the bytes
are smaller.
The handshake before it starts
Both sides have the same public parameters: the elliptic curve equation, the generator G, the LWE modulus and dimension. They haven't exchanged anything yet.
Press Next to step through the six messages of the handshake. Each step shows what one side has computed and what gets added to the wire. The wire panel always shows what an eavesdropper could observe.
HKDF — the combiner
SHA-256Both halves of the handshake produce a 32-byte shared secret. To get a single key for AES-GCM, we mix them through HKDF-SHA-256 (RFC 5869) — the standard key-derivation function used everywhere in TLS 1.3.
HKDF has two steps: extract (HMAC the input keying material under a salt to get a uniformly-distributed pseudorandom key) and expand (use that PRK to produce as many bytes of output as you need, with a context label).
The result is computed below using your browser's real Web Crypto implementation — the same SHA-256 + HMAC code that runs your TLS handshakes. The toy hybrid handshake above feeds its outputs in; you can also try your own inputs.
Why not just use the secrets as keys directly?
A shared secret out of ECDH or ML-KEM is uniformly random bytes
— but only "uniform" in a specific cryptographic sense. The output
of x·y·G on a curve isn't pure randomness; it's a curve
point with structure. The output of ML-KEM has a specific
distribution. Using these directly as AES keys would be fine
in most cases but not always — and certainly not when you have
two different shared secrets from different schemes
that you need to combine.
HKDF normalizes everything. It takes the concatenation
ECDH_shared || KEM_shared, hashes it through HMAC,
and produces a uniformly-random 32-byte key with proper randomness
properties — even if one of the inputs turns out to have hidden
structure. The salt and info parameters bind the key to the protocol
context, preventing cross-protocol reuse.
For TLS 1.3 specifically, the key schedule in RFC 8446 §7.1 already uses HKDF at every transition. Hybrid PQ KEX simply substitutes the concatenated secret in place of the classical-only secret at the first step.
wire format and deployment
The X25519MLKEM768 codepoint (0x11ec) is a single
TLS 1.3 NamedGroup that the client offers in supported_groups
and supplies a key share for in key_share. The wire
format concatenates the post-quantum key first, then the classical
public key — a deliberate ordering chosen so that PQ migration is
easy to track in packet captures.
| field | contents | size |
|---|---|---|
| NamedGroup | 0x11ec — X25519MLKEM768 | 2 B |
| key_exchange.length | 1216 | 2 B |
| ML-KEM-768 public key | 1184 bytes of polynomial-encoded lattice data | 1184 B |
| X25519 public key | 32 bytes — compressed Montgomery x-coordinate | 32 B |
| total | — | 1220 B |
| field | contents | size |
|---|---|---|
| NamedGroup | 0x11ec — X25519MLKEM768 | 2 B |
| key_exchange.length | 1120 | 2 B |
| ML-KEM-768 ciphertext | 1088 bytes — the encapsulation | 1088 B |
| X25519 public key | 32 bytes — server's ephemeral public point | 32 B |
| total | — | 1124 B |
Compared to plain X25519 (each side's key_share is 32 bytes), hybrid
adds about 2.3 KB per handshake. On a slow connection
that's an extra round-trip's worth of bytes, but TLS 1.3 sends
ClientHello and ServerHello in the first packet anyway. In
practice, the extra latency is unmeasurable for most users.
X25519Kyber768Draft00 codepoint experimental support.X25519Kyber768Draft00 by default for compatible servers. Cloudflare reports ~3% of TLS handshakes go post-quantum by end of year.X25519MLKEM768 (0x11ec) standardized in draft-kwiatkowski-tls-ecdhe-mlkem. Migration from draft codepoint underway.sntrup761x25519 default; ML-KEM hybrid follows. Signal Protocol moves to PQXDH (X25519 + ML-KEM-1024). Chrome, Firefox, Safari all ship X25519MLKEM768.Two camps, two threat models
General-purpose TLS — public web, e-commerce, messaging — uses hybrid because the cost of an undiscovered ML-KEM flaw is catastrophic at scale. Adding 1.2 KB to a handshake to keep X25519 as a safety net is an obvious trade.
U.S. national security systems under CNSA 2.0 are moving to pure ML-KEM-1024 with no classical fallback. The threat model assumes a quantum-capable adversary by 2033; keeping a classical algorithm in the chain just means there's an algorithm still vulnerable to that adversary in your system. Cleaner to drop it.
Both positions are coherent. The choice is about which of two failure modes you're more worried about — undiscovered PQ flaws (favor hybrid) or maintaining a known-broken algorithm in the protocol (favor pure PQ). Most of the internet falls in the first camp; the U.S. government falls in the second.