Chapter 06 // Primitives

Authenticated
Encryption

Chapter 5 showed you how encryption hides data. It also showed you that an attacker can tamper with ciphertext without detection. This chapter solves that problem by combining confidentiality and integrity into a single operation.

Scroll to explore
01 // The Problem

Encryption alone is not enough

AES-CBC and AES-CTR give you confidentiality. But as the bit-flipping demo in Chapter 5 showed, an attacker can modify ciphertext and decryption happily produces corrupted plaintext without raising an alarm. The natural thought: combine encryption with a MAC.

Three ways to combine encryption and MAC

You have a cipher (AES-CBC, AES-CTR) and a MAC (a tag that proves data was not tampered with, from Chapter 3). There are three ways to combine them, and the ordering matters enormously.

Encrypt-and-MAC

Encrypt the plaintext, then compute a MAC of the plaintext.

Problem: the MAC can leak whether two messages are identical.

MAC-then-Encrypt

Compute a MAC of the plaintext, then encrypt both together.

Problem: the receiver must decrypt before checking integrity, which can leak information through error messages.

Encrypt-then-MAC

Encrypt first, then MAC the ciphertext.

Correct: tampered data is rejected before decryption even starts.

Getting the composition right requires two separate keys (one for encryption, one for the MAC), two algorithms, correct ordering, and careful nonce management. Every step is an opportunity for a subtle bug. This is exactly why AEAD was invented: to make the right thing the easy thing.

02 // The Modern Solution

AEAD: one operation, two guarantees

Authenticated Encryption with Associated Data combines a cipher and a MAC into a single construction. One key, one function call, both confidentiality and integrity. No manual composition, no ordering mistakes.

How AEAD works

An AEAD algorithm takes four inputs: a key, a nonce (a unique value per encryption), the plaintext, and optional associated data. It produces two outputs: the ciphertext and an authentication tag.

During decryption, if anything has been modified (the ciphertext, the tag, or the associated data), the algorithm rejects the input with an explicit error. It does not return corrupted data. It does not attempt partial decryption. The answer is either the original plaintext or nothing at all.

AEAD encryption flow
Plaintext
+
Key
+
Nonce
+
AAD
AEAD
Ciphertext
+
Tag
AEAD decryption flow
Ciphertext
+
Tag
+
Key
+
Nonce
+
AAD
Verify
Plaintextif tag matches
REJECTif tampered
🔒

Confidentiality

The ciphertext reveals nothing about the plaintext without the key. Same guarantee as AES-CBC or AES-CTR, built into every AEAD operation.

🛡️

Integrity

Any modification to the ciphertext or authentication tag is detected. Decryption refuses to produce output. No corrupted plaintext, no silent failures.

Authenticity

Only someone with the key could have produced the ciphertext and tag pair. This proves the data came from the key holder, not an impersonator.

The "AD" in AEAD stands for Associated Data. This is data that you want to authenticate but not encrypt. Think of it as metadata: visible to everyone, but tamper-proof. We explore this in detail in Section 6.

03 // Try It Yourself

Encrypt and authenticate with AES-GCM

Type a message and watch AES-GCM produce both ciphertext and an authentication tag. The Web Crypto API handles everything in a single function call. Change a character and see how both the ciphertext and the tag change completely.

AES-GCM Encryption Playground

Type a message and watch AES-GCM produce both ciphertext and an authentication tag. One function call, two guarantees.

Key (256-bit)
 
Nonce (96-bit)
87a7c2a0c4f0d40f06509edb
Ciphertext (0 bytes) 
Authentication Tag (128-bit) 

The ciphertext is the same length as the plaintext (no padding needed). The 16-byte authentication tag is computed over the ciphertext and binds everything together. Modify either one, and decryption will fail.

04 // Under the Hood

How AES-GCM works

AES-GCM combines two components: CTR mode for encryption and GHASH for authentication. Understanding both halves explains why it provides two guarantees in one pass.

The CTR half: encryption

AES-GCM uses AES in Counter mode for encryption. You already know CTR from Chapter 5: AES encrypts a counter value to produce a keystream, then XORs the keystream with the plaintext. Same idea here.

The nonce is 96 bits (12 bytes). The counter is 32 bits, starting at 2. Counter value 1 is reserved for computing the authentication tag. This means a single nonce supports up to 2^32 blocks (about 64 GB of data) before the counter wraps around.

The authentication half: GHASH

After encryption, GCM computes a keyed hash over the ciphertext and any associated data. The hash key is derived from the encryption key, which makes it key-dependent (unlike a regular hash function).

The hash output is then encrypted to produce the final authentication tag. The tag covers both the ciphertext and the associated data, binding them together. Anyone who modifies either part will produce a tag mismatch, and decryption is refused.

There is an alternative AEAD called ChaCha20-Poly1305. It provides the same security guarantees as AES-GCM but is preferred on devices without hardware AES acceleration (phones, IoT). TLS 1.3 supports both.

05 // Attack Demo

Tamper with the ciphertext, get caught

In Chapter 5, you flipped bits in CBC ciphertext and the attacker got away with it. Try the same thing with AES-GCM. Flip any byte in the ciphertext or the authentication tag. Every modification is detected and decryption is refused.

AES-GCM Tamper Detection

Click any byte in the ciphertext or authentication tag to flip it. In Chapter 5, CBC silently produced corrupted output. With AES-GCM, every modification is caught.

Original plaintext
role=user;admin=false;session=ok!
Ciphertext + Tag (click a byte to flip it)
Ciphertext (0 bytes)
Auth Tag (0 bytes)
0x00XOR 0x15= 0x15
0x000x150xFF
06 // Associated Data

Authenticating data you don't encrypt

Sometimes metadata must travel in plaintext. Routing headers, protocol versions, sequence numbers. You need this data readable by network infrastructure, but you also need to guarantee nobody tampered with it. That is what associated data is for.

Why not just encrypt everything?

In TLS, the record header contains the content type, protocol version, and payload length. Network middleboxes and load balancers need to read this data to route traffic correctly. If you encrypt the header, the infrastructure breaks.

In a database, the row ID and table name might be associated data while the row contents are encrypted. The database engine needs the ID to locate the row, but the contents should be hidden from anyone without the key. Associated data lets you authenticate both parts while only encrypting the sensitive part.

Associated Data Explorer

The ciphertext and tag are fixed. Edit the "received" associated data below and watch authentication succeed or fail. The ciphertext itself is never touched.

Plaintext (encrypted)Top secret message content
Associated Data (not encrypted, authenticated)from=alice;to=bob;type=message
Ciphertext (0 bytes) 
Authentication Tag 
07 // The Danger

Nonce reuse with AES-GCM is catastrophic

Chapter 4 showed that reusing a nonce with a stream cipher leaks the XOR of plaintexts. With AES-GCM, nonce reuse is even worse. It also destroys the authentication guarantee entirely.

Two failures in one

AES-GCM uses CTR mode internally, so nonce reuse causes the same keystream reuse you saw in Chapter 4. XOR two ciphertexts encrypted with the same nonce, and you get the XOR of the two plaintexts. Confidentiality is gone.

But it gets worse. GCM's authentication key is derived independently of the nonce. When two messages share a nonce, an attacker can use the relationship between the two authentication tags to recover that key. Once they have it, they can forge valid tags for arbitrary messages. The authentication guarantee is completely destroyed.

AES-GCM Nonce Reuse

Two messages encrypted with real AES-GCM using the same key. Toggle to reused nonces and watch both confidentiality and authentication break.

Nonce 1000000000000000000000000Ciphertext 1 Tag 1 
Nonce 2000000000000000000000000Ciphertext 2 Tag 2 
C1 XOR C200000000000000000000000000000000
P1 XOR P2 (plaintext XOR)13110013060a5441004f4403161d4400
C1 XOR C2 reveals nothing. Tags are independent.

With unique nonces, each message gets a different keystream and a different authentication context. XORing the ciphertexts produces random noise. The tags are computed with different inputs, so they leak nothing about each other.

08 // Best Practices

Using authenticated encryption correctly

AEAD simplifies things enormously. But there are still ways to get it wrong.

🔐

Use AES-GCM or ChaCha20-Poly1305

Never use AES-CBC or AES-CTR without a separate MAC. If your platform supports AES-GCM (it almost certainly does), use it. These AEAD constructions are the default choice in TLS 1.3.

🔢

Never Reuse (Key, Nonce) Pairs

Generate a random 12-byte nonce per encryption. With random nonces, you can safely encrypt about 4 billion messages under one key before collisions become likely (the birthday problem). For higher volumes, rotate keys or use a simple incrementing counter as the nonce.

📎

Always Include Context in AAD

Include protocol version, message type, sender ID, or any context that should be bound to the ciphertext. Without AAD, an attacker can take a valid ciphertext from one context and replay it in another.

📏

Use the Full 128-Bit Tag

AES-GCM supports shorter tags (64 or 96 bits) but always use the full 128-bit tag. Shorter tags make forgery exponentially easier for an attacker.

The biggest shift from Chapter 5 to this chapter: never use a cipher without authentication. AES-GCM and ChaCha20-Poly1305 exist precisely so you never have to think about Encrypt-then-MAC ordering, separate keys, or padding oracles. Use them.

09 // What You Learned

From primitives to the real world

This chapter completes the core primitives of symmetric cryptography. You now have every tool needed to encrypt data securely with a shared key.

The symmetric toolkit

Chapter 2 gave you hash functions for fingerprinting data. Chapter 3 added MACs for proving integrity with a shared secret. Chapter 4 explained where keys and nonces come from. Chapter 5 introduced symmetric encryption for confidentiality.

This chapter combined it all into authenticated encryption: one operation that provides confidentiality, integrity, and authenticity. AES-GCM is the workhorse. ChaCha20-Poly1305 is the alternative. Together, they are what TLS 1.3 uses to protect every HTTPS connection you make.

One massive question remains unanswered: how do two parties agree on a shared key in the first place? If Alice and Bob have never met, how do they establish a secret over an insecure channel? That is the problem of key exchange, and it requires an entirely different kind of mathematics.

Up Next

Chapter 07 // Mathematical Foundations

Continue Learning