SSL/TLS Explained — How HTTPS Encrypts the Web and How Certificates Work thumbnail

SSL/TLS Explained — How HTTPS Encrypts the Web and How Certificates Work

⏱ approx. 23 min views 198 likes 0 LOG_DATE:2026-05-09
TOC

TLS (Transport Layer Security) is the thin encrypted layer that sits on top of TCP. It is the "S" in HTTPS — the https:// in your URL bar and the padlock icon are both this layer. From an application protocol (HTTP / SMTP / IMAP ...) point of view, TLS looks like just an encrypted byte stream, which is exactly why HTTPS could be deployed without modifying HTTP at all. This article walks through role → handshake → certificates and PKI → cryptographic algorithms → diagnosing TLS with openssl → historical vulnerabilities → real-world operational setup, covering only what server operations and troubleshooting actually need.

01

The three guarantees TLS provides #

TLS provides exactly three properties, no more.

  • Confidentiality — nobody who taps the wire can read the traffic (AES-GCM / ChaCha20-Poly1305)
  • Integrity — tampering with the traffic is detectable (AEAD authentication tag)
  • Authentication — the party you are talking to is who they claim to be (X.509 certificate + PKI)

The third one — authentication — is by far the most important: without it the first two are meaningless. If an attacker is sitting in the middle, "encrypted communication with the attacker" is exactly what you get. Flags like curl -k or --insecure throw away this guarantee, and they have no place in production.

▸ "SSL" vs "TLS" — which is which

For historical reasons "SSL" and "TLS" are still used interchangeably, but everything deployed today is TLS. The IETF standardised Netscape's SSL 2.0 (1995) / 3.0 (1996) into TLS 1.0 (1999) → 1.1 (2006) → 1.2 (2008) → 1.3 (2018, RFC 8446), and as of 2026 more than 95 % of HTTPS traffic is TLS 1.2 or 1.3. Casual phrasing like "SSL certificate" or "SSL-ify the site" survives in marketing copy, so being comfortable with either word is enough.

The position TLS sits in is between the Application layer and the Transport layer. HTTP runs on TCP; HTTPS becomes a three-layer stack of HTTP → TLS → TCP, with TLS encrypting and decrypting transparently to the layers above and below. In HTTP/3, TLS 1.3 is built directly into QUIC — a custom transport on top of UDP.

02

The handshake — one round trip to derive the keys #

The handshake is the heart of TLS. It performs key exchange and peer authentication, and establishes the session key that protects the rest of the connection. In TLS 1.3 the whole thing completes in 1-RTT (one round trip) — half the cost of TLS 1.2.

1. ClientHello (Client → Server)
Sends supported TLS versions, cipher suites, key_share (ECDHE public key), signature algorithms, and SNI (the hostname being requested) all at once.
2. ServerHello + Certificate (Server → Client)
Key exchange completes inside ServerHello, so encryption starts immediately. The server certificate, CertificateVerify (signed with the server's private key), and Finished are all sent encrypted (in TLS 1.2 the certificate was in cleartext).
3. Finished (Client → Server)
The client verifies the certificate chain and returns the handshake-completion MAC. From here on, only application_data records — symmetrically encrypted — flow on the wire.

Step through it yourself — follow how messages bounce between client and server from ClientHello to Finished and the encrypted channel is established.

The key trick is that ClientHello carries key_share with it: the client commits to an ECDHE public key on speculation, so the very first server response can finish the key exchange. TLS 1.2, by contrast, had a 2-RTT structure where the client waited for ServerHello and only then sent ClientKeyExchange.

TLS 1.2 (2-RTT) vs TLS 1.3 (1-RTT)
# TLS 1.2 — certificate in cleartext, two round trips Client Server | ClientHello | |------------------------------------>| | ServerHello / Certificate / KeyEx | ← sent in cleartext |<------------------------------------| | ClientKeyExchange / Finished | |------------------------------------>| | Finished | |<------------------------------------| |===== Application Data (encrypted) ==| # TLS 1.3 — certificate also encrypted, one round trip Client Server | ClientHello (+ key_share) | |------------------------------------>| | ServerHello + {Cert, Verify, Fin} | ← {} = encrypted |<------------------------------------| | Finished | |------------------------------------>| |===== Application Data (encrypted) ==|
▸ 0-RTT (Early Data) is replayable

When the client has already handshaken with the server previously, it can use a PSK (Pre-Shared Key) to piggyback application_data onto the first round trip in 0-RTT. This is great for mobile apps that don't want to pay handshake latency every time. The catch is that 0-RTT data is replayable, so it must be limited to side-effect-free idempotent operations like GET. Never put a payment action behind 0-RTT.

03

Certificates and PKI — the chain of trust #

A server certificate is an X.509 structure — a bundle of fields like this:

  • SubjectCN=hackinglabo.com, with target domains enumerated in the SAN (Subject Alternative Name)
  • Issuer — which CA signed it
  • Validity — expiry window (public CAs cap at 398 days)
  • Public Key — the public key for this domain (RSA / ECDSA / Ed25519)
  • Extensions — Key Usage / EKU / AIA / CRL DP / SCT (Certificate Transparency)
  • Signature — the CA's signature over all of the above

A real server certificate never stands alone. It is the leaf of a chain — "Root CA → Intermediate CA → Server Cert" — and the leaf is signed by an intermediate which is signed by a root. Trust is established only when the chain can be walked all the way back to a Root CA that is preloaded into the OS / browser trust store.

Typical certificate chain (Let's Encrypt example)
Root CA ISRG Root X1 # bundled with OS/browser, self-signed │ signs Intermediate R3 / R10 / E5 # actual issuing CA is this intermediate │ signs Server Cert CN=hackinglabo.com # the certificate the server presents # the client walks Server → Intermediate → Root; if Root is trusted, OK

Let's Encrypt and ACME automation #

Launched in 2015, Let's Encrypt is a free, fully-automated CA that today issues more than half of all HTTPS certificates worldwide. The protocol is ACME (RFC 8555), and tools like certbot / acme.sh automatically prove domain ownership (HTTP-01 / DNS-01 / TLS-ALPN-01) and acquire / renew a 90-day certificate on a schedule.

Challenge How it works When to use
HTTP-01 Place a token at http://example.com/.well-known/acme-challenge/... Standard web servers
DNS-01 Write a token into a _acme-challenge.example.com TXT record Wildcard certs, internal servers
TLS-ALPN-01 Answer a special ALPN on port 443 Services that only expose 443 and can't do HTTP-01

Revocation and Certificate Transparency #

When a private key leaks, the certificate must be forcibly invalidated — that's revocation. The modern combination is OCSP Stapling (the server fetches an OCSP response and ships it with the handshake) plus CRLite / OneCRL (the browser receives a bloom-filter bundle of revoked certs).

To detect mis-issuance, Chrome has required CAs to log every issued certificate to public Certificate Transparency logs since 2018. The certificate carries SCTs from at least two independent CT logs. Operators can monitor crt.sh to see every certificate ever issued for their domain by any CA — the single best tool for catching mis-issuance early.

04

Cryptographic algorithms — Forward Secrecy and AEAD #

In TLS 1.2 a cipher suite was a single string that specified "key exchange + authentication + symmetric cipher + MAC" — four orthogonal pieces in one identifier. TLS 1.3 dramatically simplified this, and the combinations you'll actually see in modern operations are a small finite list.

Reading a cipher suite string
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 # TLS 1.2 format │ │ │ │ │ │ │ └─ HKDF / PRF hash │ │ └─ symmetric cipher (AEAD) │ └─ server certificate key type (authentication) └─ key exchange (ECDHE = Forward Secrecy) # TLS 1.3 — key exchange and authentication are negotiated separately; # only the symmetric cipher + hash remain TLS_AES_128_GCM_SHA256 TLS_AES_256_GCM_SHA384 TLS_CHACHA20_POLY1305_SHA256

Key exchange — Forward Secrecy is the watershed #

Forward Secrecy (FS, PFS) is the property that a future leak of the long-term private key does not allow decryption of past traffic. Only ephemeral-key exchanges — DHE / ECDHE — provide this. The classic "RSA key exchange", where the client encrypts a Premaster with the server's RSA public key and ships it, fails this property: if the RSA private key ever leaks, every past session can be decrypted. This is exactly why TLS 1.3 removed RSA key exchange entirely. In practice today the key exchange is almost always X25519 or ECDHE P-256.

AEAD fuses encryption and authentication #

AEAD (Authenticated Encryption with Associated Data) is a construction that performs encryption and integrity check as one operation. It structurally eliminates the kind of ordering problems ("encrypt-then-MAC vs MAC-then-encrypt") that bred padding-oracle attacks. TLS 1.3 allows only AEAD, and in practice the choices are three:

  • AES-128-GCM / AES-256-GCM — extremely fast on CPUs with AES-NI, the server-side default
  • ChaCha20-Poly1305 — fast on mobile CPUs without AES-NI; led by Google
  • AES-CCM — a lightweight variant for IoT

Server certificate signing keys #

There are three families of key type the server certificate can use. From oldest to newest: RSA-2048 / 3072 (maximum compatibility), ECDSA P-256 / P-384 (smaller, faster), and Ed25519 (standardised in TLS 1.3, the newest). For a general-purpose public website, a dual certificate of ECDSA P-256 + RSA-2048 is the safe choice.

▸ What TLS 1.3 dropped from the "weak pile"
  • RSA key exchange — no Forward Secrecy
  • CBC mode — bred BEAST / Lucky13 / POODLE
  • 3DES / RC4 — symmetric ciphers known to be weak
  • MD5 / SHA-1 — no collision resistance
  • TLS compression — bred CRIME / BREACH

Cutting all of these at once means that simply running a TLS 1.3 server makes it structurally impossible to select a weak algorithm.

05

Diagnosing TLS with openssl #

Almost every TLS-related fault — bad certificate chain, missing SNI, fallback to an old protocol, expired certificate — can be diagnosed with a single binary: openssl.

openssl s_client — watch the handshake live
# connect and observe certificate chain + handshake $ openssl s_client -connect hackinglabo.com:443 -servername hackinglabo.com # pin a protocol version (compatibility testing) $ openssl s_client -connect example.com:443 -tls1_3 $ openssl s_client -connect example.com:443 -tls1_2 # dump every certificate in the chain as PEM (for offline verification) $ openssl s_client -connect example.com:443 -showcerts < /dev/null
openssl x509 — inspect a certificate
# pull from a server and print just the essentials (expiry / SAN / issuer) $ echo | openssl s_client -connect example.com:443 2>/dev/null \ | openssl x509 -noout -subject -issuer -dates -ext subjectAltName # read from a file $ openssl x509 -in cert.pem -noout -text # SHA-256 fingerprint (for HPKP / DANE) $ openssl x509 -in cert.pem -noout -fingerprint -sha256
Self-signed certificates (development / testing)
# generate an ECDSA P-256 private key $ openssl ecparam -genkey -name prime256v1 -out key.pem # one-liner: self-signed cert valid for one year $ openssl req -x509 -key key.pem -out cert.pem -days 365 \ -subj "/CN=test.example.com"
curl / nmap / testssl.sh — one level up
# curl — full TLS handshake log $ curl -v --tls-max 1.3 https://example.com # nmap — enumerate supported cipher suites and check Heartbleed $ nmap --script ssl-enum-ciphers -p 443 hackinglabo.com $ nmap --script ssl-heartbleed -p 443 example.com # testssl.sh — the swiss army knife for TLS misconfig & CVE scanning $ ./testssl.sh https://hackinglabo.com $ ./testssl.sh -U https://hackinglabo.com # vulnerabilities only

For an online equivalent, Qualys SSL Labs is the standard — it grades you A+ / A / B. Worth running once before any production launch.

06

What the historical vulnerabilities teach us #

The history of TLS vulnerabilities is exactly the history of what modern configuration must throw away. Knowing just the famous ones makes today's hardening guidance feel obvious instead of arbitrary.

Year Attack What happened Lesson
2011 BEAST Recover plaintext one byte at a time under TLS 1.0 / CBC Drop CBC, move to AEAD
2012 CRIME / BREACH Abuse TLS / HTTP compression to leak cookies Turn off TLS compression
2013 Lucky 13 Padding inferred from CBC + HMAC timing differences Fully migrate to AEAD
2014 Heartbleed A missing bounds check in the OpenSSL Heartbeat extension leaks up to 64 KB of server memory, possibly including the private key (CVE-2014-0160) Re-issue all certificates, take patching seriously
2014 POODLE Sloppy padding validation in SSL 3.0's CBC recovers plaintext Disable SSL 3.0 entirely (RFC 7568)
2015 FREAK / Logjam Forced downgrade to 512-bit RSA / DH left over from 90s export rules Remove EXPORT ciphers, raise DH to 2048-bit+
2016 DROWN Same private key shared between SSL 2.0 and TLS allows decryption Eliminate SSL 2.0 everywhere
2017 ROBOT The 1998 Bleichenbacher attack on RSA returns Move to ECDHE / TLS 1.3
▸ The truth Heartbleed forced us to see

One missing bounds check in OpenSSL's Heartbeat extension was enough to put the private keys of servers worldwide at risk. Yahoo!, Google, AWS — every major service patched in parallel; it remains the worst TLS-implementation disaster in history. The takeaway is simple: cryptography is mathematics, but implementation is written by humans. Checking openssl version periodically and applying CVE patches immediately is the operational baseline that came out of this.

MITM (man-in-the-middle) and modern defenses #

Mis-issuance by a CA (DigiNotar 2011, Symantec 2017) and "TLS inspection" appliances at the corporate or home-router edge that swap the certificate on the fly — these MITM scenarios are still real today. The standard defense stack combines:

  • HSTS — once a site has been reached over HTTPS, refuse plain HTTP; preload via hstspreload.org
  • Certificate Transparency — visible audit trail of every issued cert; monitor with crt.sh
  • DANE / TLSA — bind certificates to DNS via DNSSEC (operational burden is high)
  • CRLite / OneCRL — browser-side revocation distributed in bulk
07

The real-world operational setup #

Boiling all of this down for day-to-day operation, two things matter: choosing the right profile, and building a system that doesn't quietly rot.

Use Mozilla's templates #

You don't need to design the cipher-suite list yourself. The Mozilla SSL Configuration Generator (ssl-config.mozilla.org) ships three copy-paste profiles that have become the de facto industry standard.

Profile TLS versions Who this is for
Modern 1.3 only APIs and internal services where "latest browsers only" is fine
Intermediate 1.2 + 1.3 General public websites. If unsure, pick this
Old 1.0 → 1.3 Only when Windows XP / Android 4 compatibility is a legal requirement

Operational loops that catch drift #

Configure once and walk away is the path to incidents. Build automatic renewal and periodic checks so you actually notice when something is wrong. Most TLS production incidents trace back to a manual step someone left in place.

  • certbot / acme.sh + cron for automatic certificate renewal — any manual step will eventually be missed and you'll ship an expired certificate
  • Enable OCSP Stapling — fixes both the revocation-check latency and the privacy leak in one
  • HTTP → HTTPS 301 + HSTS preload registration (hstspreload.org) — structurally close the cleartext door
  • Run testssl.sh / Qualys SSL Labs on a schedule — twice a year is a reasonable cadence, plus on any major CVE
  • CT monitoring via crt.sh — catch mis-issuance against your domains early
  • Keep OpenSSL patched — assume more Heartbleed-class CVEs will appear, and have a patching procedure ready
▸ Shiny new features you don't need to chase

SNI encryption via ECH (Encrypted Client Hello) and quantum-resistant post-quantum key exchange (X25519MLKEM768 and friends) have just started rolling out at browsers and CDNs as of 2026. They are worth watching, but the biggest practical win is still nailing the basics: TLS 1.3 + the Intermediate profile + automatic renewal. Get that foundation rock-solid before chasing the new shiny.

𝕏 Post B! Hatena