On this page
TLS 1.2 Handshake
TLS 1.2 Handshake: ClientHello→ServerHello→Certificate→KeyExchange→Finished, completing key negotiation in two round trips. Understanding the cryptographic operations at each step (RSA vs ECDHE, signature vs key exchange) is a prerequisite for understanding why TLS 1.3 can reduce this to 1-RTT.
Overview
TLS (Transport Layer Security) is the foundation of secure internet communication, defined in RFC 5246 in 2008. It addresses three problems: authentication (who is the server), confidentiality (data is encrypted), and integrity (data is not tampered with). The TLS 1.2 handshake is the most widely deployed version—establishing a secure channel in 2-RTT, using ECDHE to ensure forward secrecy, and SNI allowing multiple domains to share a single IP. This article dissects the handshake process, key derivation, and session resumption mechanisms frame by frame.
Full Handshake (2-RTT)
sequenceDiagram
participant C as Client
participant S as Server
Note over C,S: ═══ RTT 1 ═══
C->>S: ① ClientHello<br/>version + random + cipher_suites<br/>+ extensions (SNI, ALPN, supported_groups)
S->>C: ② ServerHello + Certificate*<br/>+ ServerKeyExchange*<br/>+ CertificateRequest*<br/>+ ServerHelloDone
Note over C: Verify certificate chain<br/>Compute pre_master_secret
Note over C,S: ═══ RTT 2 ═══
C->>S: ③ Certificate*<br/>ClientKeyExchange<br/>CertificateVerify*<br/>[ChangeCipherSpec]<br/>Finished
Note over S: Decrypt pre_master_secret<br/>Derive session keys
S->>C: ④ [ChangeCipherSpec]<br/>Finished
Note over C,S: ✅ Secure channel established<br/>Encrypted application data transmission
C->>S: Application Data (encrypted)
S->>C: Application Data (encrypted)
* = optional (depends on cipher suite and server configuration)
ClientHello
struct {
ProtocolVersion client_version; // {3,3} = TLS 1.2
Random random; // 32B: gmt_unix_time(4) + random_bytes(28)
SessionID session_id; // ≤32B (for resumption) or empty
CipherSuite cipher_suites<2..2^16-2>; // List of client-supported suites, prioritized
CompressionMethod compression_methods; // {0} = null (null is mandatory in TLS 1.2)
Extension extensions<0..2^16-1>; // SNI, ALPN, supported_groups, signature_algorithms, ...
}
Key Extensions:
server_name (SNI): Domain name to access — server selects the correct certificate (multiple certs on one IP)
supported_groups: EC curves supported by the client (secp256r1, x25519, ...)
ec_point_formats: uncompressed (only value, practically useless)
signature_algorithms: Signature algorithms supported by the client (RSA-PKCS1-SHA256, ECDSA-SHA256, ...)
ALPN: Application layer protocol list ("h2", "http/1.1") — server selects one
Extended Master Secret: Prevents Triple Handshake attacks
SessionTicket TLS: Supports session tickets (stateless resumption)
Cipher Suite Format
Key Derivation
1. From DH key exchange: pre_master_secret (computed jointly by server/client)
2. master_secret = PRF(pre_master_secret, "master secret",
ClientHello.random + ServerHello.random)[0..47]
3. From master_secret: 6 session keys
key_block = PRF(master_secret, "key expansion",
ServerHello.random + ClientHello.random)
→ client_write_MAC_key, server_write_MAC_key,
client_write_key, server_write_key,
client_write_IV, server_write_IV
4. Finished message = PRF(master_secret, "client finished",
hash(all handshake messages))[0..11]
→ Ensures handshake was not tampered with
Session Resumption
Session ID (Stateful, RFC 5246):
1. Initial full handshake → ServerHello.session_id = <random ID>
2. Server caches: session_id → master_secret + cipher_suite
3. Reconnection: ClientHello.session_id = <cached ID>
→ Server finds session → Skips Certificate + ServerKeyExchange
→ 1-RTT
Session Ticket (Stateless, RFC 5077):
1. Server: Encrypts (master_secret + cipher_suite + ticket_lifetime)
(using server's ticket key) → Sends to client → SessionTicket extension
2. Reconnection: ClientHello.session_ticket = <encrypted blob>
→ Server decrypts ticket → Restores session → 1-RTT
→ Server does not need to store session state (cipher from ticket)
Security: Ticket key must be kept secret + rotated regularly (ticket leak → historical session leak)
References
- RFC: 5246, 6066, 7301, 5077, 7627 (Extended Master Secret)
- Tools:
openssl s_client -connect host:443 -tls1_2, Wiresharkssl.handshake
Keywords: TLS 1.2, ECDHE, cipher suite, session resumption, session ticket, SNI, ALPN, PRF