NIST finished the first post-quantum standards in August 2024. FIPS 203 covers ML-KEM for key establishment, FIPS 204 covers ML-DSA for signatures, and FIPS 205 covers SLH-DSA as a hash-based alternative. The algorithms are settled. The swap isn’t. An ML-KEM-768 encapsulation key is 1,184 bytes, and the X25519 public key it stands in for is 32 bytes. Most of what goes wrong in a migration comes out of that ratio.
Engineers arrive at our post-quantum training expecting a configuration change. Pick the new group, restart the service, close the ticket. Nothing in the mathematics argues against that. The plumbing does. Networks, certificate stores, hardware security modules and bootloaders were all sized when a public key was a few dozen bytes, and post-quantum objects are measured in thousands. This article walks through where the difference shows up, what the industry has already solved, and what to test before anyone touches production.
The Shape of the New Primitives
A key encapsulation mechanism, or KEM, is the post-quantum form of key establishment. One side publishes a public key, the other returns a ciphertext, and both sides derive the same shared secret from it. ML-KEM does the job that Diffie-Hellman does today, and it doesn’t look like Diffie-Hellman on the wire. There is no fixed-width group element, and the ciphertext travels in the opposite direction from what an ECDH exchange trains you to expect.
Almost every live deployment is hybrid. A hybrid key exchange runs a classical algorithm and a post-quantum one side by side and mixes both shared secrets into the session key, so the connection survives if either component turns out to be broken. The combination now shipping in browsers is X25519MLKEM768. It also means the handshake carries both key shares, and both sizes add up.
| Primitive | Public key | Ciphertext or signature |
|---|---|---|
| X25519 | 32 B | 32 B |
| ML-KEM-768 | 1,184 B | 1,088 B |
| ECDSA P-256 | 64 B | ~71 B (DER) |
| ML-DSA-44 | 1,312 B | 2,420 B |
| ML-DSA-65 | 1,952 B | 3,309 B |
| SLH-DSA-SHA2-128s | 32 B | 7,856 B |
Two things fall out of that table. Key establishment grew by a factor of about 37. Signatures grew by a factor of about 34 to 110 depending on the scheme, and a single TLS handshake carries several of them.
The Wire
Handshakes That No Longer Fit in One Packet
A ClientHello carrying an X25519MLKEM768 key share often exceeds QUIC’s 1,200-byte Initial datagram, and on a 1,500-byte path it can require more than one TCP segment depending on the rest of the ClientHello and its options. Splitting the first message across two segments is perfectly legal, and a great deal of network equipment has never seen it happen. Middleboxes – firewalls, inspection proxies, load balancers, anything on the path that reads the handshake in flight – often parse only the first packet, and a device that doesn’t reassemble will drop the connection rather than report anything.
QUIC makes the constraint explicit. A client Initial packet must be padded to at least 1,200 bytes, and the server may not send more than three times what it has received until it has validated the client’s address. A larger client hello splits into two Initial packets, and a load balancer that routes on connection ID may not expect two of them from a client it has not yet seen. The second packet gets dropped and the connection stalls with no error anywhere.
The Congestion Window
A TCP server starts with an initial congestion window of 10 segments, roughly 14 KB, and it must wait for an acknowledgement before sending more. A classical TLS 1.3 server flight of certificate chain, signature and Finished sits comfortably under that. Add post-quantum signatures to every object in the chain and the flight can exceed it, so the server stops mid-handshake and waits a full round trip. Cloudflare measured this directly by padding handshakes with dummy data and published the results in Sizing up post-quantum signatures. About 9 KB of extra data slowed handshakes by roughly 15 percent, and past about 10 KB the cost rose sharply as the extra round trip appeared. On a link with 100 ms of round-trip time, that penalty lands on every new connection.
Ossification, and Why It Is Not New
The word for this is ossification. The network has learned the shape of the traffic it carries, and it rejects traffic with a different shape.
TLS 1.3 hit the same wall first, and the story is worth knowing since it tells you how these problems get solved. Early drafts were a clean redesign of the handshake. Deployment tests found a meaningful share of connections failing outright, not on servers but on middleboxes written against TLS 1.2 and nothing else. The working group’s answer was compatibility mode. The finished TLS 1.3 handshake disguises itself as a TLS 1.2 session resumption, complete with a session ID that means nothing and a change_cipher_spec message that does nothing at all. That scar tissue is permanent, and it was the price of getting a new handshake across a network that had memorised the old one.
Post-quantum key exchange has now made the same crossing, and it made it largely successfully. Post-quantum authentication has not started.
The Certificate Chain
Key establishment shipped first, and the reason is worth stating plainly. Confidentiality is the part exposed to harvest now, decrypt later, where an adversary records encrypted traffic today and decrypts it once a cryptographically relevant quantum computer exists. Authentication has no equivalent exposure, since a signature forged in 2040 cannot retroactively compromise a session from 2026. A key exchange also involves only two endpoints, so a browser and a server can agree to upgrade between themselves. A signature involves the entire public key infrastructure.
Count the signature-bearing objects in an ordinary web handshake: the server’s handshake signature, the leaf certificate’s signature, the intermediate certificate’s signature, two signed certificate timestamps proving the certificate was published to a public log, and a stapled revocation response. Six. Replace each one with ML-DSA-44 at 2,420 bytes, add the two ML-DSA public keys at 1,312 bytes each, and the handshake grows by roughly 17 KB. That clears both the 1,200-byte QUIC Initial datagram and the ~14 KB TCP congestion window at once.
The IETF is working on this from several directions, including suppressing intermediate certificates the client already holds, negotiating trust anchors so the server sends only what a given client needs, and compressing the chain. None of it is settled, and none of it is deployable this quarter. Our advice to engineering teams is to stop treating post-quantum TLS authentication as this year’s project and put the effort where it pays now.
- Key establishment in TLS. Enable hybrid key exchange. It is deployable today, browsers ship it by default, and it addresses the harvest-now exposure that actually has a clock on it.
- Code and firmware signing. Here the long-lived risk is genuine, since a device signed today may still be validating that signature in 2040. SLH-DSA is available now, and the stateful hash-based schemes in NIST SP 800-208 have been standardised for years.
- Everything else. Inventory it, size it, and wait for the standards to finish.
Where the Cryptography Actually Lives
Libraries
OpenSSL added native ML-KEM, ML-DSA and SLH-DSA in its 3.5 release, and AWS-LC, BoringSSL and Go’s TLS stack carry their own support. The version running in your production images is probably older than the version you need. Language bindings lag further behind again, so an application that calls into a platform crypto provider may find the algorithm registered and the key length rejected two layers up in code nobody has touched in six years.
Hardware
Hardware security modules and smart cards store keys in objects sized when a private key was a 32-byte scalar. An ML-DSA-65 private key is 4,032 bytes. Some modules handle that with a firmware update, some need replacing, and the answer varies by model rather than by vendor. Ask for the specific model and firmware version in writing before you plan a certificate authority migration around it.
Constrained devices are stricter still. A bootloader that verifies a firmware signature needs somewhere to put the signature. SLH-DSA verification is computationally cheap, and an SLH-DSA-SHA2-128s signature is 7,856 bytes. A bootloader with a 4 KB scratch buffer will not verify one, and enlarging that buffer means changing the bootloader, which on a shipped device often means it cannot be changed at all. This single number decides device architecture, and teams usually find it late.
Side Channels
Dropping in a reference implementation is not the same as dropping in a hardened one. In December 2023 a family of timing vulnerabilities named KyberSlash was found in several ML-KEM implementations, caused by division operations whose execution time depended on secret data. Reference code was patched quickly, and the general lesson stands. These algorithms are new, their implementations are young, and the attack literature is active.
Masked implementations that resist power analysis exist, and they run several times slower than unmasked ones. For a server behind a locked rack door that cost usually buys nothing. For a smart card in an attacker’s hand it is the entire point. Decide which one you are building before you pick a library.
A Test Plan That Finds Real Failures
None of the above is a reason to wait. It is a reason to test in an order that surfaces problems while they are still cheap.
- Inventory before you test. A cryptographic bill of materials, or CBOM, lists every algorithm, key, certificate and library in use along with the systems that depend on them. You can’t test what you haven’t found, and the components that break first are usually the ones nobody remembered owning. The migration methodology at pqcframework.org covers how to build one.
- Enable it in staging with the clients you actually have. A curl test proves the server works. It proves nothing about the branch office running a decade-old inspection appliance, the mobile fleet, or the partner integration that pins a certificate. Test from the network positions your users occupy.
- Load test, and read the tail. Median handshake time will look fine. Watch the 99th percentile, and watch it per client platform. A 2 percent average cost hides a 40 percent cost on one device class.
- Look for silence, not errors. Middlebox failures show up as timeouts and missing requests rather than log lines. Compare inbound request counts with the feature on and off. A gap of a fraction of a percent is a broken population somewhere.
- Roll out by share of traffic, with a rollback you have rehearsed. Small percentage first, metrics for both latency and error rate, then increase. The rollback matters more than the rollout, since the failures you’re hunting are the ones nobody predicted.
- Re-test after every network change. A firmware update on a load balancer can quietly reintroduce a size limit you cleared six months ago.
What This Adds Up To
Post-quantum migration is a plumbing exercise wearing a mathematics costume. The primitives are standardised and the implementations are usable. What remains is the accumulated set of assumptions in networks, hardware and code about how large a cryptographic object is allowed to be, and those assumptions are undocumented, distributed, and only discoverable by testing.
Teams that get through this cleanly are the ones who found their thresholds in a lab in 2026 rather than in an incident review later. Drop in the algorithm, then tune the infrastructure underneath it, and expect the second part to take longer than the first.
We built our post-quantum cryptography training around this gap between the published standard and the working deployment, including the handshake arithmetic, the certificate chain problem, the hardware constraints and the test sequence above. Programs, formats and access options are at quantumacademy.com/. For deeper technical background on individual topics, PostQuantum.com covers the underlying research in more detail.