🧱 07-03: AES and Block Cipher Modes¶
📌 What Is AES?¶
AES (Advanced Encryption Standard) is the symmetric encryption algorithm (see 07-02: Symmetric Encryption Basics) that replaced DES in 2001, after a public competition run by the U.S. National Institute of Standards and Technology (NIST). It is currently the world's default choice for encrypting data at rest and in transit — used in Wi-Fi (WPA2/WPA3), TLS/HTTPS, disk encryption, VPNs, and far more.
| Property | AES |
|---|---|
| Block size | 128 bits (fixed, regardless of key size) |
| Key sizes | 128, 192, or 256 bits |
| Structure | Substitution-permutation network — 10/12/14 rounds of scrambling depending on key size |
| Status today | Considered secure; no practical attack breaks full AES |
💡 "AES-256" means AES using a 256-bit key. Bigger key = more possible keys to brute-force = more secure, but also slightly slower. AES-128 is already considered secure enough for virtually all purposes; AES-256 is used when organizations want an extra safety margin (e.g., against unknown future attacks or quantum computing advances).
🧊 What "Block Cipher" Means¶
AES is a block cipher: it doesn't encrypt data as one continuous stream. Instead, it chops the plaintext into fixed-size chunks — 128-bit blocks (16 bytes) — and encrypts each block independently using the key.
Plaintext: "This is a secret message that is longer than one block!"
Split into 16-byte blocks:
Block 1: "This is a secre"
Block 2: "t message that "
Block 3: "is longer than "
Block 4: "one block!" + padding
Each block goes through the same encryption process using the same key, producing a corresponding ciphertext block.
💡 If your plaintext isn't an exact multiple of 16 bytes, it gets padded (extra bytes appended following a defined scheme) so the final block is still full-size. This is a small detail, but it matters — padding mistakes have historically caused real vulnerabilities (e.g., "padding oracle" attacks against poorly implemented systems).
The interesting — and dangerous — question is: what do you do when you have more than one block? That's what "block cipher modes" answer.
🐧 ECB Mode: The Insecure Default¶
The simplest possible approach is ECB (Electronic Codebook) mode: encrypt every block independently, using the exact same key, with no relationship between blocks.
Ciphertext Block 1 = AES_encrypt(Plaintext Block 1, key)
Ciphertext Block 2 = AES_encrypt(Plaintext Block 2, key)
Ciphertext Block 3 = AES_encrypt(Plaintext Block 3, key)
This sounds fine — each block is properly encrypted with a strong algorithm — but it has a fatal flaw: identical plaintext blocks always produce identical ciphertext blocks.
The "ECB Penguin"¶
This flaw became famous through a simple demonstration: take an image of a penguin (a bitmap with large areas of solid, repeated color), encrypt the raw image data with AES in ECB mode, and look at the result.
Original image: [clearly a penguin silhouette on a solid background]
ECB-encrypted: [STILL clearly a penguin silhouette — just recolored]
CBC-encrypted: [pure random-looking static, no shape visible at all]
Because large areas of the image are made of repeating identical pixel patterns, and ECB maps identical input blocks to identical output blocks, the shape of the original image survives encryption completely intact — only the colors change. An attacker doesn't need to break the cipher at all to learn the outline of a "secret" image; the structure just leaks straight through.
💥 This is why ECB should never be used for anything beyond a single block of data. Any data with repeated patterns — images, structured records, database fields — leaks its structure under ECB.
🔗 CBC Mode: Chaining Blocks Together¶
CBC (Cipher Block Chaining) fixes ECB's flaw by making each block's encryption depend on the block before it, so identical plaintext blocks no longer produce identical ciphertext.
Block 1: Ciphertext_1 = AES_encrypt(Plaintext_1 XOR IV, key)
Block 2: Ciphertext_2 = AES_encrypt(Plaintext_2 XOR Ciphertext_1, key)
Block 3: Ciphertext_3 = AES_encrypt(Plaintext_3 XOR Ciphertext_2, key)
- XOR is a bitwise operation that mixes two values together (it flips bits where the inputs differ).
- IV (Initialization Vector): a random, non-secret value used only for the first block, so that encrypting the exact same message twice with the exact same key still produces completely different ciphertext each time.
💡 The IV does not need to be secret — it's typically sent alongside the ciphertext in plaintext — but it must be random and unique for every encryption. Reusing an IV with the same key reintroduces patterns similar to ECB's weakness.
| Mode | Identical blocks → identical ciphertext? | Needs IV? | Verdict |
|---|---|---|---|
| ECB | Yes (insecure) | No | ❌ Avoid |
| CBC | No | Yes | ✅ Better, but only provides confidentiality |
CBC solves the pattern-leakage problem, but it still only provides confidentiality — it says nothing about whether the ciphertext was tampered with in transit. An attacker who can't read the message might still be able to flip bits in it and cause predictable, undetected corruption. That's where the next mode comes in.
🛡️ GCM Mode: Encryption + Integrity Together¶
GCM (Galois/Counter Mode) is the mode used by most modern protocols, including TLS 1.3. It's an AEAD mode — Authenticated Encryption with Associated Data — meaning it provides confidentiality and integrity/authenticity in a single operation.
AES-GCM encryption produces two outputs:
1. Ciphertext -> the encrypted data (confidentiality)
2. Authentication tag -> a short cryptographic checksum (integrity + authenticity)
On decryption, the recipient recomputes the expected tag from the received ciphertext and key. If it doesn't match the tag that was sent, the data is rejected outright — the receiver knows for certain it was tampered with, without needing a separate integrity check bolted on afterward.
| Mode | Confidentiality | Integrity/Authenticity | Used in |
|---|---|---|---|
| ECB | Weak (pattern leakage) | No | Essentially nowhere (insecure) |
| CBC | Yes | No (needs a separate MAC) | Older TLS versions, disk encryption |
| GCM | Yes | Yes, built in | TLS 1.2/1.3, IPsec, modern VPNs |
💡 Before AEAD modes existed, protocols had to bolt integrity on separately — encrypt with CBC, then compute a separate message authentication code (MAC, covered in 07-06: Hashing & Message Integrity) over the ciphertext. Getting the order of those two steps wrong caused real, exploited vulnerabilities in early TLS. GCM avoids the whole problem by doing both at once, correctly, by design — which is a big part of why it's the default choice in TLS 1.3.
📌 Key Takeaways¶
- AES is the modern standard symmetric cipher: 128-bit fixed block size, with 128/192/256-bit key options.
- A block cipher encrypts data in fixed-size chunks (blocks), not as a continuous stream — data must be split (and padded) into blocks first.
- ECB mode encrypts each block independently with no chaining, so identical plaintext blocks always produce identical ciphertext — the "ECB penguin" demonstrates how this leaks the structure of the original data.
- CBC mode chains blocks together using XOR and a random IV, eliminating ECB's pattern leakage, but still provides confidentiality only — no built-in tamper detection.
- GCM mode is an AEAD mode that provides both confidentiality and integrity/authenticity in one step, producing ciphertext plus an authentication tag that detects any tampering.
- GCM is the mode used by TLS 1.2/1.3 and modern VPNs — it's the practical default for new systems.
- Never use ECB mode for anything beyond encrypting a single, unique, unstructured block.
- These modes only provide confidentiality (and sometimes integrity) — they say nothing about how the key was shared in the first place, which is why key exchange (Diffie-Hellman) and asymmetric encryption (RSA) are still needed alongside AES.