Skip to content
Record Layer
step 1/5

Reading — step 1 of 5

Read

~1 min readRecord Layer & Resumption

Record Layer

After the handshake, application data flows in records. Each record:

struct TLSRecord {
    type (1 byte)         // 22 = Handshake, 23 = ApplicationData
    legacy_version (2)    // always 0x0303 in 1.3
    length (2)            // record length (max 2^14 + 256 with overhead)
    payload (length bytes — encrypted)
}

In TLS 1.3, the inner content (after decryption) is:

plaintext || content_type (1 byte) || padding (zeros)

The real type is hidden inside the encrypted payload. The outer type is always 23 (ApplicationData) for post-handshake records — privacy: observers can't tell handshake messages from data after the first few.

Per-record nonce derivation:

python

static_iv derived from traffic key. seq_num increments per record. AEAD nonce is unique without explicit transmission.

python

Records are independent: lose one TCP segment, lose one record. The other side detects via decrypt failure (tag mismatch).

Max record size: 2^14 = 16KB plaintext. Forces head-of-line blocking on slow links — one of QUIC's motivations.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…