Disclosure: Some links on this site are affiliate links. If you purchase through them, we earn a small commission at no extra cost to you. Learn more

The Performance Cost of PQC: Key Sizes and Network Latency

TL;DR

Post-quantum primitives are not a drop-in size replacement for classical ones: ML-KEM-768's public key is 1,1841{,}184 bytes against X25519's 3232, and ML-DSA-65's signature is 3,3093{,}309 bytes against Ed25519's 6464 — roughly a 37×37\times and 52×52\times increase respectively. A hybrid X25519MLKEM768 key exchange alone adds about 1.1 KB per direction; a full ML-DSA-65 certificate chain adds tens of kilobytes to the server's first flight. That flight can now exceed the RFC 6928 initial TCP congestion window (IW=min(10MSS, max(2MSS, 14,600 bytes))\text{IW} = \min(10 \cdot \text{MSS},\ \max(2 \cdot \text{MSS},\ 14{,}600\text{ bytes}))), forcing a congestion-driven wait or exposing more of the handshake to loss-triggered retransmission. Over UDP-based transports (QUIC, DTLS 1.3), the same growth collides with the mandatory anti-amplification limit (Bserver3×BclientB_{\text{server}} \le 3 \times B_{\text{client}} before address validation) — a hybrid/PQC ServerHello and certificate chain routinely exceeds that budget, which effectively makes Retry-based address validation mandatory rather than an edge-case defense. None of this is fatal to PQC deployment, but it means the migration is a network-engineering problem as much as a cryptographic one.

Byte-Level Comparison

Equation
PrimitivePublic KeyPrivate KeySignature / CiphertextX25519 (ECDH)32 B32 B— (32 B shared secret)Ed25519 (sig.)32 B32 B64 BML-KEM-768 (FIPS 203)1,184 B2,400 B1,088 B (ciphertext)ML-DSA-65 (FIPS 204)1,952 B4,032 B3,309 B (signature)\begin{array}{l|r|r|r} \text{Primitive} & \text{Public Key} & \text{Private Key} & \text{Signature / Ciphertext} \\ \hline \text{X25519 (ECDH)} & 32\text{ B} & 32\text{ B} & \text{— (32 B shared secret)} \\ \text{Ed25519 (sig.)} & 32\text{ B} & 32\text{ B} & 64\text{ B} \\ \text{ML-KEM-768 (FIPS 203)} & 1{,}184\text{ B} & 2{,}400\text{ B} & 1{,}088\text{ B (ciphertext)} \\ \text{ML-DSA-65 (FIPS 204)} & 1{,}952\text{ B} & 4{,}032\text{ B} & 3{,}309\text{ B (signature)} \\ \end{array}

The ratios matter more than the absolute numbers:

Equation
pkML-KEM-768pkX25519=1,1843237×,σML-DSA-65σEd25519=3,3096451.7×\frac{|\text{pk}_{\text{ML-KEM-768}}|}{|\text{pk}_{X25519}|} = \frac{1{,}184}{32} \approx 37\times, \qquad \frac{|\sigma_{\text{ML-DSA-65}}|}{|\sigma_{\text{Ed25519}}|} = \frac{3{,}309}{64} \approx 51.7\times

A single hybrid key exchange is a modest addition: X25519's 32 bytes plus ML-KEM-768's 1,184-byte encapsulation key brings a ClientHello key_share to 1,216 bytes, and the server's response (X25519's 32 bytes plus a 1,088-byte ML-KEM ciphertext) to 1,120 bytes — each well under 1.5 KB. The larger cost sits in certificate signatures, and it compounds: a typical chain carries a leaf and an intermediate certificate, each holding a public key and an issuer signature. Under ML-DSA-65, one certificate's cryptographic payload alone (public key + signature) is roughly 1,952+3,309=5,2611{,}952 + 3{,}309 = 5{,}261 bytes, before X.509 boilerplate (names, extensions, OIDs — typically 300–500 bytes regardless of algorithm). A two-certificate chain pushes the server's Certificate message past 11 KB on cryptographic material alone.

TCP Congestion Window Pressure

RFC 6928 sets the initial TCP congestion window — how much a server can send in its first flight before waiting for an ACK — as:

Equation
IW=min(10MSS, max(2MSS, 14,600 bytes))\text{IW} = \min(10 \cdot \text{MSS},\ \max(2 \cdot \text{MSS},\ 14{,}600\text{ bytes}))

With a standard 1,460-byte MSS (1500-byte Ethernet MTU minus IP/TCP headers), this caps the first flight at roughly 14.6 KB. A classical TLS 1.3 server flight — ServerHello, EncryptedExtensions, Certificate, CertificateVerify, Finished — typically totals a few kilobytes and clears this window without incident, one reason the classical handshake reliably completes in a single round trip.

A server flight carrying a hybrid ML-KEM key share plus a full ML-DSA-65 certificate chain can reach 15–17 KB — past the default initial window on stacks that haven't tuned it upward. Two consequences follow. First, on a connection that hasn't otherwise validated a larger window, the excess bytes wait for the window to grow via normal slow-start, adding latency the classical handshake never incurred. Second, and more consistently costly: more packets in flight means a proportionally higher chance that at least one segment is lost on any given connection, and TCP's retransmission timeout for a lost segment costs at minimum a full RTT — a cost that scales with how many additional segments the larger PQC flight requires, not with the connection's underlying loss rate changing.

Fragmentation and UDP-Based Transports

TLS 1.3 over TCP doesn't fragment at the IP layer under normal conditions — TCP simply segments the payload into multiple MSS-sized packets, and the transport layer handles reassembly transparently. The sharper fragmentation risk shows up in TLS's UDP-based relatives, QUIC (RFC 9001) and DTLS 1.3 (RFC 9147), where a datagram exceeding the path MTU can be IP-fragmented, and fragmented UDP datagrams are dropped by a meaningful fraction of middleboxes and firewalls in practice — particularly over IPv6, where only the originating host fragments and path MTU discovery failures silently blackhole the connection instead of triggering a retry. QUIC mitigates this partly by requiring Initial packets to pad to at least 1,200 bytes and by coalescing multiple QUIC packets into a single UDP datagram up to the path MTU, but a hybrid/PQC handshake that no longer fits in one datagram's worth of coalesced packets must be split across several sends — each an independent point of loss exposure in a transport that, unlike TCP, does not benefit from decades of kernel-level congestion and retransmission tuning applied uniformly across the fleet.

Amplification: The Anti-Amplification Limit Under Pressure

TLS-over-TCP is structurally resistant to reflection amplification: an attacker spoofing a victim's source IP cannot complete the TCP three-way handshake, since the SYN-ACK goes to the victim, not the attacker — no TLS byte is ever sent to an unvalidated address. QUIC and DTLS 1.3, running over UDP, have no equivalent handshake gate, so both specify an explicit anti-amplification limit instead: before a client's address is validated, a server must not send more than three times what it has received from that address.

Equation
Bserver3×BclientB_{\text{server}} \le 3 \times B_{\text{client}}

QUIC's mandatory 1,200-byte minimum Initial packet size sets a starting budget of about 3,600 bytes before validation — sized with classical certificate chains in mind. A hybrid ServerHello plus an ML-DSA-65 certificate chain of 15+ KB overruns that budget by roughly 445×5\times regardless of whether the requesting client is legitimate. The server cannot simply send the oversized flight: it must either coalesce as much as the budget allows and wait for the client's response (which, by proving receipt, incrementally validates the address and unlocks more send budget) or issue a Retry token up front to force explicit address validation before attempting the full flight. In practice, PQC-sized certificate chains make Retry-based validation the default path for first-time QUIC connections rather than a fallback reserved for suspected abuse — a direct, quantifiable operational cost of the larger payloads, independent of whether any attack is actually underway.

Mitigation Strategies