SSL/TLS Explained: HTTPS Encryption and Certificates thumbnail

SSL/TLS Explained: HTTPS Encryption and Certificates

⏱ approx. 28 min views 63 likes 0 LOG_DATE:2026-05-09
TOC

SSL/TLS (Transport Layer Security) #

Transport Layer Security (TLS) and its predecessor Secure Sockets Layer (SSL) are cryptographic protocols that provide confidentiality (eavesdropping protection), integrity (tamper detection), and authentication (anti-impersonation) for network traffic. The "S" in HTTPS is SSL/TLS, and almost every secure communication on the Internet — Web, email (SMTPS / IMAPS), VPNs, APIs, IoT, gaming, custom protocols — rides on top of it.

For historical reasons "SSL" and "TLS" are still mixed in casual usage, but only TLS is actually deployed today (the IETF declared SSL deprecated in 2011). The colloquial phrasing — "SSL certificate," "SSL-ify your site" — survives anyway. This article will say "SSL/TLS" or "TLS" depending on context.

1. The history of SSL/TLS #

1.1 SSL 1.0 (1994, Netscape, never released) #

In 1994 Netscape designed SSL 1.0 internally to safely transmit credit card numbers over the Web. It had so many design flaws that it never shipped.

1.2 SSL 2.0 (1995) #

Netscape published SSL 2.0 in 1995. Bundled in Netscape Navigator 1.1+, it was the first version of SSL to spread across the Web. It still had fundamental defects — using the same key for the MAC and the encryption, not retroactively verifying handshake integrity, and so on.

1.3 SSL 3.0 (1996) #

In 1996, after the SSL 2.0 mistakes were laid bare, Netscape did a complete refactor and released SSL 3.0. This is where the modern TLS structure — separating the record layer from the handshake layer — took shape. RFC 6101 (2011) later documented it for reference. POODLE (2014) finished it off (RFC 7568 forbids it).

1.4 TLS 1.0 (1999, RFC 2246) #

In 1999, the IETF standardized SSL 3.0 — with modifications — as TLS 1.0 (RFC 2246). This was the moment ownership moved from a Netscape-only standard to an open IETF one. It was not wire-compatible with SSL 3.0; the differences are in details like Premaster Secret derivation.

1.5 TLS 1.1 (2006, RFC 4346) #

Fixed an implementation issue where the CBC IV could be predicted. Introducing an explicit IV preempted what would later be BEAST (2011). Practically, TLS 1.1 was just a stepping stone from 1.0 to 1.2.

1.6 TLS 1.2 (2008, RFC 5246) #

The start of TLS's long golden age. SHA-1 was no longer wired into the PRF/MAC; any hash could be plugged in. AEAD ciphers (GCM, ChaCha20-Poly1305) became supported, and the signature algorithm space was extended. TLS 1.2 is still the workhorse of production deployments, running side-by-side with 1.3.

1.7 TLS 1.3 (2018, RFC 8446) #

The first major overhaul in 10 years. Backwards compatibility was sacrificed and the protocol was rebuilt:

  • The handshake is now 1 round-trip (1-RTT), and 0-RTT for resumption
  • All the legacy / weak crypto (RSA key exchange, CBC, 3DES, RC4, MD5, SHA-1) was removed
  • AEAD ciphers (AES-GCM / ChaCha20-Poly1305 / AES-CCM) are mandatory
  • Forward Secrecy is required (DHE / ECDHE only)
  • Encryption begins right after ServerHello, minimizing metadata leakage

Chrome and Firefox shipped real support in 2018. Today over 95% of HTTPS speaks TLS 1.2 or 1.3 (TLS 1.0/1.1 was dropped from major browsers in 2020).

1.8 Beyond TLS 1.3 (Encrypted Client Hello and friends) #

TLS 1.3 itself is mature. On top of it, ECH (Encrypted Client Hello) — a draft extension that encrypts the SNI (the destination hostname leaked in plaintext today) — is being rolled out for censorship-circumvention and privacy.

2. The role of SSL/TLS and its OSI position #

+----------------------+
| Application layer    | HTTP / SMTP / IMAP / FTP ...
+----------------------+
| ★ TLS                | (this article) — encryption / authentication / integrity
+----------------------+
| Transport layer      | TCP (TLS) / UDP+QUIC (TLS 1.3 baked in)
+----------------------+
| Network layer        | IP
+----------------------+
| Data Link / Physical | Ethernet / Wi-Fi / fiber
+----------------------+

TLS is a thin layer wedged "above Transport, below Application". To the application protocol (HTTP, SMTP, ...) it presents just an encrypted byte stream. That's the great design beauty of TLS — it's exactly why HTTPS could exist without changing HTTP at all.

What TLS provides:

  • Confidentiality: an eavesdropper can't read the traffic (symmetric crypto = AES-GCM etc.)
  • Integrity: tampering with the traffic is detectable (the AEAD authentication tag)
  • Authentication: the peer is provably who they claim to be (X.509 certs + PKI)

A point that is easy to forget: encryption without authentication is meaningless. If a man-in-the-middle has substituted itself for the server, you'll happily encrypt your traffic… straight into the attacker's hands. SSL/TLS is meaningful only as a package with certificates.

3. The TLS handshake #

The handshake is the heart of TLS. It completes key exchange and peer authentication and establishes the session keys that the rest of the conversation will use. TLS 1.2 and TLS 1.3 differ a lot, so we'll cover both.

3.1 TLS 1.3 handshake (1-RTT) #

TLS 1.3 handshake (1-RTT) Client offers cipher suites and a key share up front → keys established in one round trip Client Server 1 ClientHello supported_versions, cipher_suites, key_share (ECDHE pubkey), signature_algorithms, SNI 2 ServerHello + {EncryptedExtensions, Certificate, CertificateVerify, Finished} Key share completes at ServerHello → encryption begins immediately ({...} is encrypted) At this point both sides hold handshake_traffic_secret application_traffic_secret_0 3 {Finished} (Client → Server) Confirms the handshake MAC → from here on application_data is symmetric-encrypted only ★ Differences vs TLS 1.2 (red parts removed/merged) • TLS 1.2 went ClientHello → ServerHello → Certificate → ServerKeyExchange →   ServerHelloDone → ... requiring 2 round trips (2-RTT) • TLS 1.3 puts key_share in ClientHello and finishes the key in one ServerHello → 1-RTT • Encryption starts right after ServerHello, so the certificate is encrypted too (plaintext in 1.2) • Old crypto (RSA key exchange, CBC, 3DES, RC4, MD5, SHA-1) is completely removed • Key exchange is ECDHE / DHE only = Forward Secrecy is mandatory ★ 0-RTT (Early Data) and resumption • If you've spoken to the server before, a PSK (Pre-Shared Key) lets you send   application_data with 0-RTT • 0-RTT data is replayable — restrict it to side-effect-free, idempotent things like GETs • PSK + (EC)DHE mode preserves Forward Secrecy even on resumption

3.2 Compared to the TLS 1.2 handshake #

A full TLS 1.2 handshake is 2-RTT and looks like this:

Client                                  Server
  |  ClientHello                          |
  |  (supported cipher suites, random)    |
  |-------------------------------------->|
  |                                       |
  |  ServerHello                          |
  |  (chosen cipher, random)              |
  |  Certificate (X.509 chain)            |
  |  ServerKeyExchange (ECDHE pubkey)     |
  |  ServerHelloDone                      |
  |<--------------------------------------|
  |                                       |
  |  ClientKeyExchange (ECDHE pubkey)     |
  |  ChangeCipherSpec                     |
  |  Finished                             |
  |-------------------------------------->|
  |                                       |
  |  ChangeCipherSpec                     |
  |  Finished                             |
  |<--------------------------------------|
  |                                       |
  |======== Application Data (encrypted) =|

Everything from ServerHello through ChangeCipherSpec travels in the clear, so on TLS 1.2 a network observer can see "which certificate was used" and "which version / cipher suite was selected." TLS 1.3 encrypted these and cut the metadata leakage.

3.3 Cipher suites #

In TLS 1.2 and earlier a cipher suite was a single string encoding four things: key exchange + authentication + bulk cipher + MAC.

TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
    │     │       │             │
    │     │       │             └─ HKDF/PRF hash
    │     │       └─ symmetric cipher (AEAD)
    │     └─ authentication (server cert key type)
    └─ key exchange (Forward-Secret)

In TLS 1.3 key exchange and authentication are negotiated separately, and the cipher suite specifies just bulk cipher + hash. Representative TLS 1.3 cipher suites:

  • TLS_AES_128_GCM_SHA256
  • TLS_AES_256_GCM_SHA384
  • TLS_CHACHA20_POLY1305_SHA256

4. Certificates and PKI #

4.1 X.509 certificates #

TLS authentication relies on X.509 certificates. A certificate is a structured record (encoded as DER binary, or as PEM = base64 + headers) containing:

  • SubjectCN=hackinglabo.com, plus SANs (Subject Alternative Names) for additional domains
  • Issuer — which CA signed this cert
  • Validity — the validity period (currently capped at 398 days)
  • Public Key — the public key for this domain (RSA / ECDSA / Ed25519)
  • Extensions — Key Usage, Extended Key Usage, AIA, CRL DP, SCT (Certificate Transparency)
  • Signature — the CA's signature over all the fields above

4.2 The certificate chain and the chain of trust #

A real-world server certificate sits at the end of a chain of CA signatures going parent → child.

[Root CA]   (bundled in OS / browser, self-signed)
   │ signs
   ↓
[Intermediate CA]   (the CA actually used in production)
   │ signs
   ↓
[Server Certificate]   (the cert for hackinglabo.com)

The client:

  1. Validates each certificate in the chain it received from the server in turn
  2. Checks validity period, signature, and extensions
  3. Trust is established if the chain ultimately terminates at a Root CA that's in the OS / browser trust store

Let's Encrypt's root, ISRG Root X1, has been bundled in major OSes since 2016.

4.3 Revocation checking (CRL / OCSP / OCSP Stapling) #

A certificate inside its validity period can still be revoked — typically because the private key leaked. Revocation checking comes in several flavors:

Mechanism How it works Drawback
CRL (Certificate Revocation List) CA publishes a list, clients fetch it periodically The file balloons over time
OCSP (Online Certificate Status Protocol) Client asks the CA per certificate Privacy leakage + latency
OCSP Stapling Server fetches the OCSP response in advance and bundles it in the handshake The modern default
CRLite / OneCRL Browsers ship a Bloom-filter-based bulk distribution Used by Chrome / Firefox

4.4 Certificate Transparency (CT) #

To detect mis-issuance, CAs are required to log every certificate they issue to public CT logs (Chrome has required CT since 2018). Each certificate carries at least two SCTs (Signed Certificate Timestamps) from independent logs.

The result: it's effectively impossible for an attacker or a malicious CA to issue a certificate for a domain you own without you being able to see it. Researchers and operators can monitor every certificate ever issued for their domain on crt.sh.

4.5 Let's Encrypt and ACME #

Started in 2015, Let's Encrypt is a free, fully automated CA that today issues more than half the world's HTTPS certificates. Its protocol is ACME (Automatic Certificate Management Environment, RFC 8555): clients like certbot perform a domain-ownership challenge (DNS-01 / HTTP-01 / TLS-ALPN-01) and obtain a 90-day-valid certificate, automatically renewed.

5. Cryptographic algorithms #

5.1 Key exchange #

How both sides safely agree on a session key.

Algorithm Notes Status
RSA Key Exchange Client encrypts the Premaster Secret to the server's RSA pubkey Removed in TLS 1.3 (no Forward Secrecy)
DHE (Diffie-Hellman Ephemeral) Sharing via short-lived DH keys Safe but slow
ECDHE (Elliptic Curve DHE) The elliptic-curve flavor of DHE TLS 1.3 default (X25519, P-256)

Forward Secrecy (FS, PFS): even if the long-term private key leaks tomorrow, past sessions stay encrypted. Only DHE / ECDHE provide it. RSA key exchange does not (a future RSA private-key leak retroactively decrypts every past session). That's why TLS 1.3 banned it.

5.2 Bulk ciphers (symmetric) #

Used for the actual data after the handshake.

Cipher Mode Use Recommended?
AES-128-GCM / AES-256-GCM AEAD General purpose ◎ (mandatory in TLS 1.3)
ChaCha20-Poly1305 AEAD Fast on mobile (no AES-NI)
AES-CCM AEAD IoT
AES-CBC + HMAC non-AEAD Up to TLS 1.2 △ (BEAST/Lucky13)
3DES / RC4 / NULL legacy ✗ (removed)

AEAD (Authenticated Encryption with Associated Data) combines encryption and integrity into one operation, structurally preventing padding-oracle attacks like Lucky13 and BEAST. TLS 1.3 only allows AEAD.

5.3 Signatures and authentication #

The signing key in the server certificate is what proves "this is really the server."

Key Status
RSA-2048 / RSA-3072 Classic, still very common
ECDSA P-256 / P-384 Elliptic curve, shorter keys, faster handshakes
Ed25519 Standardized for TLS 1.3, the newest

6. Major SSL/TLS commands #

6.1 openssl s_client — diagnostic TLS client #

# Connect, watch the chain and the handshake
openssl s_client -connect hackinglabo.com:443 -servername hackinglabo.com

# Pin a TLS version
openssl s_client -connect example.com:443 -tls1_3
openssl s_client -connect example.com:443 -tls1_2

# Just dump certificates
openssl s_client -connect example.com:443 -showcerts < /dev/null

# Probe a specific cipher suite
openssl s_client -connect example.com:443 -cipher 'ECDHE-RSA-AES256-GCM-SHA384'

6.2 openssl x509 — inspect a certificate #

# Pull from a server and decode in one shot
echo | openssl s_client -connect example.com:443 2>/dev/null \
  | openssl x509 -noout -text

# From a file
openssl x509 -in cert.pem -noout -subject -issuer -dates -ext subjectAltName

# Fingerprint
openssl x509 -in cert.pem -noout -fingerprint -sha256

6.3 Issuing a self-signed certificate with openssl #

# Generate a key (ECDSA P-256)
openssl ecparam -genkey -name prime256v1 -out key.pem

# Make a CSR
openssl req -new -key key.pem -out csr.pem \
  -subj "/CN=test.example.com"

# Self-signed cert (1 year)
openssl req -x509 -key key.pem -out cert.pem -days 365 \
  -subj "/CN=test.example.com"

6.4 Debugging TLS with curl #

# Verbose handshake log
curl -v --tls-max 1.3 https://example.com

# Skip certificate verification (testing only — never in production)
curl -k https://self-signed.example.com

# Force a TLS version
curl --tlsv1.2 --tls-max 1.2 https://example.com

6.5 Scanning TLS configuration with nmap #

# ssl-enum-ciphers — supported cipher suites, TLS versions, grades
nmap --script ssl-enum-ciphers -p 443 hackinglabo.com

# Certificate info
nmap --script ssl-cert -p 443 hackinglabo.com

# Heartbleed check
nmap --script ssl-heartbleed -p 443 example.com

6.6 testssl.sh — comprehensive TLS audit #

# Full scan
./testssl.sh https://hackinglabo.com

# Vulnerabilities only
./testssl.sh -U https://hackinglabo.com

The standard tool when you want a single command to find every misconfiguration (legacy protocols, weak ciphers, missing CT, etc.). Qualys SSL Labs (ssllabs.com/ssltest) is the online equivalent.

7. Security — well-known attacks and defenses #

7.1 BEAST (2011) — TLS 1.0 / CBC #

Exploits the predictable IV in CBC mode to recover plaintext one byte at a time. Mitigation: explicit IV in TLS 1.1+, or RC4 (which itself was later broken, so out), and ultimately abandoning CBC entirely for AEAD.

7.2 CRIME / BREACH (2012) — compression #

Abuses TLS / HTTP compression to leak secret strings (cookies and friends) byte by byte. Mitigation: TLS compression (RFC 3749) is disabled across the board, and HTTP-level responses must not echo secrets.

7.3 Lucky 13 (2013) — CBC + HMAC timing differential #

Padding inferred from timing differences between CBC and HMAC. Mitigation: AEAD migration (irrelevant in modern crypto).

7.4 Heartbleed (2014) — OpenSSL bug #

OpenSSL's Heartbeat extension forgot a bounds check, leaking up to 64 KB of arbitrary server memory — including potentially the private key itself. Worst-class severity in TLS history. CVE-2014-0160. Mitigation: immediate OpenSSL patch + rotation of all keys and reissue of all certs. Yahoo!, Google, AWS, and the rest of the planet patched in parallel.

7.5 POODLE (2014) — SSL 3.0 #

Sloppy CBC padding validation in SSL 3.0 lets an attacker recover plaintext. Mitigation: completely disable SSL 3.0 (RFC 7568) and use TLS_FALLBACK_SCSV to prevent forced downgrades.

7.6 FREAK / Logjam (2015) — Export-Grade crypto #

Re-activated 90s-era US-export-grade 512-bit RSA / 512-bit DH and forced a downgrade. Mitigation: remove all EXPORT cipher suites and use DH parameters of at least 2048 bits.

7.7 DROWN (2016) — SSL 2.0 keysharing #

If the same private key is shared between SSL 2.0 and TLS, the SSL 2.0 endpoint can be used to decrypt the TLS endpoint's traffic. Mitigation: eliminate SSL 2.0 from every server worldwide.

7.8 ROBOT (2017) — RSA Bleichenbacher #

A 19-year-old Bleichenbacher attack (1998) was rediscovered in many TLS implementations — Facebook, PayPal, Cisco, IBM and others. Mitigation: ECDHE instead of RSA key exchange. RSA key exchange is removed entirely from TLS 1.3.

7.9 Man-in-the-middle (MITM) and certificate-validation bypass #

Mis-issuance by rogue CAs (DigiNotar 2011, Symantec 2017), corporate / home-router "TLS inspection" swapping certificates, and so on. Mitigation:

  • HSTS (HTTP Strict Transport Security) — once a site has been visited over HTTPS, plaintext HTTP is refused
  • HPKP (deprecated) → CT + browser-side CRLite + Public Key Pinning, used in limited contexts
  • DANE / TLSA — bind certificates via DNSSEC (operationally heavy)
  • Certificate Transparency — make mis-issuance visible

8. The practical operational setup #

After the algorithm choices and vulnerability history in §5–§7, what real-world operations actually need comes down to two things: picking a profile and building loops that don't let the setup quietly age.

8.1 Server configuration: Mozilla's templates are enough #

You don't need to design handshake parameters or cipher-suite combinations yourself. The Mozilla SSL Configuration Generator (ssl-config.mozilla.org) hands you three copy-pasteable profiles, and that's effectively the industry standard.

Profile Supported TLS Intended for
Modern 1.3 only APIs / internal tools where "modern browsers only" is fine
Intermediate 1.2 + 1.3 Typical websites — the safe default
Old 1.0–1.3 Only when legal/business reasons force Windows XP / Android 4 compat

8.2 Mechanisms that prevent "I forgot, it got old" #

The configuration itself matters less than building operational loops where stale config gets noticed and renewed automatically:

  • Auto-renew certs with certbot / acme.sh + cron. Anything manual will eventually result in an expiry incident
  • Run testssl.sh or Qualys SSL Labs on a schedule (twice a year + when a major CVE drops). New CVEs will surface even on settings you used to think were safe
  • Monitor CT logs: crt.sh catches mis-issued certificates for your domain early
  • 301 redirect HTTP → HTTPS plus HSTS preload registration (hstspreload.org) structurally closes plaintext HTTP
  • Enable OCSP Stapling: removes revocation-check latency and the per-client privacy leak

ECH (Encrypted Client Hello) and post-quantum migration are still draft / experimental as of 2026. Track the news; production rollouts can wait.


SSL/TLS is often imagined as "the layer that just quietly works," but in reality it's the product of 30 years of cryptographic research and many painful vulnerability discoveries. Skip one cert auto-renewal and every user sees an error page; flip one wrong handshake setting and your bandwidth, latency, or compatibility quietly degrades. As the foundation of trust on today's Internet, taking the time to understand the principles is worth it for any Web developer, SRE, or security engineer.