# TLS and HTTPS

TLS is the layer that turns an untrusted network into a channel you can send a password through. It is also where a large share of "the API is down" incidents actually live, because certificate and clock problems present as application errors.

## What HTTPS is

HTTPS is HTTP inside TLS. Nothing about the application protocol changes; the transport becomes authenticated and encrypted.

TLS gives you three things, and it is worth naming them separately because each fails differently:

1. **Confidentiality** — nobody on the path reads the bytes.
2. **Integrity** — nobody on the path alters the bytes undetected.
3. **Authentication** — the server proved it controls the private key for that name, via a certificate chain to a trusted root.

## The handshake, plainly

```mermaid
sequenceDiagram
    participant C as Client
    participant S as Server
    C->>S: ClientHello (TLS 1.3, SNI example.com, ALPN h2, key share)
    S->>C: ServerHello + {Certificate, CertificateVerify, Finished}
    Note over C: verify chain, name, dates, revocation
    C->>S: {Finished} + first HTTP request
    Note over C,S: 1-RTT, keys derived from ECDHE
```

TLS 1.3 removed the extra round trip, the RSA key exchange and most legacy ciphers. A resumed session can be 0-RTT, which is fast and replayable — which is why 0-RTT is only safe for idempotent requests.

Key terms, in the order they matter:

| Term | Meaning | Failure it explains |
|---|---|---|
| **SNI** | The hostname the client asks for, in cleartext | Wrong certificate served by a shared IP |
| **Certificate chain** | Leaf → intermediate(s) → root | "Untrusted certificate" when the intermediate is missing |
| **SAN** | The names a certificate is valid for | `www.` works, apex does not |
| **Validity dates** | `notBefore` / `notAfter` | The most common outage in the world |
| **ALPN** | Which protocol to speak (`h2`, `http/1.1`) | Client and server disagree, silently fall back |
| **Cipher suite** | Algorithms for key exchange, encryption, MAC | Old clients rejected by a hardened server |
| **OCSP / CRL** | Revocation checking | Soft-fail means revocation is often not enforced |

## Inspecting it in ten seconds

```bash
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates -ext subjectAltName
curl -vI https://example.com 2>&1 | grep -E "SSL|TLS|certificate|expire"
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -enddate
```

`-servername` matters: without SNI you get the default certificate and a misleading error.

## Certificates and automation

Certificates are infrastructure, not an annual chore. Manual renewal is the reason for the majority of expiry outages.

| Approach | Good for | Watch out |
|---|---|---|
| ACME (Let's Encrypt, ZeroSSL) | Public web endpoints | 90-day lifetime; renewal must be tested, not assumed |
| Provider-managed (ACM, Cloudflare, GCP) | Cloud load balancers | Limits on custom domains and validation methods |
| Internal CA / private PKI | Service-to-service, internal names | Distribution of the root to every client |
| mTLS | Workload identity | Rotation of client certs, revocation, clock skew |

Rotate before expiry, monitor the expiry date as a metric, and keep one non-automated path documented for when the automation is broken.

## Where it goes wrong

- **Expired certificate.** Alert on `notAfter` at 30, 14 and 7 days, for every endpoint, including the ones behind a CDN and the ones nobody remembers.
- **Missing intermediate.** Works in browsers (which cache or fetch intermediates) and fails in `curl`, Java and older Android. Test with a fresh client, not your laptop.
- **Name mismatch.** Certificate covers `api.example.com`, client calls `api.internal.example.com`. Fix the certificate or the client, not the error message.
- **Clock skew.** A host five minutes behind rejects valid certificates, and logs say "certificate not yet valid". NTP is a security dependency, not a convenience.
- **TLS termination in the wrong place.** Terminated at the load balancer and re-encrypted to the backend without validation is fine; terminated and sent cleartext across an untrusted network is not.
- **Protocol floor set too high or too low.** Disabling TLS 1.2 breaks old integrations; allowing TLS 1.0 fails audits. Know which clients you actually have.
- **Pinning without an exit plan.** Certificate pinning breaks the day you rotate, and mobile clients that pinned cannot be updated in time.

## Teaching hook

**The sealed envelope with a wax stamp.** Anyone can carry it; only the holder of the stamp could have sealed it; if the seal is broken you know. The certificate is the notarised copy of the stamp, signed by someone you already trust.

Demo: visit a site with a deliberately wrong system clock (in a VM) and watch a perfectly healthy site fail. Then `openssl s_client` the same host from a correct clock. That contrast teaches clock skew better than any paragraph.

## Related Notes

- [[Core-Protocols/HTTP-Versions-And-QUIC.md]] — what runs inside the tunnel
- [[Network-Services/NTP-And-Time.md]] — the dependency nobody lists
- [[Security/Zero-Trust-And-Segmentation.md]] — mTLS as workload identity
- [[Network-Services/Load-Balancing.md]] — where TLS usually terminates
