Walk me through a TLS 1.3 handshake. Why is it one round trip instead of two?
Show the answer
Say this first
The client sends a ClientHello with its supported versions, cipher suites, signature algorithms, SNI, ALPN and, the key change, a key share: its ephemeral Diffie-Hellman public key for the group it guesses the server will pick. The server replies with ServerHello and its own key share, and both sides can now compute the handshake keys. Everything after ServerHello is encrypted: EncryptedExtensions, Certificate, CertificateVerify and Finished. The client checks them and sends its Finished, already able to send its request. TLS 1.2 needed a separate round trip to agree on parameters before exchanging keys; TLS 1.3 sends the key share up front.
Go deeper
The messages
Client Server
ClientHello
+ supported_versions, key_share, signature_algorithms,
server_name (SNI), ALPN, psk_key_exchange_modes ->
ServerHello + key_share
{EncryptedExtensions} (ALPN result)
{Certificate}
{CertificateVerify} (signature over the transcript)
<- {Finished}
{Finished}
[Application data: GET /] ->Braces mean encrypted with handshake keys. The server can send data right after its Finished.
Round trips before the first request byte
| Stack | Round trips |
|---|---|
| TCP + TLS 1.2 | 3 |
| TCP + TLS 1.3 | 2 |
| QUIC (TLS 1.3 inside) | 1 |
| TLS 1.3 or QUIC resumption with 0-RTT | data in the first flight |
What 1.3 removed
RSA key transport (no forward secrecy), static Diffie-Hellman, CBC and RC4 ciphers, SHA-1 in signatures,
compression and renegotiation. The cipher suites are AEAD only, for example TLS_AES_128_GCM_SHA256,
TLS_AES_256_GCM_SHA384 and TLS_CHACHA20_POLY1305_SHA256.
Things that look odd in captures
- The version field says TLS 1.2; the real version is in the supported_versions extension. This middlebox compatibility mode also sends a dummy ChangeCipherSpec.
- If the server does not like the client's key share group it sends a HelloRetryRequest, which costs one more round trip.
- Hybrid post-quantum key shares such as X25519MLKEM768 make the ClientHello larger than one packet, which has exposed middleboxes that assumed a ClientHello fits in one segment.
They will ask next
What can a firewall read in a TLS 1.3 handshake?
The ClientHello in clear: SNI, ALPN, offered versions and cipher suites (often fingerprinted, for example with JA3 or JA4), and the ServerHello. The server certificate is encrypted in 1.3, unlike 1.2.
What is forward secrecy and why does 1.3 force it?
Session keys come from ephemeral Diffie-Hellman values that are thrown away, so stealing the server's private key later does not decrypt recorded traffic. With RSA key transport it did, so 1.3 removed it.
What does CertificateVerify prove?
That the server holds the private key for the certificate. It is a signature over the handshake transcript, which also protects the negotiation from tampering.
Traps
- Saying the server certificate is visible to observers in TLS 1.3. It is encrypted.