TLS 1.3 Handshake

One round trip to a secure channel — how TLS 1.3 got there by deleting options, what each handshake message actually does, and why 0-RTT is the one part that trades security for latency.

TLS 1.3 (RFC 8446, 2018) took five years and 28 drafts, and its central design move was subtraction. TLS 1.2 accumulated two decades of options — RSA key transport, static DH, CBC modes, compression, renegotiation, MD5/SHA-1 signatures, custom DH groups — and nearly every major TLS attack exploited one of them or the negotiation between them. TLS 1.3 removed all of it, cut the handshake to one round trip, and made forward secrecy and AEAD mandatory rather than optional.

What was deleted, and which attack each deletion closes #

Removed Attack it enabled
RSA key transport Bleichenbacher oracles — DROWN, ROBOT, Marvin
CBC ciphersuites padding oracles — BEAST, Lucky 13, POODLE
RC4 keystream biases
Compression CRIME, BREACH
Renegotiation triple-handshake, renegotiation injection
Custom/arbitrary DH groups Logjam, small-subgroup confinement
MD5/SHA-1 in signatures SLOTH, collision forgeries
Static DH / non-PFS suites retroactive decryption of recorded traffic

What remains is a short list: ECDHE or DHE key agreement with named groups only, five AEAD ciphersuites, and signatures over the transcript. Forward secrecy is not negotiable — there is no non-PFS mode left to downgrade into.

The 1-RTT handshake #

The move that buys the round trip: the client guesses the group and sends its ECDHE key share in the very first flight. If it guesses right (X25519 essentially always), the server completes key agreement on receipt and can encrypt everything after ServerHello. A wrong guess costs a HelloRetryRequest and one extra round trip — the fallback, not the norm.

The messages, and what each is for:

  • ClientHello — random, offered ciphersuites, key_share (the actual ECDHE public value), supported_versions (this is where "TLS 1.3" is declared — the legacy version field still says 1.2 for middlebox compatibility), signature_algorithms.
  • ServerHello — chosen suite and the server's key_share. After this, both sides derive handshake traffic keys and everything else is encrypted, including the certificate. TLS 1.2 sent certificates in the clear; TLS 1.3 does not, which removes a passive-observer identity leak (though SNI in the ClientHello still leaks the hostname unless ECH is in use).
  • EncryptedExtensions — the rest of the negotiated parameters, now confidential.
  • Certificate + CertificateVerify — the chain, plus a signature over the entire handshake transcript hash with the certificate's private key. This is what proves possession of the key and simultaneously binds the whole negotiation.
  • Finished — HMAC over the transcript under a derived finished_key, from each side.

The key schedule #

Everything derives from HKDF through chained extract/expand stages:

Every Derive-Secret call mixes in a label and the transcript hash at that point, so each key is bound to the exact handshake state that produced it. Record keys and nonces come from the traffic secrets, and the per-record nonce is the 96-bit sequence number XORed with a static IV — counter-derived, never random, which is exactly the GCM nonce discipline the protocol needs. Traffic secrets can be ratcheted forward with KeyUpdate for long-lived connections.

Session resumption and 0-RTT #

After a handshake the server may issue NewSessionTickets carrying a PSK. A resumed handshake uses that PSK instead of a certificate, and the client may attach early data to its first flight — encrypted under a key derived from the PSK alone, before any fresh ECDHE. Zero round trips to first byte.

Resumption with the psk_dhe_ke mode restores full forward secrecy by mixing fresh ECDHE into the resumed handshake; prefer it over pure psk_ke.

Operational notes #

  • Named groups only. X25519 is the default; P-256 for FIPS. No custom parameters means no Logjam.
  • Five ciphersuites, all AEAD: TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, and two CCM variants. Clients pick GCM or ChaCha20 by hardware.
  • Middlebox compatibility mode — the dummy ChangeCipherSpec and legacy version fields exist purely because deployed middleboxes broke on a handshake that looked new. A large fraction of the RFC's final drafts went into making TLS 1.3 look enough like 1.2 on the wire to pass.
  • Encrypted Client Hello (ECH) closes the remaining SNI leak by encrypting the inner ClientHello to a public key published in DNS; it is a separate, later specification.
  • Post-quantum: deployments have converged on the hybrid X25519MLKEM768 group — classical and ML-KEM combined, so the handshake stays secure if either component holds. Enabled by default in major browsers as of 2026.

Sources

  1. docsRFC 8446 — The Transport Layer Security (TLS) Protocol Version 1.3
  2. paperA Comprehensive Symbolic Analysis of TLS 1.3 (Cremers et al., CCS 2017)
  3. docsRFC 8470 — Using Early Data in HTTP
  4. articleThe Illustrated TLS 1.3 Connection

Searches titles, aliases, headings, summaries, and full text.↑↓ move ↵ open esc close