TLS Handshake
The handshake that authenticates the server and derives symmetric session keys.
At a Glance
- Purpose — Authenticate the server (and optionally the client), agree on a cipher suite, and derive symmetric keys for the session. Everything after is encrypted with AEAD.
- Versions — TLS 1.3 is the dominant modern version; TLS 1.2 still common. SSL and TLS ≤1.1 are dead — disable them.
- Latency — TLS 1.3 is 1 RTT for a fresh connection; TLS 1.2 is 2 RTTs. With PSK resumption, TLS 1.3 offers 0-RTT for early data.
- Forward secrecy — TLS 1.3 mandates (EC)DHE key exchange. Stealing the server's long-term key does not decrypt past traffic captures.
- Authentication — Server proves possession of its private key by signing transcript; client validates the cert chain to a trusted root and matches the hostname (SNI).
- Runs on TCP — On a cold connection you pay TCP's 1 RTT handshake before TLS even starts. QUIC folds TCP+TLS into one handshake instead.
TLS 1.3 Handshake (Sequence)
One round trip. The client sends its key_share with ClientHello so the server can derive keys and start encrypting in its very first response.
Dashed arrows are encrypted under the handshake keys.
ClientHello / ServerHello
The hellos carry almost everything interesting. Many legacy fields survive in TLS 1.3 only for backwards compatibility.
| Field | In ClientHello | In ServerHello |
|---|---|---|
legacy_version | Always 0x0303 (TLS 1.2) for compat | Same — real version in supported_versions |
random | 32 random bytes | 32 random bytes (incl. downgrade sentinel) |
cipher_suites | List of acceptable AEAD+hash pairs | The single selected suite |
supported_versions ext | Offered TLS versions | Chosen version (e.g. TLS 1.3) |
key_share ext | One or more (group, pubkey) pairs | Single matching (group, pubkey) |
supported_groups ext | ECDHE curves client will accept | — |
signature_algorithms ext | What client can verify | — |
server_name (SNI) | Hostname client is asking for | — |
| ALPN | Protocols client can speak (h2, http/1.1) | The single chosen protocol |
pre_shared_key ext | Resumption ticket + binders | Index of accepted PSK |
Key Exchange (ECDHE)
Ephemeral ECDH on Curve25519 or a NIST P-curve. Both sides derive the same shared secret without it ever touching the wire.
CX = cx · G Note over S: sx = random scalar
SX = sx · G C->>S: key_share CX S->>C: key_share SX Note over C: shared = cx · SX Note over S: shared = sx · CX Note over C,S: HKDF-Extract(shared) → handshake + application traffic secrets
Keys are ephemeral (both scalars are discarded after the connection closes), so forward secrecy is automatic: past sessions cannot be decrypted even if the server's signing key is later compromised.
Certificate Verification
The Certificate message carries the server's end-entity cert + any intermediates. The client must verify all of the following.
- Chain to a trusted root — every cert is signed by the next; the root is in the client's trust store. Intermediates are not trusted on their own. (RFC 5280 defines X.509 path validation.)
- Signature validity — each signature in the chain verifies under its issuer's public key, using an algorithm the client accepts (usually ECDSA or RSA-PSS).
- Hostname match — the SNI the client sent must match a DNS name or IP SAN in the leaf cert. Wildcard rules apply only to the leftmost label.
- Validity window — current time is within
notBefore/notAfteron every cert in the chain. - Revocation — not revoked via CRL or OCSP. Modern deployments use OCSP stapling: server includes a signed, timely OCSP response in the handshake so clients don't do a side-call.
- CertificateVerify — server signs a hash of the transcript with the cert's private key. This proves this server holds the private key, not a replay of a recorded handshake.
- Finished — HMAC over the transcript under the derived handshake key. Binds the whole handshake together; any tampering breaks it.
TLS 1.2 vs 1.3
| TLS 1.2 | TLS 1.3 | |
|---|---|---|
| RTTs to first app byte | 2 | 1 (or 0 with PSK) |
| Key exchange | RSA, DHE, or ECDHE | ECDHE only (PSK too, for resumption) |
| Forward secrecy | Optional (only with DHE/ECDHE) | Mandatory |
| Cipher suite | Bundles kx + auth + cipher + MAC (e.g. TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) | Only AEAD + hash (e.g. TLS_AES_128_GCM_SHA256); kx and auth negotiated separately |
| Handshake encryption | Plaintext after ServerHello | Encrypted from EncryptedExtensions onward |
| Removed / banned | — | Static RSA, CBC MAC-then-encrypt, SHA-1, compression, renegotiation, custom groups |
| 0-RTT | Not supported | Supported via early_data + PSK |
| Version negotiation | In legacy_version | In supported_versions extension (legacy field frozen) |
Session Resumption & 0-RTT
After a successful handshake, the server can issue a NewSessionTicket (an opaque blob, usually an encrypted PSK). Future connections can skip the full handshake.
0-RTT replay risk. The network (or a middlebox) can capture the 0-RTT record and resend it. TLS 1.3 provides no per-record replay protection for early data, so 0-RTT payloads must be idempotent. In practice: safe for GET, unsafe for POST/PUT. Servers typically only accept 0-RTT for known-safe endpoints or enforce an anti-replay window.
Cipher Suite Format
TLS 1.2 bundles four things into one name; TLS 1.3 strips it down to the two things that actually vary per-record.
TLS 1.2:
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
└───┬───┘ └┬┘ └─────┬─────┘ └──┬──┘
key exchange auth AEAD cipher PRF / HMAC hash
= ephemeral ECDH for key exchange,
RSA signatures for server auth,
AES-128-GCM for symmetric encryption,
SHA-256 as the HKDF hash.
TLS 1.3:
TLS_AES_128_GCM_SHA256
└─────┬─────┘ └──┬──┘
AEAD cipher HKDF hash
Key exchange (ECDHE group) and server auth (signature alg)
are now negotiated via separate extensions, not baked into
the suite name. References
- RFC 8446 — TLS 1.3, the current spec.
- RFC 5246 — TLS 1.2 (still widely deployed).
- RFC 6066 — TLS Extensions (SNI, Max Fragment Length, Status Request, etc.).
- RFC 7301 — Application-Layer Protocol Negotiation (ALPN).
- RFC 6960 — Online Certificate Status Protocol (OCSP).
- RFC 5869 — HKDF, the KDF used throughout TLS 1.3.
- RFC 7748 — Curve25519 and Curve448 for key exchange.
- RFC 8032 — EdDSA (Ed25519) signatures.
- RFC 5280 — X.509 certificates and certification paths.
- RFC 8740 — Using TLS 1.3 with HTTP/2 (and implicitly HTTP/3).
- The Illustrated TLS 1.3 Connection — byte-by-byte walk-through of a real handshake.
- Wikipedia: Transport Layer Security — overview, history, and attack surface.
- Wikipedia: ECDH — math behind the key exchange.
- Wikipedia: Authenticated encryption — the AEAD model TLS 1.3 is built on.