TLS
Transport Layer Security — encryption, authentication, integrity
The Three Pillars of TLS
TLS (Transport Layer Security) sits between the application layer and the transport layer. It wraps a reliable transport (typically TCP; embedded in QUIC for HTTP/3) and provides three guarantees:
Confidentiality
Data is encrypted so that only the intended recipient can read it. Anyone intercepting packets on the wire sees ciphertext. Achieved via symmetric encryption (AES-GCM, ChaCha20-Poly1305) with keys established during the handshake.
Authentication
The server proves its identity via a certificate signed by a trusted Certificate Authority. The client verifies the certificate chain to confirm it's talking to the real server, not an impersonator. Optionally, the client can also authenticate (mTLS).
Integrity
Every TLS record includes a MAC (Message Authentication Code). If any bit of the ciphertext is modified in transit, the recipient detects it and rejects the record. In TLS 1.3, AEAD ciphers (AES-GCM) provide encryption + integrity in a single operation.
Note
Terminology: "SSL" and "TLS" are often used interchangeably in casual conversation, but SSL (Secure Sockets Layer) is the deprecated predecessor. SSL 3.0 was the last SSL version (1996). TLS 1.0 replaced it in 1999. As of 2021, only TLS 1.2 and TLS 1.3 are considered secure. TLS 1.0 and 1.1 are officially deprecated (RFC 8996).
TLS 1.3 Handshake
TLS 1.3 (RFC 8446, 2018) redesigned the handshake to be both faster and more secure than TLS 1.2. The key improvement: 1-RTT handshake — the client sends its key share in the first message, enabling the server to derive the shared secret immediately.
Full Handshake (1-RTT)
Step-by-Step Breakdown
- Client Hello — The client sends:
- Supported TLS versions (only 1.3 in the supported_versions extension)
- Supported cipher suites (e.g., TLS_AES_256_GCM_SHA384)
- Key share — the client's ECDHE public key (this is the 1.3 innovation: send key material upfront)
- SNI (Server Name Indication) — the hostname (e.g.,
api.example.com) - Supported signature algorithms
- ALPN list (e.g.,
h2, http/1.1)
- Server Hello — The server responds with:
- Chosen cipher suite
- Server's ECDHE public key (key share)
- Encrypted Extensions — additional server parameters
- Certificate — the server's X.509 certificate
- Certificate Verify — signature over the handshake transcript, proving the server owns the private key for the certificate
- Finished — HMAC over the entire handshake transcript (integrity check)
- Client Finished — The client sends its Finished message (HMAC over the handshake). Application data can be sent immediately in this same flight. Total: 1 round trip.
TLS 1.2 vs TLS 1.3 Handshake Comparison
- ClientHello (cipher suites, random)
- ServerHello + Cert + ServerKeyExchange + Done
- ClientKeyExchange + ChangeCipherSpec + Finished
- ChangeCipherSpec + Finished
- Application Data
Key exchange happens in messages 2-3. Encryption begins only after step 4.
- ClientHello + key_share + SNI
- ServerHello + key_share + {Cert + Finished}
- Finished + Application Data
Client sends key material in message 1. Server encrypts from message 2 onwards. App data flows in message 3.
0-RTT Resumption (PSK)
When a client has connected to a server before, TLS 1.3 supports 0-RTT resumption. During the previous session, the server sends the client a PSK (Pre-Shared Key) — essentially a session ticket. On reconnection, the client includes application data in the very first message, encrypted with the PSK.
Warning
0-RTT replay attack risk: Because the 0-RTT data is sent before the handshake completes, there's no anti-replay protection from the TLS protocol itself. An attacker who captures the initial packet can replay it. Servers MUST only accept 0-RTT for idempotent requests (GET, HEAD). Non-idempotent operations (POST, PUT) must wait for the full handshake. Many servers disable 0-RTT entirely because of this.
Cipher Suites
A cipher suite defines the algorithms used for the TLS session. TLS 1.3 dramatically simplified the cipher suite structure compared to TLS 1.2.
Anatomy of a TLS 1.3 Cipher Suite
TLS_AES_256_GCM_SHA384
│ │ │ │
│ │ │ └── Hash algorithm: SHA-384 (for HKDF key derivation)
│ │ └──────── Mode: GCM (Galois/Counter Mode — AEAD)
│ └──────────────── Cipher: AES-256 (symmetric encryption)
└───────────────────── Protocol: TLSTLS 1.3 only supports 5 cipher suites, all using AEAD (Authenticated Encryption with Associated Data):
| Cipher Suite | AEAD Cipher | Hash | Notes |
|---|---|---|---|
TLS_AES_128_GCM_SHA256 |
AES-128-GCM | SHA-256 | Most common, good performance |
TLS_AES_256_GCM_SHA384 |
AES-256-GCM | SHA-384 | Higher security margin |
TLS_CHACHA20_POLY1305_SHA256 |
ChaCha20-Poly1305 | SHA-256 | Fast on CPUs without AES-NI (mobile) |
TLS_AES_128_CCM_SHA256 |
AES-128-CCM | SHA-256 | Counter with CBC-MAC, IoT use |
TLS_AES_128_CCM_8_SHA256 |
AES-128-CCM-8 | SHA-256 | Shorter auth tag, constrained devices |
Note
Key point: Notice that TLS 1.3 cipher suites do NOT specify the key exchange algorithm. That's because TLS 1.3 mandates ephemeral key exchange (ECDHE or DHE) — it's not negotiable. In TLS 1.2, the cipher suite included the key exchange (e.g., TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384), and you could negotiate static RSA key exchange (no forward secrecy).
What TLS 1.3 Removed
Removed in TLS 1.3 (security improvements)
| Removed | Why |
|---|---|
| RSA key exchange | No forward secrecy — if the server's private key is compromised later, all past sessions can be decrypted |
| Static DH | Same problem — no forward secrecy without ephemeral keys |
| CBC mode ciphers | Vulnerable to padding oracle attacks (BEAST, POODLE, Lucky 13) |
| RC4 | Broken — statistical biases in keystream allow plaintext recovery |
| MD5, SHA-1 | Collision attacks practical (SHA-1 collision demonstrated by Google in 2017) |
| Compression | CRIME/BREACH attacks — compression leaks information about plaintext |
| Renegotiation | Complex, historically buggy, source of vulnerabilities |
| ChangeCipherSpec | Entire message type removed — unnecessary in 1.3's cleaner design |
Certificates (X.509)
Certificates are how TLS achieves authentication. The server presents a certificate that cryptographically binds a public key to an identity (domain name). The client verifies this certificate against a trusted set of Certificate Authorities (CAs).
X.509 Certificate Structure
Tip
Ops tip: The Subject CN (Common Name) is deprecated for hostname matching. Modern certificates use the SAN (Subject Alternative Name) extension, which supports multiple domains and wildcards: DNS:example.com, DNS:*.example.com, DNS:api.example.com.
Certificate Chain of Trust
End-Entity Cert
Your domain cert
(e.g., api.example.com)
Signed by Intermediate CAIntermediate CA
Issued by Root CA
Signs end-entity certs
Signed by Root CARoot CA
Self-signed
Pre-installed in OS/browser
~150 root CAs in trust stores
Why Intermediate CAs Exist
Root CA private keys are kept offline in HSMs (Hardware Security Modules) in secure facilities. They are too valuable to risk exposure. Intermediate CAs are signed by root CAs but operate online to issue certificates. If an intermediate CA is compromised, it can be revoked without invalidating the root (which would break the entire trust chain for thousands of sites).
Certificate Validation Steps
- Chain building: Construct the chain from end-entity cert to a trusted root CA. The server should send all intermediate certs (the root is already in the trust store).
- Signature verification: For each cert in the chain, verify that the issuer's public key correctly signed the certificate.
- Validity period: Check that the current time is within the Not Before / Not After range for every cert in the chain.
- Revocation check: Verify the cert hasn't been revoked:
- CRL (Certificate Revocation List): Download a list of revoked serial numbers from the CA. Downside: lists can be large, and clients must fetch and cache them.
- OCSP (Online Certificate Status Protocol): Query the CA in real-time for a single cert's status. Downside: adds latency, privacy concern (CA sees what sites you visit).
- OCSP Stapling: The server fetches its own OCSP response and "staples" it to the TLS handshake. Best of both worlds — no extra round trip, no privacy leak.
- Hostname matching: Check that the requested hostname matches a SAN entry in the end-entity cert.
SNI (Server Name Indication)
Problem: a single IP address can host many TLS domains (like virtual hosts). The server needs to know which certificate to present before the TLS handshake completes. But without decrypting anything, the server doesn't know which domain the client wants.
Solution: SNI — the client includes the target hostname in the ClientHello message (which is sent in plaintext). The server uses this to select the correct certificate.
SNI in the TLS ClientHello
ClientHello
TLS Version: 1.3
Cipher Suites: [TLS_AES_256_GCM_SHA384, ...]
Extensions:
server_name (SNI): "api.example.com" ← sent in PLAINTEXT
supported_versions: [TLS 1.3]
key_share: [x25519: 0x...]
signature_algorithms: [ecdsa_secp256r1_sha256, ...]
alpn: [h2, http/1.1]Warning
Privacy concern: Because SNI is sent in cleartext, anyone on the network path (ISP, corporate firewall, surveillance systems) can see which domains you're connecting to, even though they can't see the content. This is how some censorship systems block specific sites. The solution is ECH (Encrypted Client Hello), which encrypts the entire ClientHello using a public key published in DNS. ECH is still being standardized and rolled out.
ALPN (Application-Layer Protocol Negotiation)
ALPN is a TLS extension that lets client and server negotiate which application protocol to use during the TLS handshake, avoiding an extra round trip after the handshake.
alpn: ["h2", "http/1.1"]"I support HTTP/2 and HTTP/1.1, in order of preference."
alpn: "h2""We'll use HTTP/2."
Note
Why this matters: Without ALPN, the client would have to complete the TLS handshake, then use the HTTP Upgrade mechanism to switch from HTTP/1.1 to HTTP/2 — adding another round trip. ALPN piggybacks on the TLS handshake, so protocol selection is free. This is also how HTTP/3 is discovered — the server advertises h3 support via the Alt-Svc header in an HTTP/2 response.
Certificate Transparency (CT)
Certificate Transparency is a system of public, append-only logs that record every certificate issued by participating CAs. It's designed to detect rogue or mistakenly issued certificates.
How CT Works
- CA submits cert to CT logs — Before (or shortly after) issuance, the CA submits the certificate to multiple independent CT log servers.
- Log returns SCT — The log returns a Signed Certificate Timestamp (SCT), which is a promise that the cert will appear in the log within a maximum merge delay (typically 24h).
- Server delivers SCTs — The server includes SCTs in the TLS handshake (via certificate extension, OCSP stapling, or TLS extension). Chrome requires at least 2 SCTs from different logs.
- Monitors watch logs — Domain owners, researchers, and automated systems continuously monitor CT logs for unexpected certificates issued for their domains.
Tip
Ops action: You can monitor CT logs for your domains using tools like crt.sh or Google's CT search. If you see a certificate for your domain that you didn't request, it could indicate a CA compromise or a domain validation failure. Many organizations set up automated CT monitoring alerts.
Key Exchange: ECDHE and Forward Secrecy
TLS 1.3 mandates ephemeral key exchange — both sides generate fresh, temporary key pairs for every connection. The dominant algorithm is ECDHE (Elliptic Curve Diffie-Hellman Ephemeral).
How ECDHE Works (Conceptual)
ECDHE Key Exchange Steps
- Both sides agree on an elliptic curve (e.g., x25519 or P-256).
- Client generates a random ephemeral private key and computes the corresponding public key on the curve. Sends the public key in ClientHello.
- Server does the same — generates its own ephemeral key pair. Sends its public key in ServerHello.
- Both sides compute the same shared secret using their private key + the other's public key. This is the ECDH math:
shared_secret = client_private * server_public = server_private * client_public. - The shared secret is fed into HKDF (HMAC-based Key Derivation Function) to derive the actual encryption keys, IVs, and MAC keys for the session.
Forward Secrecy
- Client encrypts the pre-master secret with the server's long-lived RSA public key
- If the server's private key is compromised years later, an attacker can decrypt all previously recorded sessions
- Passive eavesdropping + future key compromise = total exposure
- Fresh ephemeral keys for every session
- Ephemeral private keys are discarded after the session ends
- Compromising the server's long-lived key only affects authentication, not past encryption
- Each session's encryption key is independent
Warning
Critical: Forward secrecy is not optional in TLS 1.3 — it's mandatory by design. This is one of the most important security improvements over TLS 1.2, where RSA key exchange (no FS) was still allowed and commonly used.
Note
Common curves: x25519 (Curve25519, Daniel Bernstein's design — fast, constant-time, hard to misuse) is the most widely used. P-256 (secp256r1, NIST curve) is the other common choice. TLS 1.3 implementations typically support both. Post-quantum key exchange (ML-KEM/Kyber) is being deployed as a hybrid alongside x25519 to protect against future quantum computers.