Transport Layer Security

πŸ”’ TLS / SSL Internals

TLS is the cryptographic backbone of the modern internet. It secures every HTTPS connection, every API call, every mTLS service mesh, and every VPN tunnel. TLS 1.3 (RFC 8446) is the current standard β€” a dramatic simplification of the protocol that cut handshake latency in half, removed every cipher suite that had ever been broken, and made forward secrecy mandatory. This guide covers the full picture: what TLS actually does, how the handshake works, how certificates chain together, what a cipher suite really means, and where TLS fits in the broader security landscape.

TLS 1.3
Current version
RFC 8446, Aug 2018
TLS 1.2
Predecessor
RFC 5246, 2008
1-RTT
Round trips (new)
down from 2-RTT
0-RTT
Round trips (resumed)
with PSK
Mandatory
Forward secrecy
ECDHE only
5 total
Cipher suites
all AEAD

What TLS Actually Does

TLS solves three distinct problems between a client and a server that have a raw TCP (or UDP/QUIC) connection:

πŸ”‘
Confidentiality

An eavesdropper on the wire sees only ciphertext. TLS uses symmetric encryption (AES-GCM, ChaCha20-Poly1305) with per-connection keys that an eavesdropper cannot decrypt without the session key. Even if the attacker records every packet and stores it for years, TLS 1.3 with forward secrecy ensures it's permanently unreadable.

Without confidentiality: passwords, session tokens, personal data, and API keys travel in cleartext and can be harvested by anyone on the path β€” coffee shop WiFi, corporate proxies, ISP-level surveillance, or state actors.

πŸ›‘οΈ
Integrity

TLS records include an authentication tag (from AEAD ciphers) that detects any tampering. An active attacker who modifies ciphertext β€” even flipping a single bit β€” causes authentication failure and the connection aborts. There's no way to forge a valid record without knowing the session key.

Without integrity: attackers can tamper with requests in transit (change a GET to a POST, modify a bank transfer amount). This is the "integrity" half of authenticated encryption.

βœ…
Authentication

The server proves its identity via a certificate chain rooted in a trusted Certificate Authority (CA). The client verifies the chain, checks the hostname, and confirms the server holds the corresponding private key (via a CertificateVerify signature). This prevents man-in-the-middle attacks where an adversary impersonates the server.

Without authentication: any on-path attacker can terminate the connection, present their own certificate, and the client has no way to know.

TLS does not provide availability β€” it's not a DDoS mitigation tool. It doesn't hide traffic metadata perfectly (record sizes, timing, and SNI are sometimes visible). And it doesn't protect application-layer data after the TLS session ends.

TLS vs. SSL β€” Why SSL Is Dead

TLS evolved from SSL (Secure Sockets Layer), which Netscape introduced in the mid-1990s. The naming stuck β€” browsers still show "SSL" in certificate details even when connections use TLS 1.2 or 1.3. Here's the lineage:

SSL 2.0
1995 β€” Insecure, broken. MD5 in signatures, MAC vulnerabilities, no forward secrecy. Never use.
SSL 3.0
1996 β€” Significantly better but still flawed. POODLE attack (2014) made it unusable. Disabled everywhere.
TLS 1.0
1999 β€” Essentially SSL 3.1. BEAST attack exploited CBC mode. Now deprecated (RFC 8996).
TLS 1.1
2006 β€” Added explicit IV for CBC mode. Better but still CBC-based. Deprecated 2020.
TLS 1.2
2008 β€” Adds AEAD support (AES-GCM), SHA-256 in signatures, removes MD5 in handshakes. The current minimum for most deployments. Still widely deployed.
TLS 1.3
2018 β€” Dramatically simplified: 1-RTT handshake, no RSA key exchange, no CBC modes, no renegotiation, mandatory forward secrecy. Current standard.

When someone says "SSL certificate," they mean an X.509 certificate used for TLS. The protocol is TLS; the cert format is X.509; the historical name is SSL. In practice, all modern "SSL" implementations use TLS 1.2 or 1.3.

Check your servers: SSL 3.0 and TLS 1.0/1.1 should be disabled on any public-facing service. TLS 1.2 should be the minimum; TLS 1.3 is the target. Use openssl s_client -tls1_3 to verify which versions your server accepts.

TLS 1.2 vs TLS 1.3: What's Actually Different

TLS 1.3 isn't just a version bump β€” it's a redesign. The committee removed roughly a dozen protocol features that had caused vulnerabilities, collapsed the handshake from two round trips to one, and introduced new primitives for session resumption. Here's every meaningful difference:

Aspect TLS 1.2 TLS 1.3
Round trips to app data 2 RTT (TCP + TLS) 1 RTT (TCP + TLS)
Resumption Session ID or ticket (1-RTT resumption) PSK ticket (1-RTT) or 0-RTT early data
Key exchange RSA key transport, DHE, ECDHE ECDHE only (forward secrecy mandatory)
Static RSA Allowed β€” no forward secrecy Removed
Cipher modes CBC, GCM, RC4, 3DES, many weak AEAD only (GCM, ChaCha20, CCM)
Cipher suites 300+ registered, many broken 5 total, all secure
Certificate visibility Sent in cleartext (privacy leak) Encrypted post-ServerHello
Renegotiation Yes β€” CVE-prone Removed
Compression Optional β€” CRIME attack Removed
MAC-then-encrypt Yes (CBC suites) No β€” encrypt-then-MAC only
Downgrade protection Weak (version fallback) Strong (sentinel bytes in ServerHello.random)
Key derivation PRF(SHA-256/SHA-384) HKDF (HMAC-based KDF)
TLS 1.2 (2-RTT)
RTT 1 ClientHello β†’ ← ServerHello, Certificate, ServerKeyExchange, ServerHelloDone
RTT 2 ClientKeyExchange, ChangeCipherSpec, Finished β†’ ← ChangeCipherSpec, Finished
App Data
TLS 1.3 (1-RTT)
RTT 1 ClientHello + key_share β†’ ← ServerHello + key_share, {Cert, CertVerify, Finished}
App Data + Finished β†’

Certificate Types: DV, OV, EV

Every TLS certificate encodes an identity β€” a hostname, an organization, or both. The validation method determines how trusted the certificate is, and the certificate type is determined by how rigorously the CA validated the request.

DV

Domain Validation

The CA verifies that the requester controls the domain. This is done by placing a random token in a DNS TXT record, serving a file at http://example.com/.well-known/acme-challenge/..., or responding to an email at the domain's WHOIS contact. DV certs can be issued in minutes, often automatically via ACME (Let's Encrypt).

What it proves: Someone with control over DNS for example.com` answered a challenge. It does not prove who that someone is.

Issuance time: Minutes
Cost: Free (Let's Encrypt) to ~$10/yr
Visually: Padlock only, no org name in cert
OV

Organization Validation

The CA verifies domain control and the identity of the organization: legal name, registration number, jurisdiction. This typically involves looking up the company in business registries, calling the phone number listed in directory services, or requiring an attorney letter. OV certs take 1–5 days to issue.

What it proves: The certificate belongs to a specific legal entity (e.g., "Acme Corp, Delaware, EIN 12-3456789") that controls the domain.

Issuance time: 1–5 days
Cost: ~$50–$200/yr
Visually: Padlock + org name in cert details
EV

Extended Validation

The most rigorous validation. The CA performs extensive checks: verifying legal identity against government registries, confirming physical address, requiring attestation from an authorized officer, checking for sanctions/blocklists. EV certs are issued to corporations and governments only. Chrome removed the EV certificate indicator (the green bar) in 2019, significantly reducing EV adoption.

What it proves: The certificate belongs to a specific, verified legal entity with high confidence. Used primarily by financial institutions and governments.

Issuance time: 1–2 weeks
Cost: ~$200–$1,000/yr
Visually: Historical green bar; now only visible in cert details
Wildcard certificates: A cert with CN=*.example.com or a SAN entry *.example.com covers any single-level subdomain (e.g., www.example.com, api.example.com), but does not cover example.com itself or multi-level subdomains (deep.page.example.com). Wildcard certs are DV-only β€” CAs won't issue OV or EV wildcards because validating the scope is impractical.

Certificate Chain Architecture

A TLS certificate chain is a signed linked list: the leaf server certificate is signed by an intermediate CA, which is signed by another intermediate or a root CA, which is either signed by a higher root or self-signed. The root is pre-installed in your browser's trust store.

Root CA (Trust Anchor)
DigiCert Global Root G2
Self-signed Β· Pre-installed in OS/browser trust store
Key: RSA 4096-bit Β· SHA-256
cA: TRUE Β· pathlen: unlimited
signs
Intermediate CA
DigiCert SHA2 Extended Validation Server CA
Signed by: Root CA
Key: RSA 2048-bit Β· SHA-256
cA: TRUE Β· pathlen: 0 (cannot issue further CAs)
signs
Leaf / Server Certificate
example.com
Signed by: Intermediate CA
Key: ECDSA P-256 Β· SAN: example.com, *.example.com
cA: FALSE Β· serverAuth + clientAuth
OCSP: http://ocsp.digicert.com

What the server sends

The server presents its leaf certificate and any intermediate certificates needed to reach a trust anchor. The root CA is not sent β€” it must already exist in the client's trust store. A typical TLS handshake carries 1–3 KB of certificates.

Certificate message contains:
  [0] Leaf:    example.com (ECDSA P-256)
  [1] Int:     DigiCert SHA2 EV Server CA (RSA 2048)
  [2] (Root: not sent)

What the client does

The client walks the chain: verifies the leaf signature against the intermediate's public key, then the intermediate's signature against the root's public key. It then checks hostname match, validity dates, key usage, revocation (via OCSP or CRL), and optionally Certificate Transparency logs.

1. Find issuer for each cert
2. Verify each signature up the chain
3. Check validity windows (notBefore/notAfter)
4. Verify hostname (SAN, not CN)
5. Check revocation status (OCSP/CRL)
6. Verify CT logs (SCTs embedded in cert)

Subject Alternative Names (SAN) and Virtual Hosting

A single TLS certificate can cover multiple hostnames. The Subject Alternative Name (SAN) extension in X.509 holds a list of DNS names, IP addresses, and other identifiers that the certificate is valid for. The Common Name (CN) field in the Subject DN is deprecated for hostname matching β€” always use SANs.

X.509 Subject Alternative Name extension (RFC 5280 Β§4.2.1.6):

extension: subjectAltName (2.5.29.17), critical
  dNSName: example.com
  dNSName: www.example.com
  dNSName: api.example.com
  dNSName: *.example.com
  dNSName: staging.example.com
  dNSName: localhost              # for local dev
  rfc822Name: [email protected]   # email certs (S/MIME)
  iPAddress: 192.0.2.1           # rarely used in TLS

# Wildcard matching rules:
#   *.example.com  matches  www.example.com, api.example.com
#   *.example.com  does NOT match  example.com, page.www.example.com
#   CN=foo matches only if no SAN entry exists (fallback)
SNI (Server Name Indication) is a TLS extension that tells the server which hostname the client wants before the certificate is selected. This is what makes virtual hosting work β€” a single IP can serve thousands of sites with different certs. The problem: SNI is visible in cleartext in ClientHello, letting network observers see which hostname you're connecting to even if the connection is encrypted. Encrypted ClientHello (ECH) is the fix β€” it encrypts the entire inner ClientHello, including SNI, using a public key published in DNS.

TLS and mTLS: One-Way vs. Mutual Authentication

Standard TLS authenticates the server to the client. The client verifies the server's certificate chain; the server proves it holds the private key via CertificateVerify. But TLS supports a bidirectional mode where the server also requests a certificate from the client β€” this is mTLS (mutual TLS).

Standard TLS
Client verifies server cert
⇉
Server has no client cert requirement
HTTPS for humans (browsers, mobile apps)
mTLS
Client verifies server cert
⇄
Server verifies client cert
Service-to-service, zero-trust, API keys

mTLS works by having the server send a CertificateRequest message in the TLS handshake. The client must present a certificate signed by a CA the server trusts. This is the identity primitive for service meshes (Istio, Linkerd, Consul Connect), API security, and zero-trust architectures where network position alone doesn't grant access.

How mTLS certificates differ: Unlike web server certs (which are often short-lived and automated via Let's Encrypt), mTLS client certificates often need explicit CA scoping β€” a server needs to trust only specific client CAs, not any publicly trusted CA. This means most mTLS deployments use private CAs (internal PKI, SPIFFE/SPIRE) rather than public CA certs.

TLS in the Protocol Stack

TLS sits between the transport layer (TCP/UDP) and the application layer (HTTP, gRPC, SMTP, etc.). Understanding where TLS fits relative to these other protocols helps clarify what TLS does and doesn't protect.

Application Layer
HTTP/1.1, HTTP/2, gRPC, WebSocket, SMTP, XMPP, LDAP...
Protected by TLS: end-to-end payload is encrypted
⬇ TLS encrypts this boundary ⬇
TLS 1.3
Record Protocol Β· Handshake Β· Alert Β· KeyUpdate
Authenticates server (and optionally client), derives session keys
⬇ TLS runs over this ⬇
Transport Layer
TCP Β· QUIC (UDP) Β· DTLS (datagram)
Reliable (TCP) or unreliable (DTLS) delivery; QUIC replaces TCP for HTTP/3
⬇ IP packet routing ⬇
Network / Internet Layer
IP Β· BGP Β· routing
TLS does not protect IP addresses (visible to routers)

Explore TLS Internals

Frequently Asked Questions

Is TLS 1.2 secure enough for production?

Yes, for most purposes. TLS 1.2 with ECDHE and a modern AEAD cipher suite (AES-GCM, ChaCha20-Poly1305) is considered secure as of 2025. The main reason to target TLS 1.3 is the 1-RTT latency improvement and the reduced attack surface (no renegotiation, no CBC modes, no static RSA). If you have clients that only support TLS 1.2 (very old embedded devices, some corporate proxies), TLS 1.2 with a strong cipher suite is acceptable. But TLS 1.2 configurations often drift toward weak cipher suites in practice β€” TLS 1.3 eliminates that risk by removing the weak options entirely.

What's the difference between a certificate and a key?

A key is a number (e.g., 32 random bytes for X25519). A certificate is a structured document (X.509 DER ASN.1) that binds a key to an identity. The certificate contains the public key, the subject (hostname or organization), the issuer (which CA signed it), a validity window, and extensions (SANs, key usage). The CA signs the certificate with its own private key. A client verifies the signature using the CA's public key (from the CA's own certificate).

Why do I see both RSA and ECDSA in TLS cipher suites?

The certificate contains a public key of a specific type (RSA, ECDSA P-256, or Ed25519). The TLS handshake signature (CertificateVerify) is made with the corresponding private key. In TLS 1.3, authentication is negotiated separately from the AEAD cipher β€” the signature_algorithms extension lists which signature types the client accepts; the server picks one that matches its certificate. So if a server has an ECDSA P-256 certificate, it will sign with ECDSA P-256; the cipher suite only specifies the data encryption (e.g., AES-128-GCM). This separation is new in TLS 1.3.

What's the chain length limit?

There's no hard protocol limit, but basicConstraints: cA: TRUE, pathlen: N on an intermediate caps how many additional CA levels can be signed below it. A pathlen of 0 means that intermediate cannot sign any further CA certificates β€” it can only sign leaf certs. This is how CAs limit chain depth. RFC 5280 recommends chains no deeper than 4 certificates; browsers typically enforce stricter limits. Deep chains (4+ hops) add latency and increase failure probability.

Can I use a self-signed certificate in production?

For public internet-facing services: no. Browsers and clients will reject self-signed certificates unless explicitly configured to trust them. For internal services, dev/test environments, and mTLS where both sides are configured in advance: yes. Self-signed certs are appropriate when you control both sides of the connection and can configure the client to trust the cert by thumbprint (HPKP-style) or by installing the CA cert in the trust store. Kubernetes ingress controllers often use self-signed certs internally with cert-manager managing the rotation.

Why does my cert show "Valid" but browsers say it's insecure?

A certificate's validity window is only one of ~15 checks a browser performs. Common reasons for "insecure" despite a valid cert: (1) the hostname doesn't match β€” the SANs don't include the hostname you're visiting; (2) the certificate chain is incomplete β€” the server didn't send intermediate certs; (3) revocation check failed hard (must-staple cert with no valid OCSP response); (4) the certificate was issued after the cert was revoked; (5) CT log checks failed in Chrome β€” the cert doesn't have sufficient SCTs for the browser's CT policy. Use openssl s_client -connect example.com:443 -showcerts and sslsabs.com to debug.

What's the relationship between TLS and Certificate Transparency (CT)?

Certificate Transparency (RFC 6962) is a logging infrastructure that requires CAs to publish every certificate they issue to publicly auditable CT logs. Each certificate includes Signed Certificate Timestamps (SCTs) β€” proofs that the certificate was logged. Browsers check CT logs to detect misissued certificates (CAs accidentally issuing certs for domains they don't control). Chrome requires EV certs to have at least 2 embedded SCTs; DV certs issued after April 2018 must also have SCTs. CT doesn't replace the CA trust model β€” it's an auditing layer on top of it. You can't validate a cert against CT logs yourself without downloading and checking against the log's Merkle tree, but you can view issued certs at crt.sh.