Chapter 05 // Primitives

Symmetric
Encryption

You know where keys come from. You know how to verify integrity. Now comes the core promise of cryptography: hiding data so that only someone with the right key can read it.

Scroll to explore
01 // The Core Problem

Turning secrets into gibberish

Encryption transforms readable data into something indistinguishable from random noise. Symmetric encryption means both sender and receiver share the same key. It is the oldest and still the most widely used form of encryption.

What "symmetric" means

One key encrypts. The same key decrypts. Both parties must have it, and nobody else can. This is different from asymmetric cryptography (Chapter 9), where encryption and decryption use different keys.

Symmetric encryption is what AES does. It protects your disk (FileVault, BitLocker), your HTTPS traffic (TLS), your messages (Signal, WhatsApp), and your VPN tunnels. Everything starts here.

The encryption contract

A good symmetric cipher gives you three guarantees. Confidentiality: when used correctly (with a proper mode of operation), the ciphertext reveals nothing about the plaintext without the key. Uniqueness: different plaintexts produce different ciphertexts. Reversibility: decrypting with the correct key always recovers the original.

Notice what is not promised. Encryption alone does not tell you whether someone tampered with the ciphertext. An attacker can flip bits, rearrange blocks, or truncate the message, and decryption will happily produce garbage without raising an alarm. That problem is solved in Chapter 6.

02 // The Building Block

Block ciphers: one block at a time

A block cipher encrypts a fixed-size chunk of data using a key. AES operates on 128-bit (16-byte) blocks. It is a permutation: every possible input maps to a unique output, and the process reverses with the same key.

AES: the standard

The Advanced Encryption Standard (AES) is the universally used block cipher. It supports key sizes of 128, 192, and 256 bits. Modern CPUs have dedicated hardware instructions that make AES essentially free in terms of performance.

Internally, AES applies multiple rounds of substitution, shifting, and XOR mixing. After 10+ rounds, changing a single input bit avalanches across every output bit. Same principle as hash functions, applied as a reversible transformation.

📦

Fixed Block Size

AES always processes exactly 16 bytes at a time. Longer messages need a mode of operation to handle multiple blocks. Shorter messages need padding.

🔀

Key-Dependent Scrambling

With one key, AES maps each possible 128-bit input to a unique 128-bit output. A different key produces a completely different mapping. The key is the secret.

🎯

Deterministic

Same key plus same plaintext block always equals the same ciphertext block. This is by design, but it creates a serious problem when encrypting multiple blocks independently.

03 // Try It Yourself

Encrypt and decrypt with AES

Type a message, pick a mode, and watch the ciphertext update in real time. Don't worry about what CBC and CTR mean yet. They are explained in Section 06. For now, just notice how changing a single character transforms the entire ciphertext.

AES Encryption Playground

Type a message, pick a mode, and watch the ciphertext update in real time. Change a single character and see how the entire output changes.

Key (256-bit)
 
IV (128-bit)
49605141fcf99f3407849ccf986b98dd
Ciphertext (0 bytes) 

CBC adds PKCS#7 padding so the ciphertext is always a multiple of 16 bytes. A 20-byte message produces 32 bytes of ciphertext.

04 // The Danger

Why encrypting blocks independently fails

AES encrypts one 16-byte block at a time. The simplest approach is to encrypt each block separately. This is called ECB mode (Electronic Codebook). It is catastrophically insecure for almost all real data.

The ECB problem

Because AES is deterministic, identical plaintext blocks produce identical ciphertext blocks. If your message contains repeated patterns (and real data almost always does), those patterns survive encryption unchanged.

The classic demonstration: encrypt a bitmap image in ECB mode. The colors are scrambled, but the shape is perfectly visible. The structure of the data leaks through because identical pixel blocks map to identical ciphertext blocks. This is not encryption in any meaningful sense.

Stream ciphers: a different approach

Instead of encrypting blocks independently, a stream cipher generates a keystream (a sequence of random-looking bytes) from the key and a nonce, then XORs it with the plaintext byte by byte (recall XOR from Chapter 1). This is what AES-CTR mode does: it turns the AES block cipher into a stream cipher.

Each block position gets a unique counter value. The counter is encrypted to produce keystream, and the keystream is XORed with the plaintext. No padding needed. Ciphertext is the same length as plaintext. But the nonce must never repeat with the same key, as we saw in Chapter 4.

05 // See the Difference

Patterns that survive encryption

Type a message with repeating blocks. In ECB mode, identical plaintext blocks produce identical ciphertext blocks. In CBC mode, chaining makes every block unique. The difference is immediate.

ECB vs CBC: Pattern Leakage

Identical plaintext blocks produce identical ciphertext in ECB mode. In CBC mode, chaining makes every block unique.

Plaintext blocks (4 x 16 bytes)
P1
AAAAAAAAAAAAAAAA
P2
AAAAAAAAAAAAAAAA
P3
AAAAAAAAAAAAAAAA
P4
AAAAAAAAAAAAAAAA
ECB ciphertext
CBC ciphertextAll unique
06 // How It Works

Modes of operation

A block cipher alone can only encrypt 16 bytes. A mode of operation defines how to encrypt messages of any length. The choice of mode determines whether patterns leak, whether you need padding, and what happens when things go wrong.

CBC (Cipher Block Chaining)

Each plaintext block is XORed with the previous ciphertext block before encryption. The first block is XORed with a random IV (initialization vector). This chains blocks together: even identical plaintext blocks produce different ciphertext because each one depends on everything before it.

CBC requires padding (extra bytes added to the last block to fill it to 16 bytes, which the receiver knows how to strip). The IV must be random and unpredictable for each encryption. It does not need to be secret, just unique. CBC is sequential: you cannot encrypt block N without first encrypting block N-1.

CTR (Counter)

AES encrypts a counter (nonce combined with block number) to produce a keystream. The keystream is XORed with the plaintext. This turns AES into a stream cipher. No padding needed. Ciphertext is the same length as plaintext.

CTR can be parallelized because each block uses an independent counter. It also allows random access: you can decrypt block 47 without touching blocks 0-46. The nonce must never repeat with the same key. Encryption and decryption are the same operation, since both just XOR with the keystream.

07 // Step by Step

Watch the modes in action

Step through ECB, CBC, and CTR to see how each mode processes blocks. Watch how blocks connect (or don't) and understand the trade-offs.

Block Cipher Modes Visualizer

Step through each mode to see how plaintext blocks become ciphertext. Watch the connections between blocks.

Key
P1
AES
C1
P2
AES
C2
P3
AES
C3
Step 1 of 8

Start with 3 plaintext blocks and a key.

08 // The Missing Piece

Encryption without integrity is dangerous

Symmetric encryption hides your data. But it does not prevent an attacker from modifying the ciphertext. With CBC, an attacker can flip specific bits in the decrypted plaintext without knowing the key.

How CBC bit-flipping works

In CBC decryption, each plaintext block is produced by decrypting the ciphertext block and XORing with the previous ciphertext block. If an attacker flips bit N in ciphertext block K, then bit N flips in plaintext block K+1 (predictably), while plaintext block K becomes completely garbled (unpredictably).

An attacker who knows the plaintext of block K+1 can calculate exactly which bits to flip to produce any desired modification. Changing "admin=false" to "admin=true" is a matter of XORing the right bytes. No key required.

Real-world consequences

Real attacks have exploited this. If a server reveals whether decrypted padding is valid (through error messages or timing differences), an attacker can use that feedback to decrypt traffic one byte at a time, without ever knowing the key.

The fundamental issue: encryption alone does not tell you whether the ciphertext was modified. The decryption function will happily process tampered data and return corrupted plaintext without complaint.

This is exactly why Chapter 6 exists. Authenticated encryption (AES-GCM) combines encryption with a MAC. Any modification to the ciphertext is detected and rejected before decryption. Never use AES-CBC or AES-CTR without also applying a MAC.

09 // Attack Demo

Flip bits, change the message

Encrypt a message with AES-CBC. Then modify a byte in the ciphertext and see how the decrypted plaintext changes. The attacker does not need the key.

CBC Bit-Flipping Attack

Click a byte in the ciphertext to flip it. Block 0 will be garbled, but block 1 gets a precise, targeted modification. The attacker needs no key.

Original plaintext
role=user;admin=false;id=123456789;session=valid
Ciphertext (click a byte to flip it)
0x00XOR 0x15= 0x15
0x000x150xFF
Original decryption
Modified decryption
10 // Best Practices

Using symmetric encryption correctly

The algorithm is the easy part. Getting the details right is where systems break.

🛡️

Use AES-GCM, Not CBC or CTR Alone

Authenticated encryption prevents tampering. We cover this in the next chapter. If you must use CBC or CTR, always pair it with HMAC.

🔢

Never Reuse (Key, IV/Nonce) Pairs

For CBC, generate a random 16-byte IV per encryption. For CTR, generate a random nonce per encryption. Reuse breaks everything, as we saw in Chapter 4.

🔑

Use 256-Bit Keys

AES-128 is still considered secure, but AES-256 provides a larger safety margin. There is no meaningful performance difference on modern hardware with built-in AES acceleration.

🚫

Do Not Implement Your Own AES

Use your platform's built-in crypto library. Correct implementations must protect against timing attacks and other subtle leaks, which is extremely difficult to get right from scratch.

Up Next

Chapter 06 // Authenticated Encryption

Continue Learning