Goal

Master symmetric encryption with AES: understand encryption modes (and why ECB is broken), use OpenSSL for file encryption, and learn how Key Derivation Functions transform weak passwords into strong keys.

Prerequisites: Week 2a (Hash Functions)

This is Part 2 of 3 - Covers symmetric encryption and key derivation.


1. Symmetric Encryption: Shared Secrets

What Is Symmetric Encryption?

Symmetric encryption uses the same key for both encryption and decryption.

Alice                                    Bob
  |                                       |
  | "Meet at midnight" + Key123          |
  |---------> AES Encrypt --------------> |
  |     f8a3b2c1d4e5f6 (ciphertext)      |
  |                                       |
  | <-------- AES Decrypt <-------------- |
  |      f8a3b2c1d4e5f6 + Key123         |
  |  "Meet at midnight" (plaintext)      |

Key challenge: How do Alice and Bob agree on “Key123” without anyone else learning it? (Solved in Week 3 with asymmetric crypto)

AES: The Gold Standard

Advanced Encryption Standard (AES) is the most widely used symmetric cipher.

Key facts:

  • Adopted by US government in 2001
  • Replaced older DES (Data Encryption Standard)
  • Block cipher: Encrypts data in 128-bit chunks
  • Key sizes: 128-bit, 192-bit, or 256-bit (recommended)
  • Unbroken after 20+ years of analysis

How secure is AES-256?

  • 2^256 possible keys
  • At 1 billion keys per second, brute force would take ≈3.67 × 10^60 years
  • Universe is only 13.8 billion years old
  • Conclusion: AES-256 is computationally unbreakable with current technology

Stream Ciphers vs Block Ciphers

Block Cipher (AES):

  • Encrypts fixed-size blocks (128 bits)
  • Requires padding for data not perfectly divisible by block size
  • Needs “mode of operation”

Stream Cipher (ChaCha20):

  • Encrypts data byte-by-byte
  • No padding needed
  • Often faster on devices without hardware AES acceleration

When to use each:

  • AES: General purpose, hardware accelerated on modern CPUs
  • ChaCha20: Mobile devices, embedded systems (faster without AES-NI)

2. Encryption Modes: How Block Ciphers Handle Data

AES encrypts 128-bit blocks, but files are arbitrary sizes. Modes of operation define how to encrypt multiple blocks.

ECB (Electronic Codebook) - NEVER USE

Block 1 → AES → Cipher 1
Block 2 → AES → Cipher 2  (Encrypted independently - BAD!)
Block 3 → AES → Cipher 3

Why it’s broken:

  • Same plaintext block always produces same ciphertext block
  • Patterns in data leak through encryption
  • Famous example: ECB Penguin

CBC (Cipher Block Chaining) - Legacy

IV → XOR → AES → Cipher 1
      ↑            ↓
   Block 1      XOR → AES → Cipher 2
                     ↑        ↓
                  Block 2   Cipher 3...

Features:

  • Each block depends on previous block (no patterns)
  • Requires Initialization Vector (IV) - random starting value
  • Vulnerable to padding oracle attacks if implemented incorrectly
  • Still widely used but being phased out
Counter → AES → XOR → Cipher 1
             ↑     ↑
          Block 1  |
                   |
          Authentication Tag (prevents tampering)

Features:

  • Authenticated encryption - detects tampering automatically
  • Parallel encryption (faster on multi-core CPUs)
  • Industry standard for modern applications
  • Used in TLS 1.3, SSH, disk encryption

Bottom line: Use AES-256-GCM unless you have a specific reason not to.


3. Hands-On: Encryption with OpenSSL

Basic File Encryption (CBC Mode)

# Encrypt a file with password
openssl enc -aes-256-cbc -salt -in secret.txt -out secret.enc
# You'll be prompted to enter a password

# Decrypt the file
openssl enc -d -aes-256-cbc -in secret.enc -out decrypted.txt
# Enter same password

# Verify decryption worked
diff secret.txt decrypted.txt  # Should output nothing (files identical)

What’s happening:

  • enc - Encryption/decryption operation
  • -aes-256-cbc - Algorithm and mode
  • -salt - Adds randomness to prevent rainbow table attacks
  • -in / -out - Input and output files
  • -d - Decrypt flag

Encryption with Key File

# Generate a 256-bit key as base64 TEXT. (Subtle trap: `-pass file:` reads only
# the FIRST LINE of the file, so a raw binary key containing a 0x0A newline byte
# would be silently truncated. Base64 is one clean line, so it's safe.)
openssl rand -base64 32 > aes.key

# Encrypt using the key file as a passphrase, with PBKDF2 key stretching
openssl enc -aes-256-cbc -pbkdf2 -in secret.txt -out secret.enc -pass file:./aes.key

# Decrypt using the key file
openssl enc -d -aes-256-cbc -pbkdf2 -in secret.enc -out decrypted.txt -pass file:./aes.key

# CRITICAL: Protect your key file!
chmod 600 aes.key  # Only you can read/write

Modern Authenticated Encryption (AEAD)

The CBC command above encrypts but does not authenticate — if someone tampers with the ciphertext, it can still “decrypt” into garbage with no error. Authenticated encryption (AEAD) — such as AES-256-GCM or ChaCha20-Poly1305 — adds an integrity tag so any tampering is detected at decryption time.

⚠️ OpenSSL’s enc command cannot do AEAD. Modern OpenSSL rejects GCM and ChaCha20-Poly1305 here — it prints enc: AEAD ciphers not supported, because enc has nowhere to store the authentication tag. For real authenticated encryption from the command line, use a tool built for it:

# age — modern, authenticated by default (recommended)
age -p -o secret.age secret.txt       # encrypt with a passphrase
age -d -o decrypted.txt secret.age    # decrypt

# ...or gpg symmetric (also authenticated)
gpg --symmetric --cipher-algo AES256 secret.txt   # creates secret.txt.gpg
gpg -d secret.txt.gpg > decrypted.txt

# Tamper test: flip one byte of the ciphertext, then decrypt again —
# BOTH tools fail loudly (integrity error) instead of returning garbage.

ChaCha20-Poly1305 is another modern AEAD cipher (an alternative to AES-GCM), used by:

  • WireGuard - VPN protocol
  • TLS 1.3 - supported cipher suite
  • SSH - available cipher for connections

(Under the hood, age encrypts with ChaCha20-Poly1305 — so the age commands above already give you authenticated ChaCha20 encryption.)


4. Key Derivation Functions: From Passwords to Keys

The Problem with Password-Based Encryption

Passwords are weak. Most people choose:

  • Dictionary words (“password123”)
  • Short phrases (8-10 characters)
  • Reused across sites

Raw passwords make terrible encryption keys:

# BAD: Using password directly
echo "MyPassword" → AES key
# Attacker tries 1 billion passwords/second → Cracked in minutes

How KDFs Work

A Key Derivation Function (KDF) transforms a weak password into a strong encryption key by making the process intentionally slow.

Process:

User Password + Salt → KDF (slow, expensive) → Strong 256-bit Key → AES Encryption

Steps:

  1. Add salt (random value) to prevent rainbow tables
  2. Apply hash function thousands/millions of times (CPU/memory intensive)
  3. Produce cryptographically strong key

Effect on attackers:

  • Each password guess takes 0.1 seconds instead of 0.000001 seconds
  • 1 billion guesses now takes ~3 years instead of ~16.7 minutes

Common KDFs

AlgorithmYearStrengthNotes
PBKDF22000ModerateWidely supported, NIST standard
bcrypt1999GoodMemory-hard, resists GPUs
scrypt2009BetterMemory-hard + CPU-hard
Argon22015BestWinner of Password Hashing Competition

Recommendation: Use Argon2id for new applications, scrypt if Argon2 unavailable.

Hands-On: Key Derivation with OpenSSL

By default, OpenSSL’s enc uses a legacy, weak key-derivation function (EVP_BytesToKey — a single MD5 pass over your password + salt). You must add -pbkdf2 to opt into proper PBKDF2 key stretching.

# The DEFAULT is WEAK: salt only + a single legacy MD5-based derivation (NOT PBKDF2)
openssl enc -aes-256-cbc -salt -in secret.txt -out secret.enc

# STRONG: opt into PBKDF2 with a high iteration count (higher = slower = stronger)
openssl enc -aes-256-cbc -salt -pbkdf2 -iter 100000 -in secret.txt -out secret.enc
# 100,000 iterations makes password cracking 100,000x slower

Lab: Compare Weak vs Strong Passwords

# Encrypt same file with weak and strong passwords
echo "Sensitive data" > test.txt

# Weak password
openssl enc -aes-256-cbc -salt -in test.txt -out weak.enc -k "password"

# Strong password
openssl enc -aes-256-cbc -salt -in test.txt -out strong.enc -k "kR9$mP2#vL7@nQ4*wX6&jZ8"

# Both files are encrypted, but strong password makes brute force infeasible
# Weak password could be cracked in hours/days
# Strong password would take millennia

Lesson: KDFs help, but strong passwords are still essential.


Up Next

Week 2c covers entropy and randomness, binary encoding (Base64/hex), and putting it all together in an encrypted workflow.


Key Takeaways

  • Symmetric encryption uses the same key for encrypt/decrypt
  • AES-256 is computationally unbreakable (2^256 key space)
  • ECB mode is broken - patterns leak through encryption
  • GCM mode is recommended - provides authentication and confidentiality
  • ChaCha20 is faster on devices without AES hardware acceleration
  • Key Derivation Functions transform weak passwords into strong keys
  • Salt + iterations make password cracking 100,000x+ slower