awesome-everything RU
↑ Back to the climb

Networking & Protocols

Session resumption and 0-RTT

Crux PSK tickets let warm connections skip certificate validation; 0-RTT early data eliminates the handshake RTT for read-only requests — but replay attacks constrain what can safely go in early data.
Your altitude — climbing toward senior
ZeroJuniorMiddleSenior
You are at middle altitude — in the sky
◷ 12 min

The first TLS connection to a server costs one full RTT. But when you reload the same page five minutes later, the browser already knows that server. TLS 1.3 lets it skip certificate validation entirely and — in the right conditions — attach the first request to the handshake itself, paying zero extra RTTs.

NewSessionTicket and PSK resumption

After a successful handshake, the server sends a NewSessionTicket message — an encrypted blob containing a pre-shared key (PSK) and metadata (ticket age, lifetime). The client caches it keyed by hostname.

On the next connection to the same server, the client includes a pre_shared_key extension in its ClientHello with the ticket. The server decrypts the ticket, recognizes the PSK, and skips certificate validation entirely. It derives the session keys from the PSK instead of ECDHE.

Cost: still one full RTT (the ClientHello must still reach the server), but no expensive PKI operations. Certificate parsing and chain validation are eliminated.

0-RTT early data

If the browser has a cached PSK, it can encrypt the first request using the PSK’s key and attach it to the ClientHello itself — before the handshake completes. The server decrypts and processes the request immediately, then sends both the handshake response and the application response. Cost for the request: zero extra RTTs.

RTT cost comparison
TLS 1.2 cold
2 RTT
TLS 1.3 cold
1 RTT
TLS 1.3 warm (PSK resumption)
1 RTT (no cert)
TLS 1.3 0-RTT
0 RTT for request
At 100 ms RTT: 0-RTT saving
100 ms vs cold TLS 1.3
Typical ticket lifetime
up to a few hours (impl-defined)

The replay problem

0-RTT has a fundamental security weakness: it is not protected against replay attacks. An attacker on the wire can capture the 0-RTT ClientHello and resend it to the server. The server, seeing a valid PSK ticket and valid early data, may process the request again.

  • For GET /news: replay is harmless — same read, same result.
  • For POST /transfer: replay is catastrophic — the database row is created twice, money is transferred twice.

The simplest rule: 0-RTT is only safe for idempotent requests where replaying produces no additional side effects. GET, HEAD, and OPTIONS are typically safe. POST, PUT, DELETE that mutate state are unsafe.

RFC 8470 and 425 Too Early

RFC 8470 defines the HTTP response code 425 Too Early: the server returns this status when it receives a 0-RTT request for a route that is not safe to replay. The client must retry after the handshake completes. Frameworks (Spring, Express, Caddy) expose middleware that inspects the Early-Data: 1 request header and returns 425 Too Early for any handler that mutates state.

Trace it
1/4

A POST /transfer arrives with TLS early_data and ticket_age = 5 seconds. Trace the server's decision path.

1
Step 1 of 4
Step 1: Is ticket_age inside the replay window (default 10 s)?
2
Locked
Step 2: Has this ticket nonce been seen before (single-use cache)?
3
Locked
Step 3: Ticket is fresh and unseen. What is the third check?
4
Locked
Step 4: A GET /catalog/42 arrives with the same valid 0-RTT context. What happens?
Quiz

Why can an attacker replay 0-RTT early data but not regular TLS 1.3 data?

Quiz

PSK resumption skips certificate validation. How does the client still know it is talking to the right server?

Why this works

NewSessionTicket obfuscation. Each ticket includes a ticket_age_add — a random value the client adds to the real ticket age before sending obfuscated_ticket_age. This stops on-path observers from correlating tickets across connections by their visible age. It also makes timing-based replay window checks more robust: the server subtracts ticket_age_add to recover the real age and compare it to its expected RTT window.

Recall before you leave
  1. 01
    What does the server send after a handshake to enable future resumption?
  2. 02
    Why is 0-RTT limited to idempotent HTTP methods?
  3. 03
    What status code should a server return for a 0-RTT POST to a mutating endpoint, and what must the client do?
Recap

After a TLS 1.3 handshake, the server issues a NewSessionTicket containing a pre-shared key. On the next connection, the client presents this ticket so the server can skip certificate validation — still one RTT, but cheaper. With a cached PSK, the client can also encrypt the first request inside the ClientHello itself as 0-RTT early data: the server processes it before the handshake completes, saving a full RTT. The catch is replay vulnerability: the same 0-RTT ClientHello can be captured and resent by an attacker. Safe use is restricted to idempotent requests (GET, HEAD, OPTIONS), and servers must return 425 Too Early for any mutating endpoint that receives early data.

Connected lessons
appears again in152
Continue the climb ↑Key schedule, SNI, ALPN, and extensions
shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.