In Part 2 we put two contenders in the ring: classical Diffie-Hellman / X25519 (tiny, fast, quantum-doomed) and post-quantum ML-KEM-768 (quantum-safe, chunky, new). Now it’s time for the main event. Let’s put them side by side from every angle that matters, and then reveal why the smartest move isn’t to crown a winner at all.
Everything here you’ll reproduce yourself in the hands-on lab in Part 4. These aren’t numbers I’m asking you to trust; they’re numbers you’ll measure.
Round 1: Size on the wire
This is where the difference jumps right out:
| X25519 | ML-KEM-512 | ML-KEM-768 | ML-KEM-1024 | |
|---|---|---|---|---|
| Public key | 32 B | 800 B | 1184 B | 1568 B |
| Response (ciphertext) | 32 B | 768 B | 1088 B | 1568 B |
| Shared secret | 32 B | 32 B | 32 B | 32 B |
| Fits in one IKE message (≤1280 B)? | ✅ yes | ✅ yes | ❌ needs fragmentation | ❌ no |
X25519’s 32-byte keys are adorably tiny. ML-KEM’s are 25–50× larger, big enough that ML-KEM-768 forces IKE fragmentation (splitting one logical message across multiple packets). Tuck that word away: fragmentation is the thread that runs through this entire pillar, and you’ll see it with your own eyes in the packet captures next post.
Round 2: Latency (round trips)
| Mode | Round trips | Messages |
|---|---|---|
| X25519 only | 2 | IKE_SA_INIT → IKE_AUTH |
| Hybrid X25519 + ML-KEM | 3 | IKE_SA_INIT → IKE_INTERMEDIATE → IKE_AUTH |
Going hybrid adds one full round trip, measurable but small in practice (typically a few milliseconds on a LAN). Since a handshake happens once per tunnel (with rekeying every few hours), this is nothing to lose sleep over.
Round 3: Compute cost (the surprise)
A common myth: “post-quantum” means “painfully slow.” For ML-KEM, the opposite is closer to the truth. Its lattice operations are genuinely fast, in the same ballpark as, and often faster than, an elliptic-curve scalar multiplication.
Rough per-operation cost on modern x86 (from published eBACS/SUPERCOP benchmarks, not measured in our lab):
| Operation | X25519 | ML-KEM-768 |
|---|---|---|
| Key generation | ~50–65k cycles | ~30k cycles |
| Derive shared secret / encapsulate | ~50–65k cycles | ~45k cycles |
| Decapsulate | n/a | ~35k cycles |
Add it up and the totals land in the same range. ML-KEM-768 is not the bottleneck, not even close. When we time the real handshakes in Part 4, you’ll see the hybrid version costs about 1 ms more than classical, and essentially all of that is the extra network round trip, not the crypto.
Round 4: Security
| X25519 | ML-KEM-768 | |
|---|---|---|
| Classical security | ~128-bit | ~192-bit |
| Quantum security | ❌ broken by Shor’s algorithm | ✅ no known quantum attack |
| Standardised | RFC 7748 (2016) | FIPS 203 (2024) |
| Deployment maturity | Very high | Emerging |
And there’s the rub. X25519 is battle-tested but quantum-vulnerable. ML-KEM is quantum-safe but new and less field-tested. Each has exactly the weakness the other doesn’t.
The verdict: why not both?
Here’s the punchline I hinted in Part 2. Neither contender clearly wins today, so instead of picking a champion, we make them work together. A hybrid key exchange runs both and combines their shared secrets into the final session key. The result:
- If ML-KEM is broken by a future quantum attack, X25519 still provides classical security.
- If X25519 is broken by a quantum computer, ML-KEM provides quantum resistance.
- An attacker must break both simultaneously, which is believed to be infeasible.
You get quantum safety without betting everything on a brand-new algorithm, all for the price of one extra round trip and ~2 KB per handshake.
The magic that makes it work: RFC 9370
So how do we actually wire two key exchanges into one IKEv2 handshake? Enter RFC 9370 (Multiple Key Exchanges in IKEv2, 2023). It defines a clean mechanism to run additional key exchanges on top of the standard IKEv2 DH exchange, each contributing keying material to the final keys.
The scheme is elegant:
- X25519 stays the primary exchange, carried in the standard
IKE_SA_INITmessage: small and unchanged. - ML-KEM joins as an additional exchange, riding in a brand-new
IKE_INTERMEDIATEround trip. - The final session key is derived from both shared secrets combined.
And it’s backward compatible: peers that don’t speak additional key exchanges simply fall back to the base DH. Everybody’s happy. This is the practical migration path NIST and most VPN vendors recommend: bolt PQC on without redesigning the whole protocol.
In strongSwan config, the whole story is spelled out in one proposal string: x25519-ke1_mlkem768
x25519 is the main DH group in IKE_SA_INIT; ke1_mlkem768 is the first RFC 9370 additional key exchange, riding in IKE_INTERMEDIATE. Remember that string.
The handshake, step by step
Here’s the whole hybrid dance, which we’re about to watch live:
Initiator Responder
| |
|--- IKE_SA_INIT (KE[x25519], Ni) -------------> |
|<-- IKE_SA_INIT (KE[x25519], Nr) -------------- |
| |
| X25519 shared secret derived |
| |
|--- IKE_INTERMEDIATE (mlkem768 pub key) ------> | (~1250 B, fragmented)
|<-- IKE_INTERMEDIATE (mlkem768 ciphertext) ---- | (~1155 B)
| |
| ML-KEM shared secret combined with |
| X25519 secret → final IKE SA keys |
| |
| IKE SA ESTABLISHED |
See that imbalance from Part 2? The initiator sends the big ML-KEM public key (~1184 B) and gets back the ciphertext (~1088 B): different sizes, opposite directions, exactly because a KEM splits the work. And that ~1250 B public-key message is precisely why fragmentation = yes is mandatory in the lab.
Enough theory: let’s run it
We’ve now got the full picture: why key exchange is the urgent pillar, who the contenders are, how they compare, and why hybrid is the answer. Time to stop reading tables and start making them.
In Part 4 we bring up a real hybrid tunnel, capture the packets, and run classical-vs-hybrid back to back, watching the extra round trip and the fragmentation appear in full detail. Meet me there!