TLS and HTTPS in Depth: Handshakes, Certificates, SNI, ALPN, HSTS, and OCSP

18 min read

Part 1 of this series compressed the TLS handshake into a single step. That is fine for the map, but it hides the decisions behind many familiar failures: the certificate is for the wrong hostname, the intermediate is missing, a proxy and origin disagree about HTTPS, or a first request pays for a connection that later requests reuse.

This is Part 4 of the How the Web Works series. It covers the encryption and identity-verification layer that sits between DNS resolution (Part 3) and the HTTP request itself (Part 2).


Quick Answer

For a typical HTTPS connection, TLS authenticates the server using a certificate, negotiates cryptographic parameters, and protects later traffic with direction-specific keys derived during the handshake.

Client                                             Server
  |                                                   |
  |  ClientHello + key share + SNI + ALPN             |
  |-------------------------------------------------->|
  |                                                   |
  |  ServerHello + key share                          |
  |  {EncryptedExtensions, Certificate,               |
  |   CertificateVerify, Finished}                    |
  |<--------------------------------------------------|
  |                                                   |
  |  Client verifies the chain and handshake signature|
  |  {Finished}                                       |
  |-------------------------------------------------->|
  |                                                   |
  |  [Encrypted HTTP application data]                |

Braces represent handshake messages encrypted after ServerHello; brackets represent application data protected with application traffic keys.

Certificate chains, SNI, ALPN, cipher suites, HSTS, and OCSP all support those two jobs: identity and encryption against an attacker sitting on the network.


Why TLS Exists

Without TLS, HTTP traffic is plain text on the wire. Anyone with access to the network path, such as a coffee shop wifi operator, an ISP, or a compromised router, can read every request and response. They can also modify them in transit without either side noticing. TLS provides confidentiality, integrity, and authenticity, which means you are talking to the real server rather than an impostor.

That third property is why certificates exist. Encryption alone does not help if you encrypt a channel straight to an attacker who set up a convincing fake server. This is a man-in-the-middle attack, and the certificate chain is designed to prevent it.


The TLS Handshake Step by Step (TLS 1.3)

TLS 1.3 is the latest standardized TLS version and normally establishes a new certificate-authenticated connection in one network round trip, compared with two for the common TLS 1.2 full-handshake flow. Resumption and exceptional paths can differ.

Step 1: ClientHello

The browser sends a ClientHello containing supported TLS versions, TLS 1.3 cipher suites, signature algorithms, supported groups, a random value, and usually the requested hostname via SNI. It commonly includes one or more key shares so the server can select a compatible group without an extra round trip; otherwise the server can send HelloRetryRequest.

Step 2: ServerHello and encrypted server handshake

The server sends ServerHello with the selected TLS version, cipher suite, and key share. ClientHello plus ServerHello establishes handshake secrets. Every following handshake message is encrypted: EncryptedExtensions, the certificate chain, CertificateVerify (proof that the server controls the certificate's private key), and Finished (key confirmation and transcript integrity).

Step 3: The client verifies the certificate

The browser checks:

  • Does the certificate's domain match the one being requested?
  • Is the certificate signed by a chain leading to a trusted root CA?
  • Is the certificate currently within its validity period?
  • Is the certificate chain and handshake signature cryptographically valid?
  • Has local/browser trust policy marked the certificate or issuer as untrusted, and is relevant revocation information available?

A fatal validation failure prevents normal HTTPS application data from being exchanged. Browsers may present an interstitial for some errors; HSTS and other policies can remove the option to bypass it. Revocation checking behavior varies by client and is not always a blocking live OCSP lookup.

Step 4: Both sides derive traffic secrets

In the normal certificate-based TLS 1.3 web handshake, ephemeral (EC)DHE key shares let both sides compute the same shared secret without transmitting it. TLS derives separate handshake and application traffic secrets, including separate keys for each direction. The certificate private key signs the handshake; it does not encrypt the HTTP session.

Step 5: Encrypted application data begins

After the client validates the server flight and sends its own Finished, it can send ordinary application data. A full TLS 1.3 handshake normally permits client application data after one round trip; common TLS 1.2 full handshakes require two. Resumed TLS 1.3 connections can optionally use 0-RTT early data, which has weaker replay guarantees.

TLS 1.2 full handshake: usually 2 RTTs before client application data
TLS 1.3 full handshake: usually 1 RTT before client application data
TLS 1.3 resumed 0-RTT: early data may be sent immediately, with replay caveats

That saved round trip is measurable on high-latency connections, especially mobile networks. This is one reason TLS 1.3 adoption mattered for web performance, not just security.


Certificates: What a CA Actually Signs

A TLS certificate is, at its core, a statement: "This public key belongs to this domain," cryptographically signed by a Certificate Authority (CA) that the browser already trusts.

Certificate contents (simplified):
  Subject:        suriyaprakash.in
  Public key:     <the server's public key>
  Issuer:         Let's Encrypt Authority
  Valid from:     2026-06-01
  Valid until:    2026-08-30
  Signature:      <CA's cryptographic signature over all of the above>

The CA does not need your private key. For a domain-validated public certificate, it verifies control through an approved validation method, commonly a DNS or HTTP challenge, then signs a certificate that binds the public key to names listed in the certificate. Anyone can then verify the signature using the CA's already-trusted public key, without ever needing to contact the CA directly at verification time.

Domain Validation vs Organization Validation vs Extended Validation

TypeWhat's verifiedWhat it proves
DV (Domain Validated)Control over the domain onlyYou control the domain, not proof of who you are
OV (Organization Validated)Domain control + some organizational identity checksA registered organization requested this certificate
EV (Extended Validation)Rigorous legal/organizational verificationThe strongest identity assurance, though browsers no longer visually distinguish it the way they used to

Most certificates issued today, including certificates from Let's Encrypt, are DV. That is fine for encryption: DV, OV, and EV certificates can use the same TLS algorithms. The difference is identity assurance, not encryption strength.


Certificate Chains: Root, Intermediate, Leaf

Browsers do not ship with trust for every CA that issues certificates directly. They trust a set of root CAs, and most site certificates are signed by an intermediate CA that chains back to a root.

Root CA (in the browser's trust store, rarely used directly)
      ↓ signs
Intermediate CA (does the actual day-to-day issuing)
      ↓ signs
Leaf certificate (your domain's actual certificate)

This chain exists mainly for security hygiene: root CA private keys are kept offline and used as little as possible, since compromising one would be catastrophic (every certificate it ever signed would need distrusting). Intermediate keys are used far more often and can be rotated or revoked without touching the root.

A common certificate-chain bug is a server sending the leaf certificate without the required intermediate. Some browsers can recover from a cached intermediate or AIA fetching, while many TLS libraries do not fetch missing intermediates automatically. Different trust stores, SNI behavior, TLS versions, and enterprise interception can produce the same browser-versus-backend symptom, so inspect the served chain rather than assuming one cause.

# Check what a server is sending, including the chain
openssl s_client -connect suriyaprakash.in:443 -servername suriyaprakash.in -showcerts

SNI: How One IP Serves Many HTTPS Domains

Before SNI (Server Name Indication), hosting multiple HTTPS certificates on one IP was difficult. The TLS handshake had to pick which certificate to present before it knew which domain the client wanted, because that information used to arrive later inside the encrypted HTTP request.

SNI fixes this by including the requested domain name in the ClientHello itself, in plain text, before encryption begins:

ClientHello:
  ...
  server_name: suriyaprakash.in

This lets a single IP address, such as a CDN edge node or reverse proxy, host many unrelated HTTPS domains and present the right certificate based on the requested name.

Without ECH, the SNI extension in the outer ClientHello is visible to an on-path observer, even though later handshake messages and HTTP content are encrypted. Encrypted Client Hello (ECH) encrypts sensitive ClientHello content, including the real server name, when the client and deployment support it. IP addresses and traffic patterns can still reveal information.


ALPN: Negotiating HTTP/1.1 vs HTTP/2 vs HTTP/3

ALPN (Application-Layer Protocol Negotiation) lets peers select an application protocol inside the TLS handshake. Over TCP, browsers commonly offer values such as h2 and http/1.1. HTTP/3 uses an h3 ALPN identifier inside the TLS 1.3 handshake carried by QUIC rather than the TCP-based TLS connection.

ClientHello:
  ALPN: ["h2", "http/1.1"]
       ↓
ServerHello:
  ALPN: "h2"   ← server picks the best one it supports from the offered list

This avoids an extra round trip that would otherwise be needed to ask "do you support HTTP/2?" after the TLS connection was established. It is also why HTTP/2 effectively requires TLS in major browsers, even though the HTTP/2 spec technically allows an unencrypted variant. Browsers implemented ALPN-based negotiation, so the unencrypted path never became a practical web deployment model.


Cipher Suites and Why Some Get Deprecated

In TLS 1.3, a cipher suite such as TLS_AES_128_GCM_SHA256 selects the AEAD record-protection algorithm and the HKDF hash. Key-exchange groups and certificate signature algorithms are negotiated separately. Older TLS versions bundled more of those choices into the cipher-suite name.

Older cipher suites get deprecated for concrete, specific reasons, not just "because they're old":

Deprecated componentWhy
RC4Statistical biases in the keystream made it practically breakable
Static RSA key transportA later compromise of the RSA private key can expose recorded handshakes and their traffic keys
SHA-1 signaturesPractical collision attacks make SHA-1 unsuitable for modern certificate signatures and related security uses
TLS 1.0 / 1.1Obsolete protocol versions with legacy constructions and no support for modern TLS 1.3 protections

A common modern compatibility baseline is TLS 1.2 plus TLS 1.3, with TLS 1.3 preferred. For TLS 1.2, choose authenticated-encryption suites with ephemeral (EC)DHE; TLS 1.3 public-key handshakes removed static RSA and static Diffie-Hellman key exchange.


Perfect Forward Secrecy

Forward secrecy means that compromise of a server's long-term authentication key does not, by itself, reveal previously recorded sessions that used fresh ephemeral key exchange.

In a certificate-authenticated (EC)DHE handshake, ephemeral key shares produce the shared secret, while the certificate private key authenticates the transcript. Historical static RSA key transport worked differently: the client generated a premaster secret and encrypted it to the server's long-term RSA key, so a later private-key compromise could expose recorded handshakes.

Static RSA key transport:
  recorded encrypted premaster secret + later RSA private-key theft
  → past session keys may be recoverable

Ephemeral (EC)DHE:
  fresh per-connection key agreement
  → long-term certificate-key theft alone does not reveal past sessions

TLS 1.3 removed static RSA and static Diffie-Hellman public-key key exchange, so its ordinary certificate-based full handshakes provide forward secrecy. TLS 1.3 also supports PSK-only modes, and 0-RTT early data does not have the same forward-secrecy and replay properties as ordinary 1-RTT application data.


HSTS: Forcing HTTPS and Preventing Downgrade Attacks

Even with TLS available, a user typing example.com with no scheme or clicking an old http:// link can create a window where the first request goes out over plain HTTP. An attacker on the network can intercept that first request and keep the victim on HTTP, a downgrade attack.

HSTS (HTTP Strict Transport Security) closes this gap:

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

After a browser receives a valid HSTS policy over HTTPS, it upgrades matching HTTP URLs locally for the policy's max-age. includeSubDomains extends the policy to subdomains. The preload token expresses preload intent but does not enroll the domain by itself: the domain must also meet the browser preload program's requirements and be submitted to its maintained list. A preloaded entry can protect the first visit in browsers that ship that list.

The catch: HSTS preload is hard to reverse. Once a domain is in the browser-shipped preload list, removing it requires a request to the list maintainers and then waiting for that removal to ship through browser releases. If a subdomain cannot yet support HTTPS and gets caught by includeSubDomains, it can stay broken for a long time.


Certificate Revocation: CRL, OCSP, and OCSP Stapling

Certificates sometimes need to be invalidated before their expiry date. A private key compromise is the most urgent case. Two main mechanisms exist to check this:

  • CRL (Certificate Revocation List): the CA publishes signed revocation data that clients or vendors can download. Full lists can become large, so compressed or partitioned forms and browser-vendor mechanisms are also used.
  • OCSP (Online Certificate Status Protocol): a client can ask an OCSP responder about one certificate. A direct query can add latency and reveal the site being checked, but browsers do not necessarily perform a blocking live OCSP query for every connection.

OCSP stapling lets the server periodically fetch a signed OCSP response and include it in the handshake. A client that uses the staple can verify its signature and freshness without making its own per-connection OCSP request. Client revocation policy still varies, and the absence of a staple does not universally force a live lookup.

# Check whether OCSP stapling is enabled
openssl s_client -connect suriyaprakash.in:443 -servername suriyaprakash.in -status

Mixed Content and Why Browsers Block It

An HTTPS page that requests an HTTP subresource creates mixed content. Modern browsers block many executable or otherwise dangerous resource types. Some eligible image, audio, and video requests may first be auto-upgraded from http to https; if a secure fetch is not possible, behavior depends on the resource type and current browser rules. Do not rely on the older simple split between "active = blocked" and "passive = warned."

HTTPS document + HTTP script/style/iframe  → normally blocked
HTTPS document + eligible media/image      → may be auto-upgraded; otherwise may be blocked

A common cause is a hardcoded http:// URL left over from before a site migrated to HTTPS. Old embedded widgets, ad scripts, and CDN links are common places to find it.


Common SSL/TLS Errors in Production

ErrorLikely cause
NET::ERR_CERT_COMMON_NAME_INVALIDCertificate doesn't cover the domain/subdomain being requested
NET::ERR_CERT_DATE_INVALIDCertificate expired, or system clock is wrong
NET::ERR_CERT_AUTHORITY_INVALIDMissing intermediate certificate, or a self-signed cert not in the trust store
Chain works in browser, fails in curl/mobile appServer isn't sending the intermediate certificate, relying on browser-side AIA fetching that other clients don't do
"Mixed content" warningAn HTTP subresource is being loaded on an HTTPS page
Intermittent SSL handshake failuresLoad balancer nodes with inconsistent certificate/cipher configuration across the fleet
Handshake works but is unusually slowNetwork latency/loss, no resumption, expensive server work, a large chain, or client-specific revocation behavior

Practical Debugging Checklist

1. Inspect the actual certificate chain being served

openssl s_client -connect suriyaprakash.in:443 -servername suriyaprakash.in -showcerts

Confirm the leaf certificate, all intermediates, expiry dates, and the exact domain(s) covered.

2. Check expiry and validity explicitly

echo | openssl s_client -connect suriyaprakash.in:443 -servername suriyaprakash.in 2>/dev/null | openssl x509 -noout -dates

3. Confirm HSTS is being sent

curl -sI https://suriyaprakash.in | grep -i strict-transport-security

4. Confirm OCSP stapling is present

openssl s_client -connect suriyaprakash.in:443 -servername suriyaprakash.in -status 2>/dev/null | grep -A5 "OCSP Response"

5. Check which protocol/cipher was negotiated

openssl s_client -connect suriyaprakash.in:443 -servername suriyaprakash.in -tls1_3

6. If it works in the browser but fails elsewhere

Check the served intermediate chain first, but also compare hostname verification, SNI, trust stores, proxy interception, system time, and supported TLS versions. Browser and backend clients can differ on any of these.


What Actually Matters During a TLS Failure

The short explanation:

TLS encrypts traffic using certificates issued by trusted authorities.

During an incident, the useful questions are:

  • Why certificate-based TLS 1.3 normally derives traffic keys through ephemeral key exchange rather than encrypting them with the certificate key
  • Why missing intermediate certificates break non-browser clients specifically
  • What SNI leaks (the domain name, in plain text) and why ECH exists to close that gap
  • Why HSTS preload is powerful, requires separate list enrollment, and can be slow to reverse
  • The tradeoff OCSP stapling solves versus plain OCSP or CRLs

FAQ

What's the actual difference between TLS and SSL?

SSL is the deprecated predecessor to TLS. SSL 2.0 and 3.0 have known serious vulnerabilities and are no longer considered safe. "SSL certificate" persists as common terminology, but the protocol in use today is TLS, usually 1.2 or 1.3.

Does HTTPS hide which website I'm visiting?

Not entirely. Standard TLS sends the domain name in the clear via SNI during the handshake, so anyone observing the network traffic can often see which domain you connected to. Encryption protects request and response content, not necessarily the destination domain, unless Encrypted Client Hello (ECH) is in use and supported by both sides.

Why does a certificate work in Chrome but fail in my backend service?

A missing intermediate is a common cause, because some browsers recover using cached or AIA-fetched certificates while many TLS libraries do not. Also compare the clients' trust stores, hostname/SNI handling, TLS support, system clock, and enterprise proxy configuration.

What does perfect forward secrecy protect against?

For sessions that used authenticated ephemeral key exchange, stealing the long-term certificate key later does not by itself reveal previously recorded traffic. This statement does not apply unchanged to historical static RSA key transport, PSK-only modes, or TLS 1.3 0-RTT early data.

Can HSTS ever be a bad thing?

Yes. If includeSubDomains is applied before all subdomains support HTTPS, a misconfigured subdomain can break for an extended period. This is especially risky once the parent domain is preloaded into browsers.

What's the point of OCSP stapling if OCSP already exists?

Direct OCSP lets a client query a responder and can add latency or reveal the site being checked. Stapling shifts periodic retrieval to the server and allows supporting clients to verify a fresh signed status in the handshake. Browsers may also use cached responses or vendor-managed revocation data, so direct OCSP is not necessarily performed on every connection.

Why does HTTP/2 basically require HTTPS in practice?

Because HTTP/2 protocol negotiation in browsers is done via ALPN, a TLS extension. The specification technically allows unencrypted HTTP/2, but major browsers did not implement that path for normal web use.


Glossary

TermSimple meaning
TLS handshakeThe negotiation that verifies identity and establishes an encrypted channel
CertificateA signed statement binding a public key to a domain
Certificate chainLeaf → intermediate → root, each link signed by the one above it
SNIA handshake field revealing which domain the client wants, in plain text
ALPNNegotiates an application protocol inside TLS; HTTP/3 uses ALPN within QUIC's TLS handshake
Cipher suiteIn TLS 1.3, the AEAD record algorithm plus HKDF hash; key exchange and signatures are separate
Forward secrecyLong-term authentication-key theft alone does not reveal sessions that used fresh ephemeral key exchange
HSTSA header instructing supporting browsers to upgrade matching HTTP URLs while the policy is active
OCSP / OCSP staplingMechanisms for checking whether a certificate has been revoked
Mixed contentHTTP subresources loaded on an otherwise-HTTPS page

Final Mental Model

ClientHello offers versions, cipher suites, key shares, SNI, and ALPN
      ↓
ServerHello selects cryptographic parameters and establishes handshake keys
      ↓
Encrypted server messages carry parameters, certificate, proof, and Finished
      ↓
Client validates the chain and handshake, then sends Finished
      ↓
Direction-specific application traffic keys protect HTTP
      ↓
HSTS can force HTTPS while its policy is active; preload can cover the first visit
      ↓
An OCSP staple may provide fresh signed revocation status without a client lookup

With this model, "the SSL is broken" becomes a specific question: is this an expired certificate, a missing intermediate, an SNI mismatch, or a downgrade/mixed-content problem? Each has a different diagnostic.


About the author

Suriyaprakash Somu is a full-stack developer from Erode, Tamil Nadu, building production-ready business applications with React, Node.js, Fastify, PostgreSQL and MySQL. He focuses on Access Control, schema-based forms, and reliable backend workflows.