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.
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.
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 the plaintext, then compute a MAC of the plaintext.
Problem: the MAC can leak whether two messages are identical.
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 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.
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.
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.
The ciphertext reveals nothing about the plaintext without the key. Same guarantee as AES-CBC or AES-CTR, built into every AEAD operation.
Any modification to the ciphertext or authentication tag is detected. Decryption refuses to produce output. No corrupted plaintext, no silent failures.
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.
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.
Type a message and watch AES-GCM produce both ciphertext and an authentication tag. One function call, two guarantees.
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.
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.
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.
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.
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.
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.
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.
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.
The ciphertext and tag are fixed. Edit the "received" associated data below and watch authentication succeed or fail. The ciphertext itself is never touched.
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.
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.
Two messages encrypted with real AES-GCM using the same key. Toggle to reused nonces and watch both confidentiality and authentication break.
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.
AEAD simplifies things enormously. But there are still ways to get it wrong.
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.
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.
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.
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.
This chapter completes the core primitives of symmetric cryptography. You now have every tool needed to encrypt data securely with a shared key.
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.