M8 / Protocols

TLS 1.3 hybrid key exchange: your own measurement

PractitionerAdvisor

After this lesson you can

  • Measure the X25519 and X25519MLKEM768 ClientHello in your own environment and explain, component by component, where the difference comes from, unlike in the RSA/ECDSA era
  • Describe which inputs a TLS handshake byte calculator works with, building on this measurement

Before thisM7: X.509 and PKI

Mental model

In M7 you measured how much a certificate chain grows with PQC. This lesson applies the same discipline to another part of the TLS handshake, the ClientHello itself: the first message a client sends when starting a connection carries the key exchange methods it supports (the key_share extension), and that extension grows with hybrid key exchange.

The measurement: in your own environment, today

While preparing this lesson, two separate ClientHellos were measured over a real connection (OpenSSL 3.6.2, macOS arm64, cloudflare.com:443, 2026-09-05), reading the raw TLS records with the -msg flag:

  • X25519 only: 306 BMEASURED
  • X25519MLKEM768 (hybrid): 1484 BMEASURED
  • Difference: 1178 BDERIVED

These figures are read from the TLS record’s (16 03 01 ...) own length field; the two bytes after the first three (01 32 or 05 cc) give the exact length of the ClientHello carried by the record, in hex (excluding the 5-byte record header itself).

Why there is a 2-byte difference: natural variance

The figure used in M3 and M9 (308 BMEASURED, OpenSSL 3.5.1, from the corpus’s Day 8 lab) is 2 bytes off from this lesson’s own measurement (306). That is not an error: the exact size of the ClientHello can change by a few bytes depending on the OpenSSL version and which extra extensions (session ticket support, the exact contents of the ALPN list, server name length) are enabled by default. The hybrid figure (1484), on the other hand, came out identical in two independent measurements, because the main source of growth (ML-KEM-768’s 1184-byte encapsulation key) is fixed; the small variance appears only in the classical part. This is the same discipline as the “22940-22950 range, natural variance” note in M7’s own X.509 chain measurement: a figure moving by a few bytes does not mean the measurement is wrong; it is the real world’s small variability.

The tool: TLS handshake byte calculator

This measurement is the basis of the site’s TLS handshake byte calculator: it computes the total bytes and segment count from the key exchange (classical, hybrid or pure PQC), the signature algorithm (the ML-DSA variants you saw in M4), the number of intermediate certificates (M7) and OCSP stapling, and shows the arithmetic for each message. This lesson’s own measurement provides the real, verified values for the calculator’s “key exchange” input; the commands in this lesson’s lab section are the way to do the same calculation by hand.

Numbers to know

  • This lesson's own measurement (OpenSSL 3.6.2, macOS arm64, cloudflare.com, 2026-09-05): X25519 ClientHello 306 B, X25519MLKEM768 ClientHello 1484 B, difference 1178 B
  • The earlier measurement used in M3/M9 (OpenSSL 3.5.1, corpus Day 8 lab): X25519 308 B, difference 1176 B; the 2 B difference is real and natural (OpenSSL version and extension set differences), not an error

Lab: Measure your own ClientHello

Requires: OpenSSL 3.5+ (for X25519MLKEM768 support), internet access. Check your setup

shell
echo Q | openssl s_client -connect cloudflare.com:443 -curves X25519 -msg 2>&1 | sed -n '4p'
Recorded output
16 03 01 01 32 (the TLS record header; the last two bytes, 01 32, are the record length: 0x0132 = 306 decimal)
shell
echo Q | openssl s_client -connect cloudflare.com:443 -curves X25519MLKEM768 -msg 2>&1 | sed -n '4p'
Recorded output
16 03 01 05 cc (0x05cc = 1484 decimal; it may differ by a few bytes in your environment, which is normal, see 'Why there is a 2-byte difference' below)

At the table

How to say this in a bank meeting.

To an executive
The real cost of hybrid key exchange is not an estimate but a number measured in our own environment: about 1.2 KB of extra overhead in a single TLS handshake. That is a cost item separate from the certificate chain growth you saw in M7.
To an architect
The growth in the ClientHello comes entirely from the `key_share` extension: next to X25519's 32-byte point, ML-KEM-768's 1184-byte encapsulation key is added (the FIPS 203 size you saw in M3). This is a cost layer completely separate from the certificate chain (M7); the two must be added, one does not replace the other.
Objection
“"I see different ClientHello figures in online sources. Which is right?"”
Answer
Several may be right, because they were measured in different environments: the OpenSSL version, which extra extensions (session ticket, ALPN list) are enabled, and the target server can all make a difference of a few bytes. What matters is not memorizing one 'official' figure but knowing how to measure it in your own environment; this lesson shows exactly that.

Sources

Checkpoint

Answer first, then compare with the model answer and score yourself against the rubric. Saved in this browser only.

  1. 01Recall

    Where does the growth in the X25519MLKEM768 ClientHello come from, and which extension carries it?

  2. 02Recall

    How many bytes apart are this lesson's own measurement and the figure used in M3/M9, and is that difference an error?

  3. 03Scenario

    A colleague brings a '2.5 KB overhead' figure from a blog post. What do you ask them, and how do you verify it in your own environment?

  4. 04Hostile

    An auditor asks 'How do you know the exact size of your ClientHello?' Give your full answer, including which command you ran in which environment.

Project linkThe core measurement of Project 1 (hybrid key exchange measurement and cost analysis); this lesson's command sequence is reused in Project 1's own lab section.