TLS 1.3 Handshake and HTTPS Hardening
How TLS 1.3 achieves 1-RTT handshakes, enforces forward secrecy by design, and what production HTTPS hardening actually requires—from certificate chains and OCSP stapling to HSTS preload and 0-RTT replay risks.
Abstract
TLS 1.3 is a clean-slate redesign that mandates forward secrecy, removes legacy cryptographic baggage, and cuts handshake latency in half. The core insight: by restricting key exchange to ephemeral (EC)DHE and having clients speculatively send key shares in ClientHello, both parties can derive session keys after a single round-trip. Everything after ServerHello is encrypted—including certificates—and the only cipher suites allowed are AEAD (Authenticated Encryption with Associated Data) constructions.
HTTPS hardening extends beyond TLS configuration. HSTS (HTTP Strict Transport Security) prevents protocol downgrade attacks but has a first-visit vulnerability that only preload lists solve. Certificate Transparency makes misissued certificates publicly detectable. OCSP (Online Certificate Status Protocol) stapling was designed to fix revocation checking’s privacy and performance problems, but browsers soft-fail on OCSP errors anyway—rendering revocation checking largely theatrical. The industry has shifted toward short-lived certificates as the practical solution.
0-RTT resumption trades security for latency: early data can be replayed across connections, so it’s safe only for idempotent requests—and even then, information disclosure remains a risk.
TLS 1.3 Handshake: Why 1-RTT Is Possible
The Design Constraint That Changed Everything
TLS 1.2 required two round-trips because key exchange parameters were negotiated before key material was sent. The client proposed cipher suites, the server selected one, then the client generated key exchange values based on that selection. This sequential dependency forced an extra RTT.
TLS 1.3 eliminates this dependency through two design decisions:
- Restricted key exchange to (EC)DHE only—no RSA key transport, no static Diffie-Hellman
- Clients speculatively send key shares for likely curves in the initial ClientHello
Since the set of acceptable curves is small and well-known (X25519, P-256, P-384), clients can predict which the server will accept. If the prediction is wrong, the server sends a HelloRetryRequest—but this is rare in practice.
RFC 8446: “The client can simply choose to send DH key shares in the first message instead of waiting until the server has confirmed which key shares it is willing to support.”
Message Sequence: What Crosses the Wire
Phase 1: Key Exchange (Plaintext)
The ClientHello contains:
- Random 256-bit nonce
- Supported cipher suites (AEAD + hash pairs)
supported_versionsextension (must include 0x0304 for TLS 1.3)key_shareextension with (EC)DHE public values- Optional
pre_shared_keyfor resumption
The ServerHello responds with:
- Selected cipher suite
- Server’s (EC)DHE key share
supported_versionsconfirming TLS 1.3
At this point, both parties can compute the shared secret and derive handshake traffic keys.
Phase 2: Server Parameters (Encrypted)
EncryptedExtensions carries metadata that was plaintext in TLS 1.2:
- ALPN (Application-Layer Protocol Negotiation) selection
- Server name handling
- Other extensions not required for key exchange
This encryption protects metadata that reveals application behavior—which protocols are in use, which hostname was requested.
Phase 3: Authentication (Encrypted)
The Certificate message contains the server’s certificate chain. CertificateVerify proves private key ownership by signing the entire handshake transcript hash:
RFC 8446: “This message provides key confirmation, binds the endpoint’s identity to the exchanged keys.”
The Finished messages are HMAC-based MACs over the handshake transcript, confirming integrity and providing key confirmation.
What TLS 1.3 Removed (and Why)
| Removed Feature | Vulnerability | RFC 8446 Rationale |
|---|---|---|
| Static RSA key transport | No forward secrecy; passive attackers who later compromise the server key can decrypt historical traffic | ”All public-key based key exchange mechanisms now provide forward secrecy” |
| Static Diffie-Hellman | Same forward secrecy problem | Ephemeral keys required for all handshakes |
| Server-chosen DHE parameters | LogJam, WeakDH attacks using weak primes | Fixed named curves only (P-256, P-384, P-521, X25519, X448) |
| Compression | CRIME attack extracts secrets via compression ratio oracle | Removed entirely |
| Renegotiation | Downgrade attacks, injection vulnerabilities | ”Renegotiation is not possible when TLS 1.3 has been negotiated” |
| CBC mode ciphers | POODLE, Lucky Thirteen padding oracles | AEAD only |
| SHA-1 signatures | Collision attacks (SHAttered, 2017) | SHA-256 minimum |
| DSA | Performance, security concerns | ECDSA, EdDSA, RSA-PSS only |
Forward Secrecy: Non-Negotiable by Design
Why Ephemeral Keys Matter
In RSA key transport (TLS 1.2), the client encrypts the premaster secret with the server’s RSA public key. If an attacker:
- Records encrypted sessions today
- Compromises the server’s RSA private key years later
- Can decrypt all historical traffic
This is devastating against nation-state adversaries who archive encrypted traffic for later cryptanalysis.
TLS 1.3 mandates ephemeral (EC)DHE for every connection:
Session Key = HKDF( ECDHE_shared_secret, // Ephemeral - discarded after use handshake_transcript, // Binds to this specific connection context_labels // Domain separation)Both client and server generate fresh key pairs per connection. Even if the server’s certificate private key is later compromised, past session keys cannot be derived—the ephemeral private keys have been destroyed.
Key Schedule: Domain Separation
TLS 1.3 derives multiple independent keys from a single handshake using HKDF (HMAC-based Key Derivation Function) with different labels:
Each derived key is cryptographically independent. Compromising one doesn’t compromise others. This is why handshake encryption uses different keys than application data encryption.
Cipher Suites: AEAD Only
TLS 1.3 defines exactly five cipher suites, all using Authenticated Encryption with Associated Data (AEAD):
| Cipher Suite | Algorithm | Hash | Use Case |
|---|---|---|---|
| TLS_AES_128_GCM_SHA256 | AES-128-GCM | SHA-256 | Default, widely supported |
| TLS_AES_256_GCM_SHA384 | AES-256-GCM | SHA-384 | Higher security margin |
| TLS_CHACHA20_POLY1305_SHA256 | ChaCha20-Poly1305 | SHA-256 | Mobile, non-AES-NI hardware |
| TLS_AES_128_CCM_SHA256 | AES-128-CCM | SHA-256 | NIST compliance |
| TLS_AES_128_CCM_8_SHA256 | AES-128-CCM-8 | SHA-256 | IoT, constrained devices |
RFC 8446: “The list of supported symmetric encryption algorithms has been pruned of all algorithms that are considered legacy. Those that remain are all Authenticated Encryption with Associated Data (AEAD) algorithms.”
Cipher Suite Structure Change
TLS 1.2 cipher suites were monolithic, specifying everything in one identifier:
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256└─────┬────┘ └─┬─┘ └────┬────┘ └───┬──┘ Key Exch Auth Encryption MACTLS 1.3 splits negotiation into three independent selections:
- AEAD + Hash (cipher suite) — symmetric encryption
- Key Exchange — always (EC)DHE, negotiated via
supported_groups - Signature — RSA-PSS, ECDSA, EdDSA, negotiated via
signature_algorithms
This separation enables cleaner security analysis and simpler implementation.
Session Resumption: PSK and 0-RTT
How PSK Resumption Works
After a successful handshake, the server sends NewSessionTicket messages containing:
- ticket: Opaque blob (server-encrypted session state)
- ticket_lifetime: Maximum validity (up to 7 days)
- ticket_age_add: Random value to obscure ticket age
- early_data: Maximum size of 0-RTT data the server will accept
The client stores this and includes the PSK identity in subsequent ClientHello messages via the pre_shared_key extension.
PSK Binder: Cryptographic Binding
The PSK binder prevents attackers from replaying ClientHello messages with different PSKs:
binder = HMAC( binder_key, // Derived from PSK Transcript(ClientHello[:-binders]) // Everything except binders)The server validates the binder before accepting the PSK. This binds the PSK to the specific handshake transcript.
0-RTT Early Data: The Security Trade-off
0-RTT allows clients to send application data in the first flight, encrypted with keys derived only from the PSK. This data has weaker security properties:
RFC 8446: “The security properties for 0-RTT data are weaker than those for other kinds of TLS data. Specifically, this data is not forward secret, as it is encrypted solely under keys derived using the offered PSK.”
Critical vulnerability: 0-RTT data can be replayed.
Unlike regular TLS data (which incorporates the server’s random value), 0-RTT data depends only on:
- The PSK
- The client’s random value
An attacker who captures 0-RTT packets can replay them to the server. The server has no way to distinguish the replay from the original.
When 0-RTT Is Dangerous
Replay attack scenario:
- User sends
POST /transfer {"amount": 1000, "to": "attacker"}via 0-RTT - Attacker captures the encrypted ClientHello + early data
- Attacker replays it within the ticket age window (typically 10 seconds)
- Server processes the duplicate transfer
Even idempotent requests have risks:
- Information disclosure: Replaying GET requests reveals the target URL and response to attackers
- Side effects: Logging, rate limiting, cache updates still occur
- Timing attacks: Response time differences can leak information
Server-Side Protections
RFC 8446 suggests several anti-replay mechanisms:
- Single-use tickets: Mark tickets as consumed after first use
- Timestamp validation: Reject early data with implausible
obfuscated_ticket_age - ClientHello recording: Store unique identifiers and reject duplicates
RFC 8470 adds HTTP-level protections:
- Early-Data header: Signals to origin servers that replay is possible
- 425 Too Early: Servers reject requests they can’t safely process via 0-RTT
HTTP/1.1 425 Too EarlyContent-Type: text/plainThis request cannot be processed in 0-RTT mode.Please retry without early data.CDN behavior (Cloudflare, Akamai, AWS):
- Accept 0-RTT only for GET, HEAD, OPTIONS
- Reject state-changing methods (POST, PUT, DELETE)
- Add
CF-0RTT-Uniqueor similar headers for origin tracking - Implement short replay windows (shorter than ticket lifetime)
Forward Secrecy with PSK: (EC)DHE + PSK Mode
PSK-only mode lacks forward secrecy—if the PSK is compromised, all sessions using it can be decrypted.
PSK-(EC)DHE mode combines both:
- PSK provides authentication
- (EC)DHE provides forward secrecy
The session key depends on both the PSK and ephemeral (EC)DHE values. Compromising the PSK alone doesn’t allow decryption of past sessions.
HSTS: Preventing Protocol Downgrade
The Mechanism
HSTS (HTTP Strict Transport Security, RFC 6797) directs browsers to:
- Upgrade all HTTP requests to HTTPS automatically
- Refuse to proceed on certificate errors (no user override)
- Remember the policy for
max-ageseconds
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload| Directive | Purpose |
|---|---|
max-age |
Policy duration in seconds (2 years = 63072000) |
includeSubDomains |
Apply to all subdomains |
preload |
Signal intent for browser preload lists |
The First-Visit Vulnerability
HSTS has a bootstrap problem: browsers can’t know about a site’s policy until after the first visit. If an attacker intercepts that first connection (SSL stripping, protocol downgrade), the policy never reaches the browser.
Attack scenario:
- User types
example.com(no explicit https://) - Attacker intercepts the initial HTTP request
- Attacker establishes HTTPS to the real server
- Attacker serves HTTP to the user
- User never receives HSTS header
Preload Lists: The Solution
Browser preload lists (maintained by Google, shared across Chrome, Firefox, Safari, Edge) contain domains that must always use HTTPS—before any network request.
Submission requirements (hstspreload.org):
- Valid HTTPS on the apex domain
max-ageat least 31536000 (1 year)includeSubDomainsdirectivepreloaddirective- All subdomains must support HTTPS
Operational consideration: Once preloaded, removal takes months. Ensure all subdomains (including staging, internal tools) support HTTPS before submitting.
Certificate Transparency: Detecting Misissued Certificates
The Problem CT Solves
The PKI’s fundamental weakness: any trusted Certificate Authority (CA) can issue a certificate for any domain. A compromised or coerced CA can issue a certificate for google.com to an attacker.
CT (RFC 9162, replacing RFC 6962) makes all certificate issuance publicly auditable.
How CT Works
Components:
- CT Logs: Append-only Merkle trees of certificates
- SCTs (Signed Certificate Timestamps): Promises to include certificate within Maximum Merge Delay (24 hours)
- Monitors: Watch logs for certificates issued to specific domains
Browser enforcement (Chrome CT policy, current as of 2026-Q2):
- Embedded SCTs: 2 from distinct logs for certificates ≤180 days, 3 for longer-lived certificates.
- Across that set, at least 2 must come from distinct CT log operators — so a single operator running multiple logs cannot satisfy the requirement.
- SCTs can be delivered via:
- X.509 extension (embedded by the CA at issuance)
- TLS extension (
signed_certificate_timestamp) - OCSP response (deprecated path; Chrome 148 stops counting these on 2026-05-05)
Note
The “≥1 SCT from an RFC 6962 log” requirement is being retired: Chrome 144 (released January 2026) no longer enforces it locally, and from 2026-04-15 all Chrome clients are expected to accept SCTs sourced exclusively from static-ct-api logs.
What CT Doesn’t Do
CT is detective, not preventive. A misissued certificate can be used for up to 24 hours (the MMD) before appearing in logs. CT enables domain owners to discover misissued certificates—it doesn’t prevent their use.
OCSP and Revocation: The Uncomfortable Truth
Why Revocation Matters (In Theory)
When a certificate’s private key is compromised, revocation should invalidate it before expiration. Two mechanisms exist:
CRL (Certificate Revocation Lists):
- CA publishes list of revoked serial numbers
- Clients download and cache periodically
- Scales well, privacy-preserving
- Stale revocation data
OCSP (Online Certificate Status Protocol):
- Real-time status queries to CA
- Fresh revocation data
- Privacy concern: CA sees which sites you visit
- Reliability concern: OCSP responder becomes critical path
OCSP Stapling: The Attempted Fix
OCSP stapling (RFC 6066) lets servers fetch OCSP responses and bundle them with the TLS handshake:
Benefits:
- Privacy: CA doesn’t see which clients connect
- Performance: No extra RTT for OCSP
- Reliability: Server can cache responses
Why Browsers Soft-Fail
The critical design flaw: if OCSP fails (network error, timeout, stapled response missing), browsers proceed anyway.
Why soft-fail:
- OCSP responder outages would break the web
- Captive portals block OCSP
- Network latency adds user-visible delay
The security implication: An attacker who can MITM the connection can also block OCSP traffic. Soft-fail provides zero protection against active attackers.
“OCSP is not making anyone more secure. Browsers are either not checking it or implementing it in a way that provides no security benefits.” — Let’s Encrypt, December 2024
OCSP Must-Staple: The Failed Experiment
The OCSP Must-Staple certificate extension signals that connections without stapled OCSP responses should fail. This would convert soft-fail to hard-fail.
Why it failed:
- Unreliable server stapling implementations
- If stapled response expires, site goes down
- No major browser adopted enforcement
- Let’s Encrypt never supported it
The Industry Solution: Short-Lived Certificates
Rather than fixing revocation, the industry moved to certificates valid for days instead of years:
- 90-day certificates: Let’s Encrypt default
- Automated renewal: Certbot, ACME protocol
- Limited exposure: Compromised key is useful for short window
Let’s Encrypt shut down its OCSP responders on 2025-08-06, citing privacy risk and the fact that browser soft-fail makes revocation checking provide no real security benefit. New Let’s Encrypt certificates have not contained OCSP URLs since 2025-05-07.
CAA Records: Authorization Before Issuance
How CAA Works
CAA (Certification Authority Authorization, RFC 8659) DNS records specify which CAs may issue certificates for a domain:
example.com. CAA 0 issue "letsencrypt.org"example.com. CAA 0 issuewild "digicert.com"example.com. CAA 0 iodef "mailto:security@example.com"| Property | Purpose |
|---|---|
issue |
Authorize CA for standard certificates |
issuewild |
Authorize CA for wildcard certificates |
iodef |
Report unauthorized issuance attempts |
CA Compliance
The CA/Browser Forum Baseline Requirements mandate CAA checking before issuance. CAs must:
- Query CAA records for the requested domain
- Walk up the DNS hierarchy if no records found
- Refuse issuance if not authorized
Limitation: CAA is preventive only. It doesn’t invalidate already-issued certificates.
DNSSEC integration (March 2026)
Starting 2026-03-15, CA/Browser Forum Ballot SC-085v2 requires CAs to perform DNSSEC validation back to the IANA root for:
- Domain control verification (DCV)
- CAA record lookups
If a domain publishes DNSSEC and validation fails (SERVFAIL, BOGUS), the CA must refuse issuance — BOGUS cannot be treated as “no DNSSEC”. This closes the long-standing window where an attacker who could spoof DNS responses to the CA could also spoof CAA records and obtain a misissued certificate.
Important
DNSSEC remains opt-in for domain owners. The ballot only affects domains that already publish DNSSEC records. Unsigned domains see no change in CAA processing.
Encrypted ClientHello (ECH): Closing the SNI Leak
What still leaks in TLS 1.3
The handshake encrypts certificates and EncryptedExtensions, but the ClientHello itself is plaintext — including the server_name (SNI) extension, the ALPN list, and the offered key_share curves. A passive observer sitting between client and server learns the hostname being visited even though the rest of the session is private. This is the residual privacy gap that ESNI (Encrypted SNI) tried, and failed, to close cleanly.
How ECH works
Encrypted ClientHello (draft-ietf-tls-esni, currently at draft-25 in 2026) replaces ESNI with a two-part design:
- The server publishes an
HTTPSresource record in DNS containing an ECHConfig: an HPKE public key (RFC 9180) and a public name (a non-sensitive “outer” hostname for the front-end). - The client builds an inner ClientHello with the real SNI and sensitive extensions, encrypts it with HPKE under the published key, and embeds the ciphertext in an outer ClientHello that advertises only the public name.
- The server decrypts the inner ClientHello and completes the handshake against the real backend. A network observer sees only the public name.
Trust assumptions and operational reality
- DNS confidentiality is required. ECH only hides SNI from on-path observers if the
HTTPS/SVCBrecord is fetched over DNS-over-HTTPS or DNS-over-TLS. A plaintext DNS lookup leaks the hostname before the handshake even starts. - Anonymity-set size matters. ECH’s privacy benefit collapses if the public name fronts a single tenant. CDN-scale deployments (Cloudflare, Fastly) provide meaningful cover; a one-tenant origin does not.
- Key rotation must be online. Servers rotate ECHConfigs and serve a
retry_configsextension when a client uses a stale key, so the client can silently retry with the fresh config. - Deployment status (2026-Q2). Cloudflare has shipped ECH as a switchable setting since 2023; Firefox and Chrome enable ECH when DoH is on and a usable
HTTPSrecord is published. Middleboxes that perform SNI inspection break: enterprise networks frequently strip theencrypted_client_helloextension, falling back to plaintext SNI.
Caution
ECH is still an IETF draft and the wire format has shifted across revisions. Only deploy via a managed CDN or a TLS library that explicitly tracks the same draft version your clients negotiate; mismatched drafts cause hard handshake failures, not silent fallback.
Operational Hardening Checklist
TLS Configuration
- Enable TLS 1.3, disable TLS 1.0/1.1
- Prefer TLS_AES_128_GCM_SHA256, TLS_CHACHA20_POLY1305_SHA256
- Configure ECDHE curves: X25519, P-256
- Enable 0-RTT only for sites without state-changing GET requests
- Set session ticket lifetime ≤ 7 days
- Rotate session ticket encryption keys regularly
HTTPS Hardening
- Deploy HSTS with
max-age=63072000; includeSubDomains - Submit to HSTS preload after verifying all subdomains
- Enable OCSP stapling (even though browsers soft-fail)
- Configure CAA records authorizing only your CAs
- Monitor CT logs for unexpected certificates (crt.sh, Cert Spotter)
- Use short-lived certificates (90 days or less)
- Publish DNS
HTTPSrecords and enable ECH on CDN-fronted hostnames (with DoH/DoT in clients)
0-RTT Policy
- Accept 0-RTT only for idempotent methods (GET, HEAD, OPTIONS)
- Configure
Early-Dataheader forwarding to origin - Implement 425 responses for non-idempotent endpoints
- Consider disabling 0-RTT entirely for high-security applications
Certificate Management
- Automate certificate renewal (ACME/Certbot)
- Include full certificate chain (leaf + intermediates)
- Monitor certificate expiration
- Test certificate deployment with SSL Labs
Conclusion
TLS 1.3 represents a decade of lessons learned from attacks on TLS 1.2. The protocol eliminates legacy cryptographic modes, mandates forward secrecy, and reduces handshake latency—all through careful design constraints rather than optional best practices.
HTTPS hardening beyond TLS requires understanding what each mechanism actually provides:
- HSTS prevents downgrade but needs preload for first-visit protection
- Certificate Transparency enables detection but not prevention of misissued certificates
- OCSP stapling improves privacy and performance but browsers soft-fail anyway
- CAA prevents unauthorized issuance but doesn’t revoke existing certificates
- ECH closes the SNI leak only when DNS is also encrypted and the public name fronts a sufficiently large anonymity set
The uncomfortable truth: revocation checking has largely failed. Short-lived certificates and CT monitoring provide more practical security than OCSP ever did.
0-RTT offers real latency benefits but introduces replay risks that require application-level mitigation. For most sites, the trade-off isn’t worth it unless you’ve carefully analyzed which endpoints can safely accept replayed requests.
Appendix
Prerequisites
- TCP/IP fundamentals
- Public key cryptography basics (RSA, ECDH, signatures)
- X.509 certificate structure
- HTTP/1.1 and HTTP/2 understanding
Terminology
- AEAD: Authenticated Encryption with Associated Data—encryption providing confidentiality and integrity in a single operation
- (EC)DHE: Elliptic Curve Diffie-Hellman Ephemeral—key exchange generating fresh keys per session
- Forward Secrecy: Property where compromise of long-term keys doesn’t compromise past session keys
- HKDF: HMAC-based Key Derivation Function—derives multiple cryptographic keys from a single secret
- OCSP: Online Certificate Status Protocol—real-time certificate revocation checking
- PSK: Pre-Shared Key—symmetric key established in a previous session for resumption
- SCT: Signed Certificate Timestamp—proof of submission to a Certificate Transparency log
- STEK: Session Ticket Encryption Key—server key used to encrypt session tickets
Summary
- TLS 1.3 achieves 1-RTT handshakes by having clients speculatively send (EC)DHE key shares
- Forward secrecy is mandatory—no cipher suites without ephemeral key exchange exist
- Everything after ServerHello is encrypted, including certificates and metadata
- 0-RTT early data trades security (replayable) for latency; safe only for idempotent requests
- HSTS prevents protocol downgrade but preload is required for first-visit protection
- Certificate Transparency detects misissued certificates post-facto; doesn’t prevent use
- Browser OCSP soft-fail means revocation checking provides no security against active attackers
- Short-lived certificates are the industry’s practical answer to revocation’s failure
- ECH (draft) hides SNI from on-path observers, but only when DNS is encrypted and the public name fronts a meaningful anonymity set
References
- RFC 8446 - The Transport Layer Security (TLS) Protocol Version 1.3 — Authoritative TLS 1.3 specification
- RFC 8470 - Using Early Data in HTTP — HTTP integration for 0-RTT, Early-Data header, 425 status code
- RFC 6797 - HTTP Strict Transport Security (HSTS) — HSTS specification
- RFC 9162 - Certificate Transparency Version 2.0 — Current CT specification (replaces RFC 6962)
- RFC 8659 - DNS Certification Authority Authorization (CAA) Resource Record — CAA record specification
- RFC 6066 - Transport Layer Security (TLS) Extensions — OCSP stapling (status_request extension)
- RFC 6961 - TLS Multiple Certificate Status Request Extension — status_request_v2 for multiple OCSP responses
- RFC 8740 - Using TLS 1.3 with HTTP/2 — Forbids
KeyUpdate-driven renegotiation patterns inside HTTP/2 connections - RFC 9180 - Hybrid Public Key Encryption (HPKE) — Construction ECH uses to encrypt the inner ClientHello
- draft-ietf-tls-esni - TLS Encrypted Client Hello — Current ECH draft
- HSTS Preload Submission — Browser preload list submission portal
- Cloudflare: A Detailed Look at RFC 8446 — Practical TLS 1.3 deployment insights
- Cloudflare: Introducing 0-RTT — 0-RTT implementation and replay protection
- Let’s Encrypt: Ending OCSP Support — Industry rationale for abandoning OCSP
- Trail of Bits: What Developers Need to Know About TLS Early Data — Application-level 0-RTT security guidance