Chris Collins

Tools · network

TLS 1.3 and QUIC handshakes

Step through TLS 1.3 (full, HelloRetryRequest, PSK resumption with 0-RTT), TLS 1.2 and QUIC handshakes message by message, with every byte built and every secret of the key schedule computed live with Web Crypto — and checked against the RFC 8448 and RFC 9001 test vectors.

Added

Works with

How to use it

A TLS handshake drawn as the usual ladder diagram, except that nothing in it is made up. Every message is built byte for byte, the key exchange is a real X25519 or P-256 ECDH done by your browser’s Web Crypto, the server’s certificate is a real self-signed ECDSA certificate made on the spot, CertificateVerify is a real signature over the transcript, and the whole key schedule of RFC 8446 §7.1 — Early Secret, Handshake Secret, Master Secret and every traffic secret — is computed with HKDF as the messages go past. The records and QUIC packets are encrypted with the keys it derives.

Switch Keys to RFC example and the TLS scenarios use the private keys and messages of RFC 8448 (Example Handshake Traces for TLS 1.3) instead: each secret then carries a ✓ when it equals the value printed in the RFC, and the encrypted records match the RFC’s to the byte. The QUIC scenarios use RFC 9001’s connection ID, so the Initial secrets can be compared with Appendix A.

How to use it

Pick a scenario and press Start. Each step sends one message; the narration says what it is for and links the section of the RFC. Back and Next (or ← →) step, Play (or space) runs through, ⏭ All shows the whole handshake. Tap any message in the diagram to inspect it.

  • The diagram. Client on the left, server on the right, time downwards; each arrow is one message, coloured by what protects it: plaintext, the handshake keys ({…} in RFC 8446’s notation), the application keys ([…]) or the 0-RTT keys ((…)); for QUIC, by packet number space (Initial, Handshake, 0-RTT, 1-RTT). The number by the sender is when it leaves, in round trips. Under each end, the state it is in.

  • Message. The fields of the message decoded — every extension of a ClientHello, the key shares, the PSK binder, the QUIC frames inside a packet — and its bytes. Hovering a field highlights its bytes in the hex dump. On the wire shows what actually crosses the network: the record (or QUIC packet) with its header and ciphertext. For the certificate, Open certificate in the decoder hands it to the certificate decoder.

  • Key schedule. Every secret in order, with its formula, its value, and who knows it at this point. New values are highlighted; tap a long value to see all of it. Below them, the AES-GCM traffic keys and IVs (and QUIC’s header-protection keys).

  • Checks. What was verified while building the handshake: both ECDH results agree, the CertificateVerify signature verifies with the certificate’s key, the Finished MACs, the record decrypts back, the anti-amplification limit — and, in RFC mode, every value the RFC prints.

  • Options. The key-exchange group (X25519 or P-256), the server name sent as SNI and put in the certificate, and the ALPN protocol. ↻ New keys runs it again with fresh randomness.

The Round trips compared tab puts the setups side by side for a round-trip time you choose: TCP + TLS 1.2, TLS 1.2 resumed, TCP + TLS 1.3 (with and without HelloRetryRequest and 0-RTT), TCP Fast Open, QUIC, QUIC with Retry and QUIC 0-RTT — when the request can leave and when the first byte of the response arrives.

The scenarios

  1. TLS 1.3 full handshake — ClientHello with key_share, SNI and ALPN; ServerHello; then EncryptedExtensions, Certificate, CertificateVerify and Finished, encrypted; the client’s Finished; a NewSessionTicket; the request. One round trip.

  2. HelloRetryRequest — the client’s key share is for the wrong group; the server asks again with a cookie, and the first ClientHello is replaced in the transcript by its hash (§4.4.1).

  3. Resumption with PSK and 0-RTT — a ticket from an earlier connection (built first, in the background) becomes the pre-shared key; the binder proves the client has it; the request goes with the ClientHello as early data, followed by EndOfEarlyData. The narration spells out why 0-RTT data can be replayed and how servers limit the damage (§8, RFC 8470).

  4. TLS 1.2 for comparison — ECDHE-ECDSA with AES-128-GCM: two round trips, the certificate and key exchange in the clear, ServerKeyExchange signed on its own, ChangeCipherSpec, keys from the PRF with the extended master secret (RFC 7627).

  5. QUIC handshake — the same TLS 1.3 messages carried in CRYPTO frames: the client’s padded Initial (encrypted with keys derived from its random connection ID), the server’s Initial and Handshake packets coalesced, the client’s Finished and its request in a 1-RTT packet, then HANDSHAKE_DONE. Connection IDs and the three packet number spaces are tabulated.

  6. QUIC Retry — the server answers with a stateless Retry and a token, with its integrity tag; the client starts again with new Initial keys.

  7. QUIC 0-RTT resumption — the request in a 0-RTT packet next to the first Initial.

  8. QUIC connection migration — the client changes network, switches to a spare connection ID, and the server validates the new path with PATH_CHALLENGE / PATH_RESPONSE.

What is real and what is simplified

Real: the encoding of every handshake message and extension (RFC 8446 §4), the key schedule and traffic keys (§7), Finished and the PSK binder (§4.4.4, §4.2.11.2), the HelloRetryRequest transcript (§4.4.1), record protection with AES-128-GCM (§5.2–5.3), the resumption PSK (§4.6.1); TLS 1.2’s PRF, extended master secret, key block and AEAD records (RFC 5246, RFC 7627, RFC 5288); QUIC’s Initial secrets, packet protection and header protection, the Retry integrity tag (RFC 9001 §5), varints, long and short headers, transport parameters and the frames used (RFC 9000).

Tested in node against: all of RFC 8448 §3 (1-RTT), §4 (resumed 0-RTT) and §5 (HelloRetryRequest with P-256) — secrets, keys, Finished messages, binder and the encrypted records byte for byte, and the RFC’s RSA-PSS CertificateVerify verified with its key; RFC 9001 Appendix A.1–A.4 (Initial keys, the protected client and server Initial packets, the Retry packet) and A.5’s key labels; the TLS 1.2 PRF test vector; RFC 5869’s HKDF vector; RFC 9000’s varint examples. The certificate made here is checked with OpenSSL.

Simplified: only TLS_AES_128_GCM_SHA256 (TLS 1.3) and ECDHE-ECDSA-AES128-GCM-SHA256 (TLS 1.2); the server always accepts what the client offers; no client certificates, KeyUpdate, ECH or post-quantum hybrid shares; the ticket in fresh mode is random bytes rather than encrypted server state; QUIC’s acknowledgements and flow control are the minimum to show the spaces, there is no loss or recovery, and the HTTP/3 request and response are placeholder text rather than QPACK-encoded frames. The comparison tab counts round trips only.

Browser support

Any current browser with Web Crypto on a secure page. X25519 in Web Crypto needs Chrome or Edge 133+, Firefox 130+ or Safari 17+; elsewhere the tool uses P-256 (the RFC 8448 §3 and §4 traces need X25519).

Privacy

Everything runs in this page; nothing is sent anywhere. The keys and the certificate are made for the demonstration and thrown away when you leave. Related: certificate decoder, HTTP client, HTTP reference, DNS lookups, latency numbers, speed test, and the simulators TCP, simulated and DHCP, ARP, NAT and routing.

Runs entirely in your browser; nothing you type leaves this page.