Network Security: TLS & Beyond
TLS, PKI, and the full network-security stack — from wire-level attacks to the cryptographic handshake that protects every HTTPS connection you've ever made.
Overview
Every time your browser shows a padlock, a small miracle of applied cryptography is happening in milliseconds. Symmetric ciphers negotiate in the open. Certificates chain back to a root of trust baked into your operating system. A tiny MAC on each record defeats any attacker who intercepts the wire. This module tears open that padlock and explains every gear inside.
Network security is not a feature you add at the end — it is a discipline that runs through every layer of the stack. We will start at the threat model: who is the attacker, what can they observe or modify, and what guarantees do we actually want? Then we build up from symmetric ciphers through Diffie-Hellman key exchange, through X.509 certificates and the PKI trust hierarchy, all the way to the TLS 1.3 handshake that runs the modern web. Along the way we study how things break: MITM attacks, certificate mis-issuance, padding oracles, Bleichenbacher's attack, BEAST, CRIME, Heartbleed — real incidents that shaped the protocol.
The second half of the module zooms out from TLS to the broader threat landscape: VPNs that tunnel encrypted traffic, firewalls and stateful packet inspection, DDoS amplification attacks and how Anycast routing fights them, and a survey of secure application-layer protocols (SSH, DNSSEC, Signal's Double Ratchet). By the end you will understand not only how the internet defends itself, but why each design choice was made and what assumptions it rests on — so you can reason about new threats as they emerge.
Network security is the reason the modern economy functions at all. Every credit card transaction, every medical record query, every software update download, every bank login travels over infrastructure that is, at the physical layer, a broadcast medium that any adversary with hardware access can read. The only thing standing between your data and a passive eavesdropper in the same coffee shop is TLS. Understanding TLS at the protocol level — not just "use HTTPS" — means you can reason correctly about what it protects, what it does not, and how to configure it correctly.
Beyond TLS, network security is one of the most intellectually alive areas of computer science. It is a continuous arms race: every published cryptanalysis paper drives a protocol revision; every new attack surface (IoT devices, 5G core networks, cloud-to-cloud traffic) demands new defenses. Practitioners who understand the first principles — the Dolev-Yao threat model, authenticated encryption, certificate transparency — can evaluate new proposals rather than blindly following configuration guides. For any software engineer, security researcher, or systems designer, this module is the foundation on which everything else rests.
TLS 1.3 Handshake and Key Schedule
TLS 1.3 full 1-RTT handshake. After ServerHello, all messages are encrypted under the handshake secret. Application data begins after both Finished messages are exchanged and verified. The ECDH key shares provide forward secrecy; the certificate + CertificateVerify provide server authentication.
The concepts
01Threat Models and the Dolev-Yao Attacker
Before designing any security protocol, you must state precisely what the attacker can do. The standard model for network protocols is the Dolev-Yao attacker (1983): the adversary controls the network. They can read every packet, replay old packets, drop packets, inject new packets, and reorder packets. They cannot, however, break the underlying cryptographic primitives (they cannot factor large integers in polynomial time, cannot invert a random oracle, etc.).
This model might seem extreme, but it is realistic on any shared network (Wi-Fi, BGP-routed internet) and conservative — if your protocol is secure against a Dolev-Yao attacker, it is secure against a passive eavesdropper too. The model gives you a clean abstraction: reason about protocol-level security separately from cryptographic security.
The CIA triad frames the goals:
- Confidentiality — only intended parties can read the data.
- Integrity — data cannot be modified in transit without detection.
- Authenticity (sometimes called authentication) — you know who you are talking to.
Note that encryption alone does not give you integrity (a stream cipher can be bit-flipped without breaking it) and integrity alone does not give you authenticity (you need to know whose MAC you are verifying). TLS provides all three. A fourth goal, forward secrecy, means that compromise of long-term keys does not reveal past session traffic — TLS 1.3 mandates this.
The attacker model also names what is out of scope: endpoint compromise (malware on your laptop), social engineering, physical access. TLS cannot help if your certificate authority is compromised or your browser has a trojan. Knowing the boundaries of your security model is as important as knowing what it covers.
# Simplified Dolev-Yao channel model in pseudocode
# The network is an untrusted relay that can do anything
class DY_Network:
def send(self, src, dst, msg):
# Attacker intercepts every message
attacker.observe(msg) # learns plaintext if unencrypted
msg2 = attacker.maybe_modify(msg) # can tamper
if attacker.drop(msg): # can drop
return
deliver(dst, msg2) # or deliver modified copy
# Security requirement: even given full network control,
# attacker cannot learn session data or forge valid messages.
02Symmetric Encryption and Authenticated Encryption (AEAD)
A symmetric cipher uses the same secret key for encryption and decryption. Modern symmetric ciphers split into two families:
Block ciphers (AES) operate on fixed-size blocks (128 bits for AES). AES itself is a substitution-permutation network: 10/12/14 rounds of SubBytes, ShiftRows, MixColumns, and AddRoundKey. A block cipher alone is a pseudorandom permutation (PRP) — it just encrypts one block. To encrypt arbitrary messages you need a mode of operation: ECB (insecure — identical blocks produce identical ciphertext), CBC (needs random IV; vulnerable to padding oracles), CTR (turns AES into a stream cipher; IV must never repeat).
Stream ciphers (ChaCha20) produce a keystream XORed with the plaintext. ChaCha20 is faster than AES on CPUs without hardware AES acceleration (mobile) and immune to timing side-channels.
But here is the critical insight: encryption without authentication is not secure. An attacker who can flip bits in a CBC ciphertext can often flip bits in the corresponding plaintext in predictable ways (the CBC padding oracle attack). The solution is Authenticated Encryption with Associated Data (AEAD): encrypt-then-MAC (or a combined construction) so any tampering is detected before decryption. Modern choices:
- AES-GCM: AES in counter mode + GHASH MAC. Hardware-accelerated on all modern CPUs via AES-NI. Nonce must never repeat or the key is recoverable.
- ChaCha20-Poly1305: ChaCha20 stream cipher + Poly1305 MAC. Better on mobile. TLS 1.3 mandates only AEAD ciphersuites — a deliberate removal of all legacy modes.
The nonce (number used once) is critical: AES-GCM with a repeated nonce completely breaks confidentiality. TLS 1.3 derives per-record nonces from a sequence counter XORed into the IV, ensuring uniqueness.
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
key = AESGCM.generate_key(bit_length=256) # 32 bytes
aes = AESGCM(key)
nonce = os.urandom(12) # 96-bit nonce; NEVER reuse
plaintext = b"Hello, network!"
aad = b"record type 23" # Associated data: authenticated but NOT encrypted
ciphertext = aes.encrypt(nonce, plaintext, aad)
# ciphertext includes 16-byte GCM tag appended
recovered = aes.decrypt(nonce, ciphertext, aad)
assert recovered == plaintext
# If any bit in ciphertext or aad was flipped, decrypt raises InvalidTag
03Public-Key Cryptography and Diffie-Hellman Key Exchange
Symmetric ciphers solve encryption — if both parties share a key. But how do two strangers on a hostile network agree on a shared secret? This is the key-distribution problem, and it was unsolved until 1976 when Diffie and Hellman published their landmark paper.
Diffie-Hellman (DH) key exchange exploits the discrete logarithm problem. Both parties agree on public parameters: a large prime p and a generator g. Alice picks a secret a, sends g^a mod p. Bob picks a secret b, sends g^b mod p. Both can now compute g^(ab) mod p = shared secret. An eavesdropper sees g^a and g^b but cannot compute g^(ab) without solving the discrete log (believed exponentially hard).
Elliptic-Curve Diffie-Hellman (ECDH) replaces the multiplicative group with an elliptic curve group over a prime field. The same structure, but the discrete log on EC is harder — you can get equivalent security with much smaller keys (256-bit EC ≈ 3072-bit DH). TLS 1.3 uses X25519 (Curve25519, designed by Bernstein) as the default; it is fast, has no weak parameter choices, and is resistant to timing attacks.
Critically, basic DH is not authenticated: a man-in-the-middle can intercept both halves and establish separate shared secrets with each party. This is exactly the attack TLS certificates defeat — the server's DH public key is signed by its certificate, binding it to a verified identity.
Forward secrecy (Perfect Forward Secrecy, PFS): if Alice and Bob generate fresh ephemeral DH keys for every session (ECDHE), then recording all traffic and later stealing the server's long-term private key does not reveal any past sessions. The ephemeral keys are discarded after the handshake. TLS 1.3 requires ECDHE; TLS 1.2 with RSA key exchange (where the server's RSA key directly encrypts the premaster secret) has no forward secrecy.
# X25519 ECDHE key exchange — what TLS 1.3 does
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
# Client side (ephemeral)
client_priv = X25519PrivateKey.generate()
client_pub = client_priv.public_key()
# Server side (ephemeral)
server_priv = X25519PrivateKey.generate()
server_pub = server_priv.public_key()
# Exchange public keys over the wire (attacker sees these)
# Both sides derive the same shared secret:
client_shared = client_priv.exchange(server_pub)
server_shared = server_priv.exchange(client_pub)
assert client_shared == server_shared # 32-byte shared secret
# Neither side's private key is ever transmitted.
# Discard private keys after handshake => forward secrecy.
04The TLS 1.3 Handshake
TLS 1.3 (RFC 8446, 2018) is the protocol that runs HTTPS. It dramatically simplified TLS 1.2 by removing all legacy algorithms, reducing round-trips, and making forward secrecy mandatory. Understanding the handshake is essential.
1-RTT handshake (full):
- ClientHello: Client sends its TLS version, random nonce, list of supported cipher suites (only AEAD in 1.3), and a key_share — its ephemeral ECDH public key.
- ServerHello: Server picks the cipher suite, sends its own ephemeral ECDH public key. After this message, both sides can derive the handshake secret and all subsequent messages are encrypted.
- Server certificate + CertificateVerify: Server sends its X.509 certificate chain (encrypted!) and a signature over the handshake transcript using its private key. This is the authentication step.
- Server Finished: An HMAC over the entire handshake, keyed by the handshake secret.
- Client Finished: Same HMAC from the client side.
- Application data: Both parties have derived symmetric application traffic keys from the shared ECDH secret + randoms. Record layer begins.
0-RTT resumption: TLS 1.3 supports 0-RTT where the client sends data in the first flight using a Pre-Shared Key (PSK) from a previous session. The catch: 0-RTT data has no forward secrecy and is replay-vulnerable (the server may receive the same data twice). Use with caution and idempotent requests only.
Key derivation: TLS 1.3 uses HKDF (HMAC-based KDF) in an Extract-then-Expand pattern to derive distinct keys for handshake encryption, client traffic, server traffic, and export. The key schedule is a Merkle-Damgard-style tree of secrets, ensuring that compromising one secret doesn't cascade.
What TLS 1.3 removed from 1.2: RSA key exchange, CBC mode ciphers, RC4, SHA-1, MD5, static DH, renegotiation. Every removal was motivated by a known attack.
05X.509 Certificates and the Public Key Infrastructure (PKI)
The TLS handshake authenticates the server — but what does 'authenticate' mean? The server presents a certificate: a data structure containing its public key, its domain name (Common Name / Subject Alternative Names), validity dates, issuer, and a digital signature from a Certificate Authority (CA). Your browser trusts the certificate if and only if it can chain this signature back to a root CA in its trusted store.
Certificate chain: Server cert → signed by Intermediate CA → signed by Root CA. Root CAs are self-signed (turtles all the way down, stopped by your OS/browser trust store). Intermediate CAs exist so root private keys can stay offline in hardware security modules (HSMs).
X.509 fields you must know:
SubjectandIssuer: Distinguished Names (DN).Subject Alternative Name (SAN): the list of hostnames/IPs this cert covers. The CN field is deprecated for hostname validation.notBefore / notAfter: validity window. TLS clients must reject expired certs.Key UsageandExtended Key Usage: what the key may be used for (TLS server auth, code signing, etc.).CA:truein Basic Constraints: only CA certs may sign other certs. Enforcing this prevents a TLS server cert from being used to forge certificates.
How CAs are abused: In 2011, DigiNotar (a Dutch CA) was compromised and fraudulent certificates for google.com were issued, used in Iran to MITM hundreds of thousands of users. The CA was subsequently distrusted by all browser vendors and went bankrupt. This is the existential risk of the PKI.
Certificate Transparency (CT): Since 2018, all CAs must submit every issued certificate to append-only public CT logs (Merkle trees). Browsers require an SCT (Signed Certificate Timestamp) proving the cert is in a log. Domain owners can monitor logs for unauthorized certificates. CT does not prevent mis-issuance but makes it detectable.
Certificate Revocation: If a private key is stolen, the cert must be revoked. Mechanisms: CRL (Certificate Revocation List, a signed list — gets large), OCSP (Online Certificate Status Protocol, per-cert query — leaks browsing history to CA), OCSP Stapling (server bundles a fresh CA-signed OCSP response — best current practice). Chrome has moved to CRLSets (compressed, browser-curated lists of high-value revocations).
# Read a live certificate and inspect fields using Python
import ssl, socket, datetime
hostname = "example.com"
ctx = ssl.create_default_context()
with socket.create_connection((hostname, 443)) as sock:
with ctx.wrap_socket(sock, server_hostname=hostname) as ssock:
cert = ssock.getpeercert() # dict of parsed fields
print("Subject:", cert["subject"])
print("SANs:", cert["subjectAltName"]) # list of ('DNS', 'example.com')
print("Issuer:", cert["issuer"])
notafter = datetime.datetime.strptime(cert["notAfter"], "%b %d %H:%M:%S %Y %Z")
days_left = (notafter - datetime.datetime.utcnow()).days
print(f"Expires in {days_left} days")
06Notable TLS Attacks and Protocol Evolution
Every version of TLS carries the scars of real attacks. Studying them reveals how protocol design choices have consequences years later.
BEAST (Browser Exploit Against SSL/TLS, 2011): CBC in TLS 1.0 used the previous record's ciphertext as the next IV (chained CBC). This made it possible for a network attacker who could inject chosen plaintext (a JavaScript exploit) to recover cookies via a chosen-boundary attack. Fix: upgrade to TLS 1.1+ or use RC4 (itself broken). Real lesson: don't use predictable IVs.
Lucky 13 (2013): CBC padding validation in TLS took slightly different time depending on padding length, leaking information about decryption. Fix: constant-time padding verification. The attack is subtle — you need ~2^23 queries — but demonstrated that timing side-channels in crypto are real. Today's lesson: use AEAD instead.
POODLE (2014): Forced a TLS downgrade to SSL 3.0 (which is always CBC with known-bad padding semantics), then applied a padding oracle. Fix: disable SSL 3.0 entirely. Also revealed the danger of downgrade attacks — a MITM can interfere with the handshake to force older, weaker protocols. TLS 1.3 fixes this with a downgrade sentinel in the ServerHello random.
DROWN (2016): A server that shared its RSA key between TLS and SSLv2 was vulnerable: the SSLv2 export-grade crypto could be broken in hours (on AWS spot instances), revealing the RSA private key, then used to decrypt TLS 1.2 sessions retroactively (no forward secrecy). Fix: never share keys between protocol versions.
Heartbleed (CVE-2014-0160): Not a cryptographic attack — a C buffer over-read in OpenSSL's TLS Heartbeat extension. A malicious client sent a heartbeat request claiming a payload of 64KB but sending 1 byte; OpenSSL read 64KB of server memory (including private keys, session data, passwords). Fixed by a one-line bounds check. Lesson: crypto correctness is necessary but not sufficient — implementation bugs are equally dangerous.
Bleichenbacher's Attack (1998, still relevant): RSA-PKCS#1v1.5 decryption of a TLS premaster secret leaks whether the plaintext starts with the bytes 0x00 0x02 via error messages. An attacker can adaptively query the server ~1 million times to decrypt any recorded session. TLS 1.3 eliminates RSA key exchange entirely, closing this class of attack permanently.
07VPNs: Tunneling Encrypted Traffic
A Virtual Private Network (VPN) creates an encrypted tunnel between two endpoints, making the traffic opaque to the underlying network. There are two primary use cases: (1) corporate: connect remote employees to an internal network as if they were on-site; (2) privacy/bypass: encrypt all traffic from a device before it leaves a coffee shop or a censored country.
IPsec is the IETF standard for network-layer encryption. It operates in two modes:
- Transport mode: encrypts the payload of IP packets; IP headers are visible.
- Tunnel mode: encrypts the entire IP packet and wraps it in a new IP packet. This is VPN mode — the inner header carries the original destination, the outer header carries the VPN gateway.
IPsec uses two sub-protocols: AH (Authentication Header — integrity + auth, no encryption) and ESP (Encapsulating Security Payload — encryption + auth). Real VPNs use ESP in tunnel mode. Key exchange uses IKEv2 (Internet Key Exchange v2), which runs Diffie-Hellman and authenticates with certificates or PSK.
WireGuard (2020) is the modern replacement. It implements only one mode (tunnel), uses only Curve25519/ChaCha20-Poly1305/BLAKE2, has 4,000 lines of C (vs. ~400,000 for OpenVPN), is in the Linux kernel, and is faster. Its cryptographic handshake is based on the Noise Protocol Framework. WireGuard has no concept of certificate chains — peers are identified by their 32-byte public keys, configured out-of-band.
OpenVPN runs TLS over UDP (or TCP) and creates a tun/tap device. It is older, more configurable, and more audited for corporate deployments.
What a VPN does NOT do: it does not make you anonymous — the VPN provider sees all your traffic. It does not protect against endpoint compromise. It does not protect TLS-in-VPN traffic from the destination server. The trust model simply shifts: instead of trusting your ISP or the coffee shop network, you trust the VPN provider.
# WireGuard config snippet — peer configuration
# /etc/wireguard/wg0.conf on the client
[Interface]
PrivateKey = <client-private-key-base64> # Keep secret
Address = 10.0.0.2/24
DNS = 1.1.1.1
[Peer]
PublicKey = <server-public-key-base64> # 32 bytes, Curve25519
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0 # route ALL traffic through VPN
PersistentKeepalive = 25
# Authentication is purely key-based: if your public key is in
# the server's [Peer] list, you're in. No passwords, no certs.
08Firewalls and Stateful Packet Inspection
A firewall is a network policy enforcement point that decides which packets to forward and which to drop. The sophistication level ranges from simple to deep:
Packet filters (stateless): Inspect each packet in isolation: source/destination IP, source/destination port, protocol. Can block TCP port 22 from the internet. Cannot detect port-scan probes, connection hijacking, or protocols that negotiate ports dynamically (FTP, SIP). Linux iptables and BSD pf start here.
Stateful inspection (SPI): Tracks the state of every TCP connection (SYN_SENT, ESTABLISHED, FIN_WAIT, etc.) and every UDP pseudo-session. Allows you to write rules like "permit established TCP sessions initiated from the inside, block externally initiated connections to the same ports". Crucially, it can detect and drop TCP packets that don't belong to any tracked session — a common form of spoofed reset attack.
Application-layer gateways (ALGs): Parse the application layer. An FTP ALG understands the PORT command and dynamically opens the data connection port. An HTTP proxy ALG can inspect URLs and block based on content. This requires the firewall to partially implement each application protocol.
Next-generation firewalls (NGFW): Add deep packet inspection, TLS inspection (MITM inside corporate networks to inspect encrypted traffic), intrusion detection/prevention (IDS/IPS matching against known attack signatures), and user/application identity tracking.
TLS inspection controversy: Corporations often deploy TLS-intercepting firewalls that act as a MITM — they present a corporate CA certificate (installed on employee devices) and re-encrypt traffic to the internet. This breaks end-to-end security but allows policy enforcement. It requires trusting the firewall vendor's implementation of TLS.
Egress vs. ingress filtering: Ingress filtering drops packets with spoofed source IPs (BCP38) before they enter a network. Egress filtering limits outbound connections. Both are critical for DDoS mitigation.
Network segmentation: Firewalls enforce boundaries between network zones (DMZ for public-facing servers, internal for workstations, OT for industrial control). This limits blast radius: a compromised web server in the DMZ cannot directly reach the internal database.
# iptables rules illustrating stateful firewall policy
# (These are Linux kernel netfilter rules)
# Drop all INPUT by default
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Allow established/related traffic back in (stateful)
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Allow new inbound SSH only from management subnet
iptables -A INPUT -s 10.0.1.0/24 -p tcp --dport 22 \
-m conntrack --ctstate NEW -j ACCEPT
# Allow inbound HTTPS from anywhere
iptables -A INPUT -p tcp --dport 443 \
-m conntrack --ctstate NEW -j ACCEPT
# Allow loopback
iptables -A INPUT -i lo -j ACCEPT
# Everything else is dropped by the default policy
09DDoS Attacks and Amplification
A Distributed Denial of Service (DDoS) attack attempts to exhaust a target's resources (bandwidth, CPU, connection table, application threads) by flooding it with traffic from many sources. Modern volumetric attacks exceed 3 Tbps — no single upstream link can absorb them.
Amplification attacks exploit the asymmetry of stateless UDP protocols. An attacker spoofs the victim's source IP in a small request to a reflector. The reflector sends a large response to the victim. The amplification factor = response size / request size:
- DNS ANY queries: up to 70x amplification
- NTP monlist: up to 556x
- Memcached (port 11211, UDP): up to 51,000x (2018 GitHub attack: 1.35 Tbps)
- QUIC version negotiation: up to 46x
Amplification works at scale because the internet has millions of misconfigured open resolvers / NTP servers. BCP38 (network ingress filtering) would prevent IP spoofing but is not universally deployed.
TCP SYN flood: Attacker sends millions of TCP SYN packets from spoofed IPs. Server allocates state for each half-open connection. Connection table exhausts. Mitigation: SYN cookies — server encodes the connection state in the sequence number (a crypto hash of (IP, port, timestamp)), allocates no memory until the ACK arrives.
Application-layer (L7) DDoS: Sends valid-looking HTTP requests that are expensive to serve (search queries, large file downloads, login attempts). Harder to filter because traffic looks legitimate. Mitigated by rate-limiting, CAPTCHAs (Cloudflare Turnstile), bot fingerprinting, and IP reputation.
Anycast for defense: CDNs and DNS services (Cloudflare, Akamai) announce the same IP prefix from PoPs worldwide via BGP Anycast. An attack is naturally distributed across all PoPs — each PoP absorbs its fraction of the flood. Combined with scrubbing centers (traffic is routed through DPI that drops attack packets), this is how Cloudflare absorbs 2+ Tbps attacks without major impact.
QUIC's amplification resistance: QUIC (HTTP/3 transport) requires that the server not send more than 3x the bytes received until the client address is validated — a protocol-level mitigation.
# Demonstrate SYN cookie concept (pseudocode)
import hmac, hashlib, time
SECRET = b"server-secret-key"
def make_syn_cookie(src_ip, src_port, dst_port) -> int:
"""
Encode connection params in the ISN (Initial Sequence Number).
Server sends this as its SYN-ACK sequence number.
No memory allocated until client ACKs with ISN+1.
"""
timestamp = int(time.time()) >> 6 # 64-second resolution
data = f"{src_ip}:{src_port}:{dst_port}:{timestamp}".encode()
mac = hmac.new(SECRET, data, hashlib.sha256).digest()[:4]
seq = (timestamp & 0x1F) << 27 | int.from_bytes(mac[:3], 'big')
return seq & 0xFFFFFFFF
def verify_syn_cookie(src_ip, src_port, dst_port, ack_num) -> bool:
# Client sends ack_num = cookie + 1
cookie = ack_num - 1
timestamp = (cookie >> 27) & 0x1F
# verify MAC matches; accept slight clock skew
for skew in (0, -1):
t = (int(time.time()) >> 6) & 0x1F
if make_syn_cookie(src_ip, src_port, dst_port) == cookie:
return True
return False
10Secure Application-Layer Protocols
TLS is the foundation, but several application-layer protocols add important security properties on top.
SSH (Secure Shell): Provides authenticated remote shell access over an encrypted channel. Uses its own key exchange (Diffie-Hellman or ECDH), then symmetric encryption. Authentication is either password-based or public-key: the server stores the client's public key in ~/.ssh/authorized_keys; the client signs a challenge. SSH does not use a PKI — instead, it uses Trust On First Use (TOFU): the first time you connect to a host, you accept its host key fingerprint and store it. Subsequent connections verify the key matches. This is simple but vulnerable to MITM on the first connection.
DNSSEC: DNS responses are unauthenticated by default — a MITM can return forged DNS records (DNS cache poisoning, Kaminsky attack 2008). DNSSEC adds digital signatures to DNS records, chained from a root trust anchor. Resolvers verify signatures. However, DNSSEC does not encrypt DNS queries (ECDH negotiation is not done). DNS over TLS (DoT) and DNS over HTTPS (DoH) add confidentiality — your ISP cannot see which domains you query.
Signal Protocol (Double Ratchet): Messaging apps (Signal, WhatsApp, FB Messenger secret conversations) use the Double Ratchet algorithm: an Extended Triple Diffie-Hellman (X3DH) initial key exchange establishes a root key; then two ratchets (a DH ratchet regenerating the root key on each message round-trip, and a symmetric hash ratchet for per-message keys) provide both forward secrecy and break-in recovery (if an adversary learns a message key, they cannot decrypt future messages once the ratchet advances). This is far more sophisticated than TLS, which only provides forward secrecy at the session level.
HTTPS Strict Transport Security (HSTS): A server sends Strict-Transport-Security: max-age=31536000; includeSubDomains in an HTTP response. The browser then refuses to connect over plain HTTP for that domain for the specified duration, preventing SSL stripping attacks. HSTS Preload lists (baked into browsers) protect even the first connection.
Certificate Pinning: An app can hard-code the expected certificate or SPKI hash for its server, refusing connections to any other certificate — even if the CA is trusted. Used by high-security apps (banking, Signal). Risk: if you pin and your cert expires/changes, users are locked out until they update the app. Today the preferred approach is CAA DNS records (Certification Authority Authorization) + CT monitoring rather than pinning.
# Check if a domain has HSTS and DNSSEC configured
import requests, dns.resolver, dns.dnssec
resp = requests.get("https://example.com", timeout=5)
hsts = resp.headers.get("Strict-Transport-Security", None)
print("HSTS header:", hsts)
# e.g. "max-age=31536000; includeSubDomains; preload"
# Check for DNSSEC: look for RRSIG records on the domain
try:
answers = dns.resolver.resolve("example.com", "RRSIG")
print("DNSSEC: signed, RRSIG present")
except dns.resolver.NoAnswer:
print("DNSSEC: no RRSIG — zone not signed")
# Full DNSSEC validation requires chain-of-trust from root
11PKI Trust and Certificate Transparency
The web PKI is perhaps the most critical piece of security infrastructure on the internet, and also one of the most fragile. Understanding its trust model — and its failure modes — is essential for any security practitioner.
The fundamental problem: Any of the ~150 root CAs trusted by Chrome can issue a certificate for any domain. If a CA is compromised or coerced by a government, fraudulent certificates can enable MITM attacks against any website. This is not theoretical: DigiNotar (2011), ANSSI (2013, issued wildcard for google.com for a corporate proxy), and several others have issued unauthorized certificates.
Certificate Transparency (RFC 6962): CAs must submit every certificate to at least two public CT logs before it is accepted by Chrome. CT logs are append-only Merkle trees: each entry is a certificate, and the tree root hash is signed by the log operator. The Signed Certificate Timestamp (SCT) in a certificate proves it was submitted. Domain owners can monitor all CT logs for their domains using services like crt.sh.
The Merkle tree property: Auditors can prove that a specific certificate is in the log (inclusion proof: O(log n) hashes) and that the log has not been altered retroactively (consistency proof: two root hashes are consistent if the tree only had appends). This gossip-and-audit scheme detects dishonest CAs within hours.
Certification Authority Authorization (CAA) DNS records: A domain owner can publish example.com CAA 0 issue "letsencrypt.org" in DNS, restricting which CAs may issue certificates for their domain. CAs are required to check CAA before issuance. An attacker who can forge DNS could bypass this, but with DNSSEC the CAA record is authenticated.
Let's Encrypt: A free, automated CA (operated by ISRG) that issues 90-day certificates via the ACME protocol. The ACME protocol proves domain control by having the CA fetch a token from a known URL on the domain or a DNS TXT record. It has democratized HTTPS — certificate cost is no longer a barrier. The 90-day lifetime forces automation and limits the window of a stolen certificate.
Post-quantum concerns: RSA and ECDSA are broken by Shor's algorithm on a sufficiently large quantum computer. NIST is standardizing post-quantum algorithms: CRYSTALS-Dilithium (lattice-based signatures, now FIPS 204) and CRYSTALS-Kyber (lattice-based KEM, now FIPS 203). TLS can be extended with hybrid key exchange (classical ECDH + post-quantum KEM) to provide protection against harvest-now-decrypt-later attacks.
# Query crt.sh CT log search API for recent certs for a domain
import requests
domain = "example.com"
url = f"https://crt.sh/?q={domain}&output=json"
resp = requests.get(url, timeout=10)
certs = resp.json()
for c in certs[:5]:
print(f"ID: {c['id']} Issuer: {c['issuer_name'][:60]}")
print(f" NotBefore: {c['not_before']} NotAfter: {c['not_after']}")
print(f" Names: {c['name_value'][:80]}")
print()
# Any cert you did NOT authorize appearing here is a mis-issuance incident.
Key insights
- ✦TLS 1.3 mandates ECDHE and AEAD — two design choices that, together, give forward secrecy and eliminate entire classes of attacks (padding oracles, CBC timing attacks) that plagued TLS 1.2.
- ✦The PKI's Achilles heel is that ANY trusted root CA can issue ANY certificate. Certificate Transparency does not prevent mis-issuance — it makes it publicly detectable, shifting the model from 'trust and hope' to 'verify and audit'.
- ✦Amplification attacks are fundamentally a spoofing problem: BCP38 ingress filtering, if universally deployed, would eliminate the entire class. The tragedy is that the benefit is external (the victim), while the cost is internal (the reflector's ISP).
- ✦Encryption without authentication is not secure. AES-CTR alone lets an attacker flip bits in plaintext; only AEAD (encrypt-then-MAC) gives you both confidentiality and integrity simultaneously.
- ✦SYN cookies elegantly solve the SYN flood problem by making the server stateless for half-open connections — a beautiful example of encoding state in cryptographic tokens rather than memory.
- ✦The Double Ratchet (Signal) achieves something TLS does not: per-message forward secrecy AND break-in recovery. TLS forward secrecy is per-session; Signal's is per-message.
- ✦90-day certificate lifetimes (Let's Encrypt) are a security feature: they force automation, limit the window during which a stolen cert is usable, and ensure rapid algorithm rollout when cryptography must change.
- ✦Post-quantum cryptography is not a future concern — the 'harvest now, decrypt later' threat means adversaries are storing TLS traffic today to decrypt once quantum computers exist. Deploying hybrid key exchange now is the correct response.
Common pitfalls
- ⚠Confusing confidentiality with authentication: 'I'm using AES so the server is verified' is wrong. TLS encryption and server authentication are separate mechanisms — the certificate is what authenticates, the cipher is what encrypts.
- ⚠Reusing an AEAD nonce: In AES-GCM, sending two records with the same nonce and key completely breaks confidentiality and allows forgery. TLS 1.3 derives nonces from sequence numbers to prevent this; rolling your own crypto will get this wrong.
- ⚠Treating a VPN as anonymity: A VPN shifts trust from your ISP to the VPN provider, who now sees all your traffic. It is not anonymity — it is trust relocation.
- ⚠Ignoring certificate revocation: A stolen certificate is valid until expiry unless revocation is checked. Not all clients check OCSP; OCSP Stapling is the best current practice to ensure revocation information is always delivered.
- ⚠Confusing TLS 1.2 and TLS 1.3 security properties: TLS 1.2 with RSA key exchange has no forward secrecy. Only ECDHE cipher suites in 1.2 (and all of 1.3) provide PFS. Many server configurations still allow RSA key exchange for compatibility.
- ⚠Assuming DDoS mitigation is purely network-level: Application-layer DDoS (slow POST, Slowloris, search-query floods) requires L7 inspection, rate limiting, and behavioral analysis — packet-rate thresholds alone will not catch it.
- ⚠Thinking HTTPS protects the full path: TLS encrypts the channel between client and server. If your server forwards to a backend over plain HTTP inside a data center, the traffic is exposed there. End-to-end encryption requires TLS at every hop.
Practice
- 01medium
Implement a minimal authenticated key exchange: Alice and Bob run X25519 ECDH, then use HKDF to derive a 32-byte symmetric key, then exchange a test message with AES-256-GCM. No TLS library — build from the cryptography primitives. Verify that a man-in-the-middle who only sees the public keys and the ciphertext cannot recover the plaintext.
- 02easy
Analyze a real TLS handshake: use `openssl s_client -connect google.com:443 -msg -tlsextdebug 2>&1` and identify in the output: (a) which ECDH curve was negotiated, (b) the cipher suite selected, (c) the certificate chain depth, (d) whether an SCT was delivered. Then repeat against a server still offering TLS 1.2 and note the differences.
- 03hard
Padding oracle attack from scratch: Implement a CBC padding oracle — a function that decrypts a ciphertext and returns True if the PKCS#7 padding is valid, False otherwise. Then write the attack: given a two-block ciphertext (IV || C1), recover the plaintext block P1 by adaptively querying the oracle ~128 times per byte (O(16 * 256) queries total). This is the POODLE/Lucky-13 attack class.
- 04medium
Write a script that scans your local network for open DNS resolvers (port 53/UDP) that respond to ANY queries with amplification > 5x. Measure the amplification factor for each. What fraction of your local network is vulnerable? (Do this only on networks you own or have permission to test.)
- 05easy
Certificate Transparency audit: write a script that queries crt.sh for all certificates issued for a domain you own (or use a test domain). For each certificate, check: (a) is the issuer expected? (b) is the notAfter within 90 days of issuance (Let's Encrypt pattern)? (c) are there any SANs that you did not request? Alert on any anomaly. This is the CT monitoring workflow a security team should run daily.
- 06hard
Forward secrecy measurement: set up a simple TLS 1.2 server (using Python's `ssl` module) configured with an RSA certificate and a static RSA key-exchange cipher suite (no ECDHE). Use Wireshark to capture a session. Then extract the server's RSA private key and use `ssldump` or a custom decryption script to decrypt the captured traffic. Repeat with an ECDHE cipher suite and observe that the private key alone is insufficient to decrypt past sessions.
Resources
Checkpoints — you can now…
- ✓You can narrate the TLS 1.3 handshake from ClientHello to first application byte, naming the role of ECDHE, the certificate signature, and HKDF at each step.
- ✓You can explain why AES-CBC is no longer acceptable in TLS and what property of AEAD (AES-GCM, ChaCha20-Poly1305) solves the padding oracle vulnerability.
- ✓You can describe what a Certificate Authority is, how a certificate chain is verified, and what Certificate Transparency adds to prevent CA misbehavior.
- ✓You can explain forward secrecy: why a server using static RSA key exchange has none, and why ECDHE gives it, and what an adversary can and cannot do given a recorded session and a later key compromise.
- ✓You can explain DNS amplification attacks: why spoofed UDP enables them, what the amplification factor is, and why BCP38 and response-rate limiting are mitigations.
- ✓You can compare IPsec/WireGuard/OpenVPN on the dimensions of: which layer they operate at, how authentication works, and what threat model they address.
- ✓You can read a Wireshark TLS capture and identify: the cipher suite, the certificate chain, and whether the session has forward secrecy.