What actually happens in a TLS 1.3 handshake
2026-10-18
TLS 1.3 reduced the full handshake to a single round trip. The mechanism is simple to state — the client guesses the key exchange group and sends a key share immediately — but the consequences are worth spelling out.
The first flight
The client sends a ClientHello containing:
- supported cipher suites, in preference order
- the
key_shareextension, carrying an ephemeral public key - the
supported_versionsextension, with 1.3 listed - a
server_nameindication, unless the client declines to send it
The key share is the important part. Because the client has already committed to a group and produced a public key, the server can compute the shared secret and reply with its own key share in the same flight as its certificate. That is what saves the round trip.
What the server sends back
The server replies with its key_share, the certificate chain, a
CertificateVerify proving possession of the private key, and a Finished
message. Everything after the key share is encrypted, including the certificate — a change from
1.2 that surprises people reading captures for the first time.
Forward secrecy, unconditionally
TLS 1.3 removed static RSA key exchange entirely. Every 1.3 handshake uses an ephemeral key exchange, so compromising the server's long-term key later does not decrypt past sessions. This is the main reason 1.3 is worth enabling even when nothing else about your setup changes.
Session resumption
After the handshake the server may send one or more NewSessionTicket messages.
A client that holds a ticket can resume with a PSK, sending early data in the very first flight —
zero round trips. The catch is that 0-RTT data is replayable: an attacker who captures the early
data can resend it. Servers are supposed to apply anti-replay windows, and applications are
supposed to restrict 0-RTT to idempotent requests. In practice both are frequently skipped.
If you are debugging a connection that behaves differently on the second attempt than the first, resumption is usually the answer.
What I would check
- Is the negotiated version actually 1.3, or did a middlebox downgrade it?
- Which group was selected — X25519, or something weaker?
- Is the certificate being sent encrypted, as 1.3 requires?
- Is 0-RTT enabled, and if so, is replay protection real?