Every time you visit a website, send an API request, or receive a message, TLS (Transport Layer Security) is working silently in the background. The padlock icon in your browser's address bar is its visible signal — but the cryptography behind it involves a sophisticated combination of every primitive we've covered across this blog.
TLS is not a single algorithm. It is a protocol orchestration that combines symmetric encryption, asymmetric key exchange, digital signatures, hash functions, and message authentication into a single handshake that completes in milliseconds. Understanding how TLS works means understanding how all these pieces fit together — and why each one is indispensable.
This guide walks through the TLS 1.3 handshake step by step, maps each phase to the cryptographic primitive it relies on, compares TLS 1.2 and 1.3, and gives you practical configuration guidance.
A Brief History: From SSL to TLS 1.3
Year Version Key Milestone
1994 SSL 1.0 Netscape's first attempt (never publicly released)
1995 SSL 2.0 First public release; quickly found to have serious flaws
1996 SSL 3.0 Complete redesign; basis for all TLS versions
1999 TLS 1.0 IETF takes over; essentially SSL 3.1
2006 TLS 1.1 Added protection against CBC attacks
2008 TLS 1.2 SHA-2 cipher suites, AEAD modes, customizable PRFs
2018 TLS 1.3 1-RTT handshake, mandatory forward secrecy, removed all legacy algorithms
TLS 1.0 and 1.1 were deprecated by RFC 8996 in March 2021. TLS 1.2 remains widely used and is still considered secure when properly configured. TLS 1.3 is the current gold standard, supported by all major browsers and servers since 2018–2020.
The TLS Handshake: Phase by Phase
The TLS handshake is the process where two parties (typically a browser and a server) establish a secure connection. Think of it as a negotiation: "Here's what I can do" → "Here's what I think is best" → "Here's proof I am who I say I am" → "Let's start encrypting."
Phase 1: Client Hello (The Opening Bid)
The client initiates the connection by sending:
Protocol version — disguised as TLS 1.2 (0x0303) for middlebox compatibility, with the real version (TLS 1.3 = 0x0304) in the supported_versions extension
32 bytes of random data — the ClientRandom, used later in key derivation
Cipher suite list — in TLS 1.3, only three AEAD suites are defined:
TLS_AES_128_GCM_SHA256
TLS_AES_256_GCM_SHA384
TLS_CHACHA20_POLY1305_SHA256
Supported groups — elliptic curves for key exchange: X25519, P-256, P-384, P-521, X448, ffdhe2048–8192
Signature algorithms — ECDSA-P256-SHA256, Ed25519, RSA-PSS-SHA256, etc.
Key share — the client's ephemeral public key (e.g., an X25519 public key, 32 bytes)
SNI (Server Name Indication) — the hostname the client wants to reach
Crypto primitives involved: Random number generation for ClientRandom, elliptic curve math for the key share.
Phase 2: Server Hello (The Response)
The server replies with:
Selected cipher suite — one from the client's list (e.g., TLS_AES_256_GCM_SHA384)
32 bytes of ServerRandom
Key share — the server's ephemeral public key (same curve as the client's)
Supported version — confirms TLS 1.3
At this point, both sides have each other's ephemeral public keys. They can now compute a shared secret using elliptic curve Diffie-Hellman (ECDH).
Phase 3: Key Derivation (The Mathematical Magic)
This is where the real cryptography happens. Both client and server independently compute the same set of session keys — without ever transmitting them.
Step 1: Shared Secret via ECDH
Each side multiplies the other's public key by their own private key on the agreed elliptic curve. Due to the properties of elliptic curve multiplication, both arrive at the same 32-byte shared secret:
shared_secret = ECDH(client_private, server_public)
= ECDH(server_private, client_public)
This is the same math behind our ECC key generator and ECDH key exchange tool.
Step 2: HKDF Key Schedule
TLS 1.3 uses HKDF (HMAC-based Key Derivation Function, defined in RFC 5869) to derive all session keys from the shared secret. The process involves:
early_secret = HKDF-Extract(salt: 0, key: 0) — initial extraction
derived_secret = HKDF-Expand-Label(early_secret, "derived", empty_hash) — bridging to handshake
handshake_secret = HKDF-Extract(derived_secret, shared_secret) — core secret
client_hs_key = HKDF-Expand-Label(handshake_secret, "c hs traffic", hello_hash) — client handshake key
server_hs_key = HKDF-Expand-Label(handshake_secret, "s hs traffic", hello_hash) — server handshake key
The HKDF is built on top of HMAC — the same primitive we cover in our HMAC guide. Each expansion step uses HMAC-SHA256 or HMAC-SHA384 depending on the cipher suite.
Step 3: Application Traffic Keys
After the handshake is verified, new keys are derived for actual data encryption:
application_secret = HKDF-Expand-Label(handshake_secret, "c ap traffic" / "s ap traffic", ...)
client_app_key = HKDF-Expand-Label(application_secret, "key", ...)
client_app_iv = HKDF-Expand-Label(application_secret, "iv", ...)
These are the keys that encrypt your HTTP requests and responses.
Phase 4: Encrypted Handshake (Server Authentication)
From this point on, all remaining handshake messages are encrypted — a major improvement over TLS 1.2, where the server certificate was sent in the clear.
The server sends:
EncryptedExtensions — non-critical extensions (hidden from eavesdroppers)
Certificate — the server's X.509 certificate chain (the same PEM format our PEM certificate parser can decode)
CertificateVerify — a digital signature over the entire handshake transcript, proving the server possesses the private key corresponding to the certificate's public key
Finished — a MAC (message authentication code) over the entire handshake, ensuring no tampering occurred
The client verifies:
The certificate chain up to a trusted root CA
The CertificateVerify signature using the certificate's public key
The Finished MAC
Crypto primitives involved: Digital signatures (RSA-PSS or Ed25519/ECDSA), SHA hashing for the transcript hash, HMAC for the Finished MAC.
Phase 5: Client Authentication (Optional)
In most web browsing, only the server is authenticated. But in mutual TLS (mTLS), the client also sends a certificate and CertificateVerify. This is common in API-to-API communication, zero-trust architectures, and enterprise environments.
Phase 6: Application Data
The handshake is complete. Both sides now use the negotiated symmetric cipher (AES-256-GCM, AES-128-GCM, or ChaCha20-Poly1305) to encrypt all application data. Each record is independently encrypted with a unique nonce derived from the IV and a sequence number.
Where Each Crypto Primitive Fits
Here's the complete picture of how TLS combines every cryptographic primitive:
Phase Primitive TLS 1.3 Usage Our Tool
Client Hello Random generation ClientRandom (32 bytes) Random Bytes
Key Exchange Elliptic curve DH X25519 or P-256 key agreement ECC Key Gen / ECDH
Key Derivation HMAC / HKDF All key schedule operations HMAC Generator
Server Auth Digital signature CertificateVerify (RSA-PSS / Ed25519 / ECDSA) Digital Signature
Server Auth Hash function Transcript hash (SHA-256 / SHA-384) SHA Hash
Server Auth X.509 certificate Server identity proof CSR Generator / PEM Parser
Data Encryption AEAD cipher AES-256-GCM or ChaCha20-Poly1305 AES Encrypt
TLS is not a single algorithm — it is a symphony of every primitive we've discussed across this blog. If you understand AES, RSA, ECC, SHA, and HMAC individually, TLS is where they all come together.
TLS 1.2 vs TLS 1.3: What Changed
Feature TLS 1.2 (2008) TLS 1.3 (2018)
Handshake round trips 2-RTT (full) 1-RTT (full), 0-RTT (resumption)
Cipher suites 37+ (including RC4, 3DES, CBC) 3 (all AEAD)
Key exchange RSA, DH, ECDH, DHE, ECDHE ECDHE only (mandatory forward secrecy)
Handshake encryption Server cert sent in clear Entire handshake after ServerHello is encrypted
RSA key transport Supported Removed — breaks forward secrecy
CBC mode ciphers Supported Removed — vulnerable to padding oracle attacks
Compression Supported (vulnerable to CRIME) Removed
Renegotiation Supported (complex, risky) Removed
Static DH Supported Removed — no forward secrecy
Signature algorithms Negotiated implicitly Explicit signature_algorithms extension
PSK resumption Session IDs / tickets PSK with (EC)DHE or alone
The 1-RTT Handshake (TLS 1.3)
Client Server
─────────────────────────────────────────────────────
ClientHello (key_share + supported_groups)
──────────────────────────────────────────→
ServerHello (key_share)
{EncryptedExtensions}
{Certificate}
{CertificateVerify}
{Finished}
←──────────────────────────────────────────
{Client Finished}
──────────────────────────────────────────→
[Application Data] ←──────────────────────→ [Application Data]
Messages in {braces} are encrypted. The entire exchange after ServerHello is protected — an eavesdropper cannot see the server's certificate or what algorithms were actually used.
The 0-RTT Resumption
If the client has connected to the server before, it can send data in the very first message using a Pre-Shared Key (PSK) from the previous session:
Client Server
─────────────────────────────────────────────────────
ClientHello (key_share + PSK_identity + early_data)
[Early Application Data] ← sent immediately!
──────────────────────────────────────────→
ServerHello (PSK acceptance)
{EncryptedExtensions}
...
←──────────────────────────────────────────
Tradeoff: 0-RTT data is not forward secret — if the PSK is compromised, the early data can be decrypted. It is also vulnerable to replay attacks — an attacker can capture and retransmit the 0-RTT message. For this reason, 0-RTT is only safe for idempotent requests (GET, HEAD) and should never be used for state-changing operations like payments or password changes.
Forward Secrecy: Why It Matters
Forward secrecy (or perfect forward secrecy, PFS) means that compromising a long-term private key does not compromise past session keys.
In TLS 1.2 with static RSA key exchange, the server's RSA private key was used to decrypt the pre-master secret sent by the client. If an attacker recorded encrypted traffic and later obtained the server's RSA private key, they could decrypt all past sessions.
In TLS 1.3, all key exchange uses ephemeral ECDH. The server generates a fresh ECDH key pair for every single connection. Even if the server's long-term signing key is compromised, past sessions remain secure because the ephemeral ECDH private keys were discarded immediately after use.
Scenario Static RSA (TLS 1.2) Ephemeral ECDH (TLS 1.3)
Server private key leaked All past sessions decryptable Past sessions remain secure
Recording + later key compromise Traffic exposed Traffic safe
Per-session key independence No Yes
This is why TLS 1.3 removed static RSA and static DH entirely — they cannot provide forward secrecy by design.
Cipher Suites in Detail
TLS 1.3 defines exactly three cipher suites. Each is an AEAD (Authenticated Encryption with Associated Data) algorithm:
TLS_AES_128_GCM_SHA256
Encryption: AES-128 in GCM mode
Key size: 128 bits
Nonce size: 96 bits (12 bytes)
Authentication tag: 128 bits
Hash: SHA-256 (for HKDF and transcript)
Security level: 128-bit
Best for: General-purpose web traffic; hardware-accelerated on most modern CPUs (AES-NI)
TLS_AES_256_GCM_SHA384
Encryption: AES-256 in GCM mode
Key size: 256 bits
Nonce size: 96 bits
Authentication tag: 128 bits
Hash: SHA-384
Security level: 256-bit
Best for: High-security applications; slightly slower than AES-128-GCM without hardware acceleration
TLS_CHACHA20_POLY1305_SHA256
Encryption: ChaCha20 stream cipher
Key size: 256 bits
Nonce size: 96 bits
Authentication: Poly1305 MAC (128-bit tag)
Hash: SHA-256
Security level: 256-bit
Best for: Devices without AES hardware acceleration (mobile phones, ARM servers); resistant to cache-timing attacks that affect AES
All three provide authenticated encryption — meaning they simultaneously encrypt data for confidentiality and generate an authentication tag for integrity. This eliminates the need for a separate HMAC on the data (unlike TLS 1.2's CBC mode, which required encrypt-then-MAC or MAC-then-encrypt).
For a deep dive into the symmetric algorithms, see our guides on AES-256 encryption and understand how AES compares to ChaCha20 in performance and security characteristics.
Certificate Authentication: The Trust Chain
TLS 1.3 servers authenticate using X.509 certificates — the same certificates generated via our CSR generator and parseable by our PEM certificate parser.
The certificate chain works like this:
End-entity certificate — contains the server's public key and domain name, signed by a CA
Intermediate CA certificate(s) — signed by the root CA, used to limit root CA exposure
Root CA certificate — pre-installed in the client's trust store (browser or OS)
The client verifies:
Each certificate's signature using the issuer's public key
Validity dates and domain names
Revocation status (via OCSP or CRL)
Certificate Transparency (CT) logs for public trust
Certificate Types
Type Validation Trust Level Use Case
DV (Domain Validated) Domain ownership only Basic Blogs, personal sites
OV (Organization Validated) Business identity + domain Medium Business websites
EV (Extended Validation) Rigorous business verification Highest Banking, e-commerce
For more on how certificates are requested and signed, see our guide on Certificate Signing Requests.
Practical TLS Configuration
Server-Side Recommendations
For nginx:
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off; # Let the client choose
ssl_ecdh_curve X25519:secp256r1:secp384r1;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_stapling on;
ssl_stapling_verify on;
For Apache:
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305
SSLHonorCipherOrder off
What to Avoid
Deprecated / Dangerous Why
TLS 1.0 / 1.1 No AEAD, vulnerable to BEAST, POODLE, Lucky13
RSA key exchange No forward secrecy
CBC mode ciphers Padding oracle vulnerabilities
RC4, 3DES, DES Known cryptographic weaknesses
SHA-1 for signatures Collision attacks demonstrated
Export-grade ciphers Intentionally weak (FREAK, Logjam)
Compression CRIME / BREACH attacks
Testing Your Configuration
SSL Labs Server Test — comprehensive grade (A+ to F) for your TLS setup
testssl.sh — command-line tool that checks for vulnerabilities and misconfigurations
cryptcheck.fr — quick grade-based assessment
TLS Beyond HTTPS
While HTTPS is the most visible use case, TLS also protects:
Protocol Over TLS? Description
HTTPS Yes (port 443) Web browsing
SMTPS Yes (port 465/587) Email submission
IMAPS Yes (port 993) Email retrieval
FTPS Yes (port 990) File transfer
MQTTS Yes (port 8883) IoT messaging
DNS over TLS Yes (port 853) Encrypted DNS resolution
DNS over HTTPS Yes (port 443) DNS within HTTPS
XMPP Optional Instant messaging
IRC Optional (port 6697) Chat
Quantum Threats to TLS
Current TLS 1.3 relies on two quantum-vulnerable primitives:
ECDH key exchange — Shor's algorithm on a sufficiently large quantum computer could compute the shared secret from the exchanged public keys
RSA/ECDSA signatures — Shor's algorithm could forge CertificateVerify signatures
Post-quantum TLS is being actively standardized:
ML-KEM (Kyber) for key exchange — replaces or supplements ECDH
ML-DSA (Dilithium) or SLH-DSA (SPHINCS+) for signatures — replaces RSA/ECDSA
Hybrid modes (e.g., X25519 + ML-KEM-768) provide dual security: even if one algorithm is broken, the other still protects the session
Major browsers (Chrome, Firefox) have already experimented with hybrid key exchange using X25519 + Kyber (now ML-KEM). See our Post-Quantum Cryptography guide for the full picture.
Troubleshooting Checklist
If your TLS connection is failing or showing warnings:
Certificate expired — check notAfter date in the server certificate
Wrong hostname — certificate CN/SAN must match the requested domain
Incomplete chain — server must send intermediate certificates (not just the leaf)
Protocol mismatch — client requires TLS 1.3 but server only supports TLS 1.2
Cipher suite mismatch — no common cipher suite between client and server
Revoked certificate — check OCSP stapling or CRL distribution
Self-signed certificate — client must explicitly trust the certificate or its CA
HSTS preload — if the domain is in the HSTS preload list, HTTP will be rejected
Frequently Asked Questions
What is the difference between TLS and SSL?
TLS (Transport Layer Security) is the successor to SSL (Secure Sockets Layer). SSL was the original protocol developed by Netscape in the 1990s. When the IETF standardized it, they renamed it TLS. TLS 1.0 was essentially SSL 3.1. All modern implementations use TLS — SSL 2.0 and 3.0 are deprecated and insecure. When people say "SSL certificate," they actually mean a TLS certificate.
Does TLS use symmetric or asymmetric encryption?
Both. TLS uses asymmetric encryption (ECDH + digital signatures) during the handshake to securely exchange keys and authenticate identities. Then it switches to symmetric encryption (AES-GCM or ChaCha20-Poly1305) for the actual data transfer, because symmetric encryption is roughly 100–1000x faster for bulk data. This hybrid design gives you the best of both worlds: the key distribution advantages of asymmetric crypto and the performance of symmetric crypto.
What is forward secrecy and why does TLS 1.3 require it?
Forward secrecy means that even if a long-term private key is compromised in the future, past session keys remain secure. TLS 1.3 achieves this by using ephemeral ECDH for every connection — the server generates a fresh key pair each time and discards the private key after the session. This prevents an attacker who records encrypted traffic from decrypting it later, even if they obtain the server's certificate private key.
What is 0-RTT and is it safe?
0-RTT (Zero Round-Trip Time) allows a returning client to send data in the very first message using a pre-shared key from a previous session. It reduces latency but comes with two caveats: (1) 0-RTT data is not forward secret, and (2) it is vulnerable to replay attacks — an attacker can capture and retransmit the 0-RTT message. Use 0-RTT only for idempotent requests like GET.
Which cipher suite should I prefer?
For most use cases, TLS_AES_256_GCM_SHA384 provides the strongest security. On mobile devices or CPUs without AES hardware acceleration, TLS_CHACHA20_POLY1305_SHA256 may be faster while still providing 256-bit security. TLS_AES_128_GCM_SHA256 is perfectly adequate for general web traffic and is the most commonly negotiated suite.
Can TLS 1.3 be broken by quantum computers?
Not yet — but a large enough quantum computer running Shor's algorithm could break the ECDH key exchange and RSA/ECDSA signatures that TLS 1.3 relies on. The solution is post-quantum TLS using algorithms like ML-KEM (Kyber) for key exchange and ML-DSA (Dilithium) for signatures. Hybrid modes combining classical and post-quantum algorithms are already being tested in Chrome and Firefox.
Further Reading
RFC 8446 — The Transport Layer Security (TLS) Protocol Version 1.3 — The definitive specification
RFC 8996 — Deprecating TLS 1.0 and TLS 1.1 — Official deprecation of legacy versions
RFC 5869 — HMAC-based Extract-and-Expand Key Derivation Function (HKDF) — The key derivation mechanism used by TLS 1.3
The Illustrated TLS 1.3 Connection — Byte-by-byte walkthrough of every handshake message
SSL Labs — TLS Deployment Best Practices — Mozilla's recommended configurations
NIST SP 800-52 Rev. 2 — Guidelines for TLS Implementations — U.S. government TLS requirements
CA/Browser Forum — Baseline Requirements — Certificate issuance standards
ACME Protocol (RFC 8555) — Automated Certificate Management (Let's Encrypt)
Related Articles
AES-256 Encryption — The symmetric cipher that encrypts most TLS 1.3 data traffic
Elliptic Curve Cryptography (ECC) — The math behind ECDH key exchange and ECDSA signatures in TLS
RSA-2048 Encryption — Still used in some TLS certificate signatures, though being phased out
How Digital Signatures Work — The CertificateVerify message that proves server identity
HMAC Message Authentication — The building block of HKDF, which derives all TLS session keys
Post-Quantum Cryptography — The future of TLS in a quantum computing world
