Loading content...
The TLS handshake, while cryptographically elegant, comes with a cost: multiple network round-trips and expensive asymmetric cryptographic operations. For a client that connects to the same server repeatedly—as browsers do constantly—repeating the full handshake each time is wasteful.
Session resumption allows parties to skip the expensive parts of the handshake by reusing cryptographic state from a previous connection. When successful, resumption:
This page explores TLS resumption mechanisms: the legacy approaches (session IDs and session tickets), TLS 1.3's unified PSK-based resumption, and the cutting-edge 0-RTT early data feature with its important security caveats.
This page provides a comprehensive examination of TLS session resumption. You will understand session ID resumption, session tickets, TLS 1.3 PSK resumption, 0-RTT early data, anti-replay mechanisms, and the security tradeoffs in resumption strategies.
To understand why resumption matters, we must quantify what full handshakes cost.
Network Latency:
Each round-trip adds network delay. For a user with 50ms latency:
Computational Cost:
Asymmetric operations dominate handshake CPU time:
| Operation | Time (2048-bit RSA) | Time (P-256 ECDSA) |
|---|---|---|
| RSA signature | ~1.5 ms | — |
| RSA verification | ~0.05 ms | — |
| ECDSA signature | — | ~0.15 ms |
| ECDSA verification | — | ~0.35 ms |
| ECDHE (P-256) | ~0.5 ms | ~0.5 ms |
| Certificate chain validation | ~2-10 ms | ~2-10 ms |
A typical full handshake: ~5-15ms of CPU time per connection.
Real-World Impact:
Consider a CDN edge server handling 100,000 connections per second:
Or consider a mobile device on 4G (100ms latency):
| Handshake Type | Time to First Byte | User Experience |
|---|---|---|
| TLS 1.2 full | TCP + 200ms TLS + HTTP = 400ms+ | Noticeable delay |
| TLS 1.3 full | TCP + 100ms TLS + HTTP = 300ms+ | Slight delay |
| TLS 1.3 0-RTT | TCP + 0ms TLS + HTTP = 200ms | Feels instant |
For interactive applications, 100-200ms savings fundamentally change perceived responsiveness.
Why Resumption Works:
Both parties can cache session secrets from a previous handshake. On reconnection:
Fresh keys for each connection provide forward secrecy within the resumption window.
High-traffic servers target resumption rates of 50-80%+. Achieving this requires proper session caching, ticket encryption key management, and understanding client connection patterns. Monitoring resumption rate is essential for TLS performance optimization.
The original TLS resumption mechanism uses session IDs—opaque identifiers assigned by the server.
How Session ID Resumption Works:
Initial Full Handshake:
Abbreviated Handshake (Resumption):
Abbreviated Handshake Properties:
Limitations of Session ID Resumption:
Server-side state: Server must store session data for every client. At scale, this means large distributed session caches.
Load balancing complexity: If a client reconnects to a different server, the session cache isn't available (unless shared via Redis, memcached, etc.).
Memory pressure: Session entries consume memory. Servers must balance cache size vs. resumption rate.
No forward secrecy relative to session cache: If the session cache is compromised, all resumed sessions are at risk.
Cache Configuration:
# Nginx session cache configuration
ssl_session_cache shared:SSL:50m; # 50 MB shared cache
ssl_session_timeout 1d; # Sessions valid for 24 hours
50MB can store roughly 200,000 sessions—sufficient for most deployments.
TLS 1.3 doesn't use session ID resumption—it's replaced by PSK-based resumption with session tickets. However, TLS 1.3 sends a legacy_session_id for compatibility with middleboxes expecting it. The field is present but semantically meaningless.
Session tickets (RFC 5077) solve the server-side state problem by encrypting session state and sending it to the client.
How Session Tickets Work:
The server possesses a ticket encryption key (STEK) known only to itself (or shared among cluster members).
After Full Handshake:
Server creates session ticket containing:
Server encrypts ticket with STEK (AES-GCM or similar)
Server sends NewSessionTicket message to client
Client caches the encrypted ticket (opaque blob to client)
Resumption with Ticket:
Server becomes stateless — no session cache needed. The client stores the state (encrypted).
Ticket Encryption Key (STEK) Management:
STEK management is critical:
STEK lifecycle:
1. Generate new STEK with cryptographically secure random
2. Distribute to all servers in cluster
3. Use for ticket encryption for period T (e.g., 24 hours)
4. Retain for ticket decryption for period 2T (accept old tickets)
5. Securely delete after 2T
Forward Secrecy Implications:
Session tickets create a forward secrecy window:
Forward secrecy window = STEK lifetime + ticket lifetime
If an attacker records traffic and later obtains a STEK (before deletion), they can:
Best Practices:
Many TLS implementations don't rotate STEKs automatically—they're static from server start. This is a significant forward secrecy weakness. If the STEK is compromised at any point, all sessions since server restart are vulnerable. Always configure STEK rotation.
TLS 1.3 unifies resumption under the Pre-Shared Key (PSK) mechanism. Session tickets become a way to establish PSKs.
PSK in TLS 1.3:
A pre-shared key (PSK) is a secret known to both client and server before the handshake. PSKs can come from:
NewSessionTicket Message (TLS 1.3):
After the handshake completes, the server sends one or more NewSessionTicket messages:
struct {
uint32 ticket_lifetime; // Seconds until expiration
uint32 ticket_age_add; // Obfuscation for age
opaque ticket_nonce<0..255>; // For PSK derivation
opaque ticket<1..2^16-1>; // The encrypted session state
Extension extensions<0..2^16-2>;
} NewSessionTicket;
Deriving the PSK:
PSK = HKDF-Expand-Label(
resumption_master_secret,
"resumption",
ticket_nonce,
Hash.length
)
Each ticket has a unique nonce, so each produces a different PSK—even from the same connection.
PSK Modes:
TLS 1.3 defines two PSK modes, communicated via the psk_key_exchange_modes extension:
1. psk_ke (PSK-only):
2. psk_dhe_ke (PSK + DHE):
Binder Verification:
To prevent offline dictionary attacks on PSKs, TLS 1.3 includes a binder:
binder = HMAC(binder_key, Transcript-Hash(Truncated-ClientHello))
The binder proves the client knows the PSK without revealing it. The server verifies before proceeding.
Ticket Age Obfuscation:
To prevent correlation of connections:
obfuscated_ticket_age = (current_time - ticket_issue_time) + ticket_age_add
The ticket_age_add is random, known only to server (stored in ticket). This prevents outsiders from correlating the timing of resumption connections.
The psk_dhe_ke mode adds only ~0.3ms of ECDHE computation but provides full forward secrecy. There's no reason to use psk_ke except in extremely constrained environments or for 0-RTT initial data. Modern TLS libraries default to psk_dhe_ke.
TLS 1.3 introduces 0-RTT (zero round-trip time) resumption—sending application data in the first flight without waiting for server response. This eliminates TLS latency entirely for resumed connections.
How 0-RTT Works:
The Timing Advantage:
Standard 1-RTT resumption:
C→S: ClientHello
S→C: ServerHello, Finished
C→S: Finished
C→S: Request (Application Data) ← First app data after 1 RTT
S→C: Response
0-RTT resumption:
C→S: ClientHello + Early Data (Request) ← App data in first flight!
S→C: ServerHello, Finished + Response ← Response can be immediate
C→S: Finished
For a 100ms latency connection, 0-RTT saves 100ms—often half the total request time.
The Replay Problem:
0-RTT has a fundamental security limitation: early data is replayable.
In standard TLS:
In 0-RTT:
Attack Scenario:
Mitigations:
Application-level idempotency: Only send 0-RTT data for idempotent requests (GET, HEAD). Never for POST, PUT, DELETE.
Server-side anti-replay:
0-RTT rejection: Server can refuse early data and require 1-RTT (safe fallback)
| Property | 0-RTT Early Data | 1-RTT Data |
|---|---|---|
| Confidentiality | ✅ Encrypted with early_traffic_secret | ✅ Encrypted with traffic_secret |
| Integrity | ✅ AEAD authenticated | ✅ AEAD authenticated |
| Forward Secrecy | ⚠️ Only vs PSK compromise, not vs ticket key | ✅ Full (with psk_dhe_ke) |
| Replay Protection | ❌ Replayable without server-side measures | ✅ Guaranteed unique (fresh ServerHello) |
| Latency | ✅ Zero additional RTT | Standard 1 RTT |
Never send state-changing requests as 0-RTT data without server-side replay protection. An attacker replaying 'transfer $10,000' or 'vote for candidate X' can have disastrous consequences. Use 0-RTT only for truly idempotent requests or with robust anti-replay mechanisms.
Servers accepting 0-RTT must implement anti-replay protection. TLS 1.3 specifies two approaches.
1. Single-Use Tickets:
Each session ticket is marked as used after the first resumption:
1. Client sends 0-RTT with ticket T
2. Server checks: Is T in used-tickets database?
- Yes: Reject 0-RTT, proceed with 1-RTT
- No: Accept 0-RTT, add T to used-tickets database
Challenges:
2. Client Hello Recording:
Track unique ClientHello fingerprints:
1. Compute fingerprint F = Hash(ClientHello)
2. Check if F in recent-fingerprints set
- Yes: Reject 0-RTT (duplicate)
- No: Accept 0-RTT, add F to set
3. Expire old fingerprints after time window
Window-Based Approach:
Combine timestamp checking with bounded storage:
This bounds storage: only need to remember recent connections.
Implementation Strategies:
Bloom Filter:
Distributed Cache (Redis/Memcached):
IP-Bound Tickets:
Embed client IP in the session ticket (encrypted):
Limitations: Legitimate IP changes (mobile roaming, NAT) cause 0-RTT rejection.
Practical Server Configuration:
# Nginx: conservative 0-RTT settings
ssl_early_data on;
ssl_session_tickets on;
ssl_session_timeout 1h; # Short timeout limits replay window
# Ensure upstream knows about 0-RTT
proxy_set_header Early-Data $ssl_early_data;
The Early-Data header tells the application whether the request came via 0-RTT, allowing it to defer state changes until confirmation.
RFC 8470 defines the 'Early-Data' header. Proxies should set it to '1' for 0-RTT requests. The origin server can then choose to process the request immediately (if idempotent) or wait for the handshake to complete (for state-changing operations). This gives applications fine-grained replay control.
Implementing resumption correctly requires balancing performance, security, and operational concerns.
Ticket Key Rotation Pattern:
// Key rotation timeline
t=0h: Generate key K1, encrypt tickets with K1
t=12h: Generate key K2, decrypt K1+K2, encrypt with K2
t=24h: Generate key K3, decrypt K2+K3, encrypt with K3, delete K1
...
Overlapping decrypt windows ensure smooth transitions without breaking resumption.
When to Disable Tickets:
Configuration Example (High-Security):
# Maximum forward secrecy configuration
ssl_session_tickets off; # Disable tickets
ssl_session_cache shared:SSL:10m; # Session ID cache
ssl_session_timeout 5m; # Short timeout
This trades resumption efficiency for stronger forward secrecy—appropriate for extremely sensitive applications.
Use TLS logging to measure resumption rate. In OpenSSL, enable session logging. Look for 'Reused' in connection logs. Aim for 50%+ resumption rate for return visitors. If lower, investigate ticket lifetime, client caching behavior, and server clock synchronization.
Session resumption transforms TLS from a connection-time bottleneck to a nearly invisible security layer. By caching and reusing cryptographic state, resumption eliminates the expensive parts of handshakes while maintaining security.
Completion of Module 2:
You have now completed the TLS Handshake module. Through these five pages, you've developed a deep understanding of:
This knowledge enables you to configure TLS securely, debug handshake failures, understand security advisories, and appreciate the elegant engineering that protects billions of daily connections.
You have mastered the TLS Handshake — the cryptographic protocol that establishes secure channels across the internet. From the initial ClientHello to 0-RTT resumption, you understand how TLS achieves authentication, confidentiality, and integrity. This foundation prepares you for advanced topics in network security protocols.