Cryptography & Security

Symmetric Encryption & Cryptographic Primitives

From AES block cipher modes to AEAD constructions, hashing, HMACs, key derivation functions, and digital signatures — the building blocks of modern cryptography.

01 / Symmetric Encryption & AES

One Key to Rule Them All

Symmetric encryption uses the same secret key for both encryption and decryption. The sender and receiver must share this key through a secure channel before communicating. This is in contrast to asymmetric cryptography, where a public/private key pair is used.

AES (Advanced Encryption Standard) is the dominant symmetric cipher. It is a block cipher that operates on fixed 128-bit (16-byte) blocks of plaintext. AES supports three key sizes: 128-bit, 192-bit, and 256-bit. More rounds of internal transformations are applied as key size increases (10, 12, and 14 rounds respectively).

Symmetric Encryption Flow
Plaintext
+
Secret Key
AES Encrypt
Ciphertext
Ciphertext
+
Same Key
AES Decrypt
Plaintext
Key Insight
AES itself only encrypts a single 128-bit block. To encrypt data longer than 16 bytes, you need a block cipher mode of operation that defines how multiple blocks are processed. The choice of mode is critical to security.
02 / Block Cipher Modes

ECB, CBC, CTR, and GCM

A block cipher mode determines how a block cipher (like AES) is applied repeatedly to encrypt data larger than one block. Different modes offer wildly different security guarantees.

ModeTypeIV/NonceParallelizableAuthVerdict
ECBBlockNoYesNoNever use
CBCBlockIV requiredDecrypt onlyNoLegacy
CTRStream-likeNonce requiredYesNoGood (needs MAC)
GCMAEADNonce requiredYesYesPreferred

ECB — Electronic Codebook

Each block is encrypted independently with the same key. Identical plaintext blocks produce identical ciphertext blocks. This leaks patterns catastrophically — the famous "ECB penguin" image demonstrates how an encrypted bitmap still reveals the original shape.

Warning
ECB is deterministic. Never use it for anything. It exists only as a teaching example of what not to do.

CBC — Cipher Block Chaining

Each plaintext block is XORed with the previous ciphertext block before encryption. An Initialization Vector (IV) is used for the first block. This hides patterns but introduces the padding oracle attack — if an attacker can distinguish valid vs. invalid padding in error messages, they can decrypt the entire ciphertext byte by byte.

CTR — Counter Mode

Turns a block cipher into a stream cipher. A counter is encrypted to produce a keystream, which is XORed with plaintext. Fully parallelizable and no padding needed. However, CTR provides no authentication — an attacker can flip ciphertext bits and the corresponding plaintext bits flip too.

GCM — Galois/Counter Mode

Combines CTR mode encryption with a Galois field MAC for authentication. It is an AEAD (Authenticated Encryption with Associated Data) construction: it provides both confidentiality and integrity in a single operation. GCM is the preferred mode in modern protocols like TLS 1.3.

03 / AEAD: AES-GCM & ChaCha20-Poly1305

Authenticated Encryption

AEAD ciphers solve the fundamental problem of "encrypt-then-MAC" composition by providing both confidentiality and integrity in a single, hard-to-misuse API. The two dominant AEAD constructions are AES-GCM and ChaCha20-Poly1305.

AES-GCM Deep Dive

AES-GCM takes four inputs and produces two outputs:

AES-GCM Inputs & Outputs
Key (128/256-bit)
Nonce/IV (96-bit)
Plaintext
AAD
AES-GCM
Ciphertext
Auth Tag (128-bit)

AAD (Additional Authenticated Data) is data that is authenticated but not encrypted — for example, packet headers or metadata. The auth tag covers both the ciphertext and the AAD, so tampering with either is detected.

Critical: Nonce Reuse
If the same (key, nonce) pair is ever used twice, AES-GCM completely breaks: an attacker can recover the authentication key H and forge arbitrary messages. For random 96-bit nonces, the birthday bound limits you to ~232 encryptions per key before collision risk becomes unacceptable.

ChaCha20-Poly1305

An alternative AEAD designed by Daniel Bernstein. ChaCha20 is a stream cipher, and Poly1305 is a one-time MAC. This construction is significantly faster than AES-GCM on platforms without hardware AES-NI instructions (mobile devices, IoT). It uses a 256-bit key and 96-bit nonce.

Rule of Thumb
Use AES-256-GCM if hardware AES-NI is available (most modern x86 CPUs). Use ChaCha20-Poly1305 on mobile/embedded platforms or when you want to avoid timing side-channel risks from software AES implementations.
04 / Cryptographic Hashing

One-Way Functions

A cryptographic hash function maps arbitrary-length input to a fixed-length digest. It must satisfy three properties:

Preimage Resistance

Given hash h, it is computationally infeasible to find any input m such that H(m) = h.

Collision Resistance

It is infeasible to find two distinct inputs m1 != m2 where H(m1) = H(m2).

Avalanche Effect

Changing a single bit of input flips roughly 50% of the output bits. No correlation between input and output.

AlgorithmOutput SizeStatusNotes
MD5128-bitBrokenPractical collision attacks since 2004
SHA-1160-bitBrokenSHAttered attack (2017), deprecated
SHA-256256-bitSecureSHA-2 family, widely used
SHA-384384-bitSecureTruncated SHA-512, used in TLS
SHA-512512-bitSecureFaster than SHA-256 on 64-bit CPUs
SHA-3VariableSecureKeccak sponge construction, different design
SHA-2 vs SHA-3
SHA-3 is not a replacement for SHA-2 — SHA-2 remains unbroken. SHA-3 uses an entirely different internal structure (sponge construction vs. Merkle-Damgård), providing algorithm diversity. If SHA-2 is ever broken, SHA-3 serves as a fallback.
05 / HMAC & Key Derivation Functions

MACs and KDFs

HMAC — Hash-based Message Authentication Code

HMAC provides message authentication using a hash function and a secret key. The construction is:

HMAC(K, m) = H( (K' XOR opad) || H( (K' XOR ipad) || m ) )

Where K' is the key padded/hashed to block size, opad is 0x5c repeated, and ipad is 0x36 repeated. This double-hashing construction prevents length-extension attacks that plague naive H(key || msg) constructions with Merkle-Damgård hashes like SHA-256.

Timing Attacks
When verifying an HMAC, always use a constant-time comparison function (e.g., hmac.compare_digest() in Python). A naive byte-by-byte comparison leaks information about how many bytes matched, allowing an attacker to forge a valid MAC one byte at a time.

Key Derivation Functions (KDFs)

KDFs stretch low-entropy passwords into strong keys, or derive multiple keys from a single master key. Two categories exist:

PBKDF2

Iterates HMAC thousands of times. Simple but only CPU-hard; vulnerable to GPU/ASIC attacks.

bcrypt

Blowfish-based, memory-hard by design. Battle-tested for decades. Max 72-byte input.

scrypt

Memory-hard KDF. Configurable CPU and memory cost. Harder to attack with GPUs than PBKDF2.

Argon2id

Winner of the Password Hashing Competition. Combines data-dependent and data-independent passes. The modern default for password hashing.

HKDF — HMAC-based Key Derivation

HKDF is designed for deriving keys from high-entropy input (not passwords). It works in two phases: Extract (compress input into a pseudorandom key using HMAC) and Expand (generate multiple output keys from that PRK). Used in TLS 1.3 for deriving session keys from the shared secret.

Best Practice
For password storage, use Argon2id. For deriving keys from shared secrets or master keys, use HKDF. Never use a plain hash like SHA-256 directly for password hashing — it is too fast.
06 / Digital Signatures

Sign with Private, Verify with Public

Digital signatures provide authentication, integrity, and non-repudiation. The signer uses their private key to produce a signature over a message (typically the hash of the message), and anyone with the corresponding public key can verify it.

Digital Signature Flow
Message
Hash(msg)
Sign(private_key)
Signature
Message + Signature
Verify(public_key)
Valid / Invalid
AlgorithmKey SizeSignature SizeSpeedNotes
RSA2048-4096 bit256-512 bytesSlow signMature, large keys, verify is fast
ECDSA256-bit curve64 bytesFastRequires good RNG for k value; reuse of k leaks private key
Ed25519256-bit64 bytesVery fastDeterministic nonce (no RNG needed), misuse-resistant, modern default
Recommendation
Use Ed25519 for new systems. It is fast, produces compact signatures, and its deterministic nonce generation eliminates the class of bugs where a bad or repeated random k in ECDSA leaks the private key (as happened with the PlayStation 3 hack).

Test Yourself

Score: 0 / 10
Question 01
Why is ECB mode considered insecure?
ECB encrypts each block independently with the same key. Identical plaintext blocks always produce the same ciphertext, revealing patterns in the data (the "ECB penguin" problem).
Question 02
What does the "A" in AEAD stand for, and what does it provide beyond regular encryption?
AEAD stands for Authenticated Encryption with Associated Data. The authentication tag ensures that any tampering with the ciphertext or associated data is detected upon decryption.
Question 03
What happens if you reuse a nonce with the same key in AES-GCM?
AES-GCM nonce reuse is catastrophic. It allows an attacker to recover the Galois hash key H via XOR of the two keystreams, enabling them to forge valid authentication tags for arbitrary messages.
Question 04
Why might you choose ChaCha20-Poly1305 over AES-GCM?
ChaCha20-Poly1305 is designed to be fast in pure software. On devices without AES-NI instructions (some mobile/embedded platforms), it significantly outperforms AES-GCM while providing equivalent security.
Question 05
Which property of a hash function means that given a hash output, you cannot find an input that produces it?
Preimage resistance means it is computationally infeasible to reverse a hash — given H(m), you cannot find m. Collision resistance is about finding two different inputs with the same hash.
Question 06
Why does HMAC use a double-hash construction (nested hashing) rather than simply computing H(key || message)?
Merkle-Damgård hashes (like SHA-256) are vulnerable to length-extension attacks: knowing H(key || msg) lets an attacker compute H(key || msg || padding || extra) without knowing the key. HMAC's nested structure prevents this.
Question 07
Which KDF is the recommended modern default for password hashing?
Argon2id won the Password Hashing Competition and is the modern default. It combines data-dependent and data-independent memory access patterns, making it resistant to both GPU/ASIC attacks and side-channel attacks. HKDF is for key derivation from high-entropy sources, not passwords.
Question 08
What advantage does Ed25519 have over ECDSA for digital signatures?
ECDSA requires a random value k for each signature. If k is ever repeated or predictable, the private key is revealed (as in the PS3 hack). Ed25519 derives the nonce deterministically from the message and private key, eliminating this entire class of vulnerabilities.
Question 09
What is the padding oracle attack, and which cipher mode is vulnerable to it?
The padding oracle attack targets CBC mode. If a server reveals whether decrypted padding is valid (through error messages or timing differences), an attacker can iteratively decrypt the entire ciphertext without the key.
Question 10
What is the purpose of AAD (Additional Authenticated Data) in AES-GCM?
AAD is data that needs integrity protection but not confidentiality — like packet headers, protocol version numbers, or routing info. The authentication tag covers both the ciphertext and the AAD, so any modification to either is detected.