# HTTPS / TLS, Explained

> What the padlock in your browser actually means: how TLS adds encryption, integrity, and server authentication on top of plain HTTP, how the handshake agrees on a key, and how certificates and Certificate Authorities decide who to trust.


---

# HTTPS / TLS, Explained

You've seen the little padlock in the address bar a thousand times. Maybe someone told you it means "the site is safe," and you half-believed them. Then one day a page threw a full-screen red warning about a certificate, and you had to decide - on the spot - whether to click through or back away. That's exactly where this guide helps. By the end, you'll know what the padlock *actually* promises (and the dangerous thing it does **not** promise), how your browser and a server agree on a secret without ever mailing it to each other, and how to read a certificate error calmly instead of guessing.

This is an intermediate guide - it assumes you know roughly what HTTP is (a browser asking a server for a page). If that's fuzzy, read [HTTP Explained](/guides/http-explained) first, then come back.

## How to read this
- **Want the one idea to carry around?** Read [Phase 1: What HTTPS Protects (and Doesn't)](01-what-https-protects.md). It installs the mental model that fixes the most common and most dangerous misunderstanding about the padlock.
- **Want it to truly click?** Read all three in order. Phase 2 shows *how* the secret gets agreed on, and Phase 3 shows *who* decides the server is who it claims to be - each answers a question the last one opened.

## The phases
1. **[What HTTPS Protects (and Doesn't)](01-what-https-protects.md)** - TLS adds three things to HTTP: *encryption* (eavesdroppers can't read it), *integrity* (nobody can tamper with it undetected), and *authentication* (you're talking to the real server). And the big gotcha: the padlock means "encrypted to whoever holds the certificate," **not** "this site is trustworthy."
2. **[The Handshake & Keys](02-the-handshake-and-keys.md)** - how two strangers agree on a shared secret over an open wire. The trick: slow *asymmetric* keys to bootstrap, then fast *symmetric* encryption for the actual data. An annotated ASCII handshake.
3. **[Certificates & Trust](03-certificates-and-trust.md)** - a *certificate* binds a domain to a public key, signed by a *Certificate Authority* your browser already trusts. The chain of trust, why Let's Encrypt changed everything, and how to read "expired," "name mismatch," and "self-signed" errors without panic.

> This guide deliberately stays at "what is happening, and why." The exact byte-level mechanics of TLS 1.3, cipher suites, and certificate revocation live in deeper material; the difference between proving *who you are* and proving *what you're allowed to do* lives in [Authentication vs. Authorization](/guides/auth-vs-authz). Read this guide first - then those, when you want to go deeper.


---

# What HTTPS Protects (and Doesn't)

Picture sending a postcard through the mail. Anyone who handles it - the mail carrier, the sorting office, a nosy neighbor - can read every word, and a determined one could erase a line and write their own before passing it along. Plain **HTTP** is that postcard: every page you load, every password you type, every form you submit travels as readable text through a dozen machines you don't control - your router, your internet provider, the coffee-shop Wi-Fi, the backbone routers in between.

**HTTPS** is the same postcard, sealed in an opaque, tamper-evident envelope that only you and the intended recipient can open - and stamped in a way that proves who sealed it. The "S" stands for *secure*, and the security comes from a layer underneath called **TLS**. Let's make that concrete, because the whole guide rests on it.

📝 **TLS** (Transport Layer Security) is the protocol that does the actual securing. You'll also hear **SSL** - that's TLS's older name. SSL itself is obsolete and broken, but the word stuck around in habits and product names ("SSL certificate"). When someone says SSL today, they almost always mean TLS. We'll say TLS.

## The three things TLS actually gives you

HTTPS is just HTTP carried inside a TLS-protected connection. TLS adds exactly three guarantees. Hold onto these three words - *encryption, integrity, authentication* - and most of HTTPS follows.

```mermaid
flowchart TD
  http["Plain HTTP: your request<br/>(a postcard - readable by everyone in between)"] --> server1[server]
  req["HTTPS: your request"] --> tls[TLS envelope]
  tls --> server2[server]
  tls --> enc["ENCRYPTION<br/>nobody can read it"]
  tls --> integ["INTEGRITY<br/>nobody can change it"]
  tls --> authn["AUTHENTICATION<br/>you reached the real server"]
```

### 1. Encryption - eavesdroppers can't read it

**What it actually is.** The data is scrambled before it leaves your machine and only unscrambled at the other end. Anyone in the middle sees gibberish.

**What it does in real life.** On open coffee-shop Wi-Fi, the person two tables over running a packet sniffer can see *that* you're talking to your bank (the destination address isn't hidden), but not your username, password, or balance. With plain HTTP, they'd see all of it in clear text.

### 2. Integrity - nobody can tamper with it undetected

**What it actually is.** Each chunk of data carries a cryptographic seal. If even one byte is altered in transit, the seal no longer matches and the receiver rejects the message.

**What it does in real life.** A malicious Wi-Fi hotspot can't silently inject ads into the page you're reading, swap a download link for malware, or flip a "transfer $10" into "transfer $10,000." Any tampering breaks the seal, and your browser refuses the data rather than showing you something forged.

### 3. Authentication - you're talking to the real server

**What it actually is.** Before any data flows, the server proves it controls the domain you asked for, using a **certificate** (Phase 3). Your browser checks that proof.

**What it does in real life.** When you type `yourbank.com`, you can be confident the encrypted tunnel actually terminates at the real `yourbank.com` and not at an impostor who hijacked your connection. Without this, encryption alone would be useless - you might be perfectly, securely talking to a thief.

💡 **The key point:** encryption without authentication is a sealed envelope handed to a stranger. Authentication is what makes sure the envelope reaches the right hands. TLS does both, and that pairing is the whole point.

## The mental model - and the dangerous misread

Here is the single most important sentence in this guide:

> The padlock means **"this connection is encrypted, and the other end is whoever the certificate is for."** It does **not** mean "this website is safe, trustworthy, or run by good people."

⚠️ **The gotcha that gets people phished.** A scammer can register `paypaI-login.com` (that's a capital *I* dressed up to look like an *l*), get a free, perfectly valid certificate for it in minutes, and serve their fake login page over HTTPS. Your browser shows a padlock. Everything *is* encrypted - securely, all the way to the scammer's server. The padlock is telling the literal truth: your connection to this site is private. It has no opinion whatsoever about whether the site itself deserves your password.

This is why the old advice "look for the padlock to know it's safe" is not just incomplete - it's actively dangerous. The padlock answers "is this conversation private and reaching the named server?" It does not answer "is this the server I *meant*?" That second question is on you: read the actual domain name, character by character.

**Why people get this wrong.** Browsers used to show a big green bar with the company's legal name for expensive "Extended Validation" certificates, training a generation to equate the padlock with legitimacy. Browsers have since dropped most of that fanfare precisely because it gave false confidence - today, a padlock is the baseline for *every* site, good and bad.

🪖 **War story.** A teammate once approved a vendor invoice from a site that had a padlock and looked exactly like the vendor's portal - same logo, same layout. The domain was off by one hyphen. The padlock was real; the site was not. Encryption did its job flawlessly: it privately and reliably delivered his credentials to the attacker. The lesson stuck: *the padlock protects the pipe, not the destination.*

## What HTTPS does NOT do

To round out the model, here's what the padlock stays silent about:

- **It doesn't vouch for the site's trustworthiness.** Covered above. Read the domain.
- **It doesn't hide *who* you're talking to.** Observers can still see the destination domain and IP, just not the content. HTTPS gives you privacy of *contents*, not invisibility.
- **It doesn't protect data once it arrives.** TLS guards data *in transit*. Once it lands on the server, how that server stores and handles it is a separate problem entirely.
- **It doesn't fix a compromised endpoint.** If malware is running on your laptop, it reads your data before TLS ever encrypts it. TLS protects the wire, not the machines at each end.

## Why this saves you later

Once the model is right, two things get easier. You'll never be fooled by a padlock on a phishing page again - you'll instinctively read the domain instead. And when you build something, you'll know HTTPS is table stakes (it protects credentials and session tokens in transit - see [Authentication vs. Authorization](/guides/auth-vs-authz)) but *not* the finish line: you still owe your users clear-cut behavior and safe storage on the server side.

## Recap

1. Plain HTTP is a postcard - readable and editable by everyone in the path.
2. TLS wraps HTTP in three guarantees: **encryption** (can't read it), **integrity** (can't tamper undetected), **authentication** (you reached the real server).
3. SSL is the old, broken name for TLS; "SSL certificate" really means a TLS certificate.
4. The padlock means *encrypted to whoever holds the certificate* - **not** *this site is safe or trustworthy*.
5. A scammer can get a valid padlock for a lookalike domain in minutes. Read the domain name yourself.
6. HTTPS protects data **in transit only** - not the servers at the ends, not your own compromised laptop.


---

# The Handshake & Keys

Here's a puzzle that sounds impossible. Two computers that have never met, talking over a wire that anyone can listen to, need to agree on a secret password so they can scramble their conversation. But anything one sends, the eavesdropper hears too - so how do they whisper a secret in a crowded room where every word is shouted aloud?

The answer is one of the genuinely clever ideas in computing, and once it clicks, the rest of TLS makes sense. No math required - just the shapes of the ideas.

## Two kinds of locks

Everyday encryption you might imagine works like a house key: one key locks and unlocks the same lock. That's **symmetric encryption** - the same secret both scrambles and unscrambles the data. It's fast and it's what protects the bulk of your traffic. The catch is right there in the name: *both sides need the same secret first.* And we're back to the impossible puzzle - how do you share that secret over a wire everyone can hear?

📝 **Asymmetric encryption** (also called *public-key* cryptography) solves it with a different shape of lock: a **key pair**. The two keys are mathematically linked, but you can't derive one from the other.

- A **public key** that you hand out freely - print it on a billboard if you like.
- A **private key** that you guard and never share.

The trick: **anything locked with the public key can only be unlocked with the matching private key.** So anyone can lock a message for you using your public billboard key, but only you, holding the private key, can open it. The eavesdropper hearing the public key learns nothing useful - it only *locks*, it can't *unlock*.

```text
   SYMMETRIC (one shared key)            ASYMMETRIC (a matched pair)
   ────────────────────────             ───────────────────────────
        🔑  same key                       🔓 public key   →  locks
       /        \                          🔑 private key  →  unlocks
   lock          unlock                    (anyone can lock; only the
   (fast, but both sides                    private-key holder unlocks;
    must share the key first)               slow, but no shared secret needed)
```

## Why use both? The design decision

Asymmetric crypto sounds magical, so why not use it for everything? Because it's **slow** - far too slow to encrypt every byte of a video stream or a busy API. Symmetric crypto is **fast**, but needs a shared secret you can't safely send.

So TLS does the obvious smart thing: use each for what it's good at.

> Use **slow asymmetric** crypto *once*, at the start, to safely agree on a shared secret. Then switch to **fast symmetric** crypto, using that secret, for all the actual data.

That bootstrapping step - agree on a shared secret without ever sending it in the clear - is the heart of the **TLS handshake**. The shared secret it produces is called the **session key**.

💡 **The one idea to hold onto:** asymmetric crypto exists to *bootstrap* a fast symmetric key. It's the secure handshake before the fast conversation - not the conversation itself.

## The handshake, step by step

Here's the shape of what happens in the half-second before your page loads, slightly simplified to keep the idea clear. (Modern TLS 1.3 streamlines this and uses a key-agreement method where neither side ever transmits the secret at all - but the *roles* below are what matters for the mental model.)

```mermaid
sequenceDiagram
  participant You as You (browser)
  participant Server as Server (yourbank.com)
  You->>Server: 1. Hello - TLS versions & ciphers I can speak
  Server-->>You: 2. Hello - use this cipher, here's my certificate (+ public key)
  Note over You: 3. CHECK the certificate<br/>(right domain? trusted CA? not expired? - Phase 3)
  You->>Server: 4. Using the public key, both sides agree on a shared SESSION KEY
  Note over You,Server: 5. Everything from here is encrypted<br/>with the fast symmetric session key
```

*What just happened:* Steps 1–2 are introductions - agreeing on a common language and the server presenting its credentials. Step 3 is where authentication happens: you verify the certificate before trusting anything (the whole of Phase 3). Step 4 is the clever part - the public/private key pair lets both sides arrive at the *same* session key without that key ever crossing the wire in a form an eavesdropper could use. Step 5 is the payoff: a fast, symmetric, encrypted tunnel for the real conversation. Notice the asymmetric keys did their job in step 4 and then step aside.

⚠️ **The gotcha.** The handshake authenticates the *server* to *you* - that's the default and what protects normal browsing. It does **not** automatically prove *you* to the server; that's what your login (password, token, etc.) is for afterward, inside the encrypted tunnel. (Two-way "mutual TLS," where the client also presents a certificate, exists but is the exception, used mostly between back-end services - not for everyday websites.)

## Where TLS sits in the stack

It helps to know *where* this layer lives. TLS isn't a replacement for the networking you already know - it slots neatly into it.

```text
   ┌─────────────────────────────┐
   │  HTTP   (your page request)  │   ← the application's language
   ├─────────────────────────────┤
   │  TLS    (encrypt + verify)   │   ← THIS GUIDE: the security layer
   ├─────────────────────────────┤
   │  TCP    (reliable delivery)  │   ← gets bytes there in order, intact
   ├─────────────────────────────┤
   │  IP     (addressing/routing) │   ← finds the machine across the internet
   └─────────────────────────────┘
```

*What just happened:* TLS sits *between* HTTP and TCP. First TCP makes a reliable connection (the bytes will arrive, in order). Then TLS runs its handshake over that connection and turns it into a private, verified channel. Then HTTP flows through that channel exactly as it normally would - it barely knows TLS is there. That's why "HTTPS" is genuinely "HTTP over TLS," nothing more exotic. For the full picture of those lower layers, see [The TCP/IP Model](/guides/tcp-ip-model).

## Why this saves you later

When something goes wrong with HTTPS, knowing the handshake order tells you *where* to look. A "connection reset during handshake" is a different problem from a certificate error (Phase 3), which is different again from a page that loads fine but behaves badly (an application bug, not a TLS one). And when you hear "we need to rotate the private key" or "the session key is ephemeral," you'll know exactly which key they mean and what role it plays.

## Recap

1. **Symmetric** encryption uses one shared key - fast, but both sides must already share the secret.
2. **Asymmetric** encryption uses a public/private key pair - anyone can lock with the public key, only the private key unlocks. No pre-shared secret needed, but it's slow.
3. TLS uses the slow asymmetric pair *once* to safely agree on a fast **symmetric session key**, then uses that for all the real data. Best of both.
4. The handshake: hello → server's certificate + public key → you verify it → both agree on a session key → encrypted conversation begins.
5. The handshake authenticates the **server to you** by default; your login authenticates **you to the server** afterward, inside the tunnel.
6. TLS sits between **HTTP** and **TCP** - it secures the reliable connection that TCP/IP already built.

Watch it animated: [the TLS handshake](/explainers/TLSHandshake.dc.html) and [encryption](/explainers/Encryption.dc.html)


---

# Certificates & Trust

Phase 2 left one promise unkept. During the handshake, the server hands you a **certificate** containing its public key - and you're supposed to *verify* it before trusting anything. But verify against what? If a stranger hands you an ID badge, how do you know it isn't forged? You can't just take their word for it - that's the whole problem we're trying to solve.

This phase answers that: what a certificate is, who signs it, why your browser believes that signature, and exactly what each error means - so the next warning is information, not a panic.

## When a warning appears: the calm cheat-card

People reach this page while staring at a red error, so here's the quick reference first - explanations underneath.

| What the warning says | What it actually means | Calm response |
|---|---|---|
| **Certificate expired** | The cert was valid but its date passed; nobody renewed it in time. | Usually an ops mistake - but you can't tell expired from a stale attack, so don't enter anything sensitive. Wait, or contact them. |
| **Name mismatch** (`NET::ERR_CERT_COMMON_NAME_INVALID`) | The cert is valid but for a *different* domain than the one in your address bar. | Treat as untrusted. Often a misconfiguration, but also exactly what an interception looks like. |
| **Self-signed / unknown issuer** | The cert wasn't signed by a CA your browser trusts - the server vouched for itself. | Fine on your own dev machine. **Never** click through on a public site you didn't set up. |
| **Revoked** | The CA has officially cancelled this cert (often after a key compromise). | Do not proceed - a strong signal something is wrong. |

⚠️ **The one rule that matters:** On a real site - your bank, your email, your company's tools - **do not click through a certificate warning.** The warning is your browser saying "I cannot prove this is who it claims to be" - precisely the moment an attacker needs you to ignore it. The "Advanced → proceed anyway" link is for developers testing their own servers, not for getting past your bank's broken cert.

## What a certificate actually is

**What it actually is.** A certificate is a small file that makes one core claim and backs it with a signature:

> "The public key inside this file belongs to the owner of `yourbank.com`." - signed, a Certificate Authority.

It bundles together: the **domain name(s)** it's valid for, the server's **public key** (from Phase 2's handshake), a **validity period** (not-before/not-after dates), the **issuer**, and the CA's **digital signature** over all of that.

**Why people get this wrong.** It's tempting to think the certificate *is* the encryption, or some kind of license proving the site is legitimate. It's neither - a certificate does exactly one job: tie a *public key* to a *domain name*, with a trusted third party's signature as proof. (Recall Phase 1: this is why the padlock can't vouch for trustworthiness - the cert only ever claimed "this key belongs to this domain.")

## The chain of trust - why your browser believes the signature

The certificate is signed by a CA. But that's the same puzzle one level up: why trust the CA's signature? The answer is a deliberate, finite chain.

📝 A **Certificate Authority (CA)** is an organization whose business is verifying that whoever asks for a cert for `yourbank.com` actually controls `yourbank.com`, then signing a certificate to that effect. Examples: Let's Encrypt, DigiCert, Sectigo.

The trust is anchored by a short list your browser and OS ship with - the **root store**, a few hundred CA certificates the vendors have vetted:

```mermaid
flowchart TD
  root["ROOT CA certificate<br/>pre-installed in your browser/OS - the anchor"]
  inter["INTERMEDIATE CA cert<br/>the root vouches for this one"]
  site["yourbank.com's cert<br/>(contains its public key) - handed to you in the handshake"]
  root -- signs --> inter
  inter -- signs --> site
```

*What just happened:* Your browser follows the chain upward. The server's cert was signed by an intermediate CA; the intermediate was signed by a root; and the root is one your browser *already* trusts because it shipped with it. If every link checks out and the chain ends at a trusted root, the browser accepts the certificate and the padlock appears. If the chain breaks anywhere - a signature doesn't verify, or it ends at a root nobody trusts - you get a warning. You don't have to trust the website; you only have to trust the handful of roots.

💡 **The key point:** you don't verify the world - you trust a small, vetted set of root CAs, and they extend that trust downward through signatures. That's the entire "chain of trust."

## Let's Encrypt - why HTTPS is everywhere now

For years, certificates cost money and took manual paperwork, so plenty of small sites stayed on plain HTTP. **Let's Encrypt**, a nonprofit CA launched to change that, issues certificates **free** and **automatically** over a protocol called ACME - a program on your server proves it controls the domain and gets a cert, no human in the loop.

**What it does in real life.** A tool like `certbot` requests, installs, and renews your certificate on a schedule:

```console
$ sudo certbot --nginx -d example.com
Requesting a certificate for example.com
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
This certificate expires on 2026-09-17.
Certbot has set up a scheduled task to automatically renew this certificate.
```

*What just happened:* certbot proved to Let's Encrypt that this server controls `example.com`, received a signed certificate valid for about 90 days, installed it, and - crucially - set up automatic renewal. The short lifetime is on purpose: if a key is ever compromised, the damage window is small. The automation is what makes a 90-day cert practical instead of a chore.

⚠️ **The gotcha: renew before expiry.** Let's Encrypt certs are short-lived *by design*. If automatic renewal silently breaks (a permissions change, a moved file, a firewall rule), the cert expires and **every visitor hits a full-page "certificate expired" warning**. This is one of the most common self-inflicted outages on the web - monitor your expiry dates; don't assume "set up auto-renew" means "never think about it again."

## Reading the errors calmly

Now the cheat-card makes sense: each error is the chain-of-trust check failing in a specific way. **Expired** means a validity date failed. **Name mismatch** means the domain binding - the *core* claim of a certificate (Phase 1) - doesn't match your address bar. **Self-signed/unknown issuer** means the chain never reaches a trusted root. None of these are things you can safely reason past on a real site; treat every one as "don't trust this connection."

🪖 **War story.** A team shipped a new subdomain, `api.theircompany.com`, but pointed it at a load balancer still serving the certificate for `www.theircompany.com`. Every API call failed with a name mismatch - nothing was hacked, the cert just didn't cover the new name. Reading the error *as information*, not a panic, is what turns a 2am page from dread into a checklist.

## Recap

1. A **certificate** binds a *domain name* to a *public key*, signed by a CA - not encryption, not a seal of legitimacy.
2. Your browser trusts a small **root store** of CAs; they sign **intermediates**, which sign site certs. Following that **chain of trust** to a known root is what makes the padlock appear.
3. **Let's Encrypt** made certs free and automatic (via ACME/`certbot`), which is why nearly everything is HTTPS now - its certs are short-lived on purpose.
4. **Renew before expiry** - broken auto-renewal causes a full-page expiry warning for every visitor, a common, avoidable outage.
5. Read errors as facts: **expired** = stale dates, **name mismatch** = wrong domain, **self-signed/unknown issuer** = chain doesn't reach a trusted root.
6. **Never click through a certificate warning on a real site** - that's exactly what an attacker needs you to ignore.
