Message Authentication
Cryptography Fundamentals
Chapter 8 · Message Authentication — MACs, HMAC & AEAD
Chapter 7 introduced hash functions as tools for integrity checking — but a plain hash, sent alongside a message with no other protection, turns out to guarantee almost nothing on its own. This chapter covers the missing ingredient: binding an integrity check to a secret, so only someone who holds it can produce a valid one — and finally explains, properly, what GCM's authentication tag from Chapter 6 was actually doing the whole time.
Why a Plain Hash Isn't Enough
Imagine a sender transmits a message along with its SHA-256 hash, so the receiver can verify nothing was altered in transit. An attacker intercepting this in transit can simply:
- Tamper with the message however they like.
- Recompute the SHA-256 hash of their tampered message — this requires no secret at all, anyone can run SHA-256.
- Forward the tampered message along with this newly-recomputed, perfectly valid hash.
The receiver checks the hash, finds it matches, and accepts the tampered message as genuine. The hash was never wrong — it correctly hashed the (tampered) message it was given. A plain hash verifies "this message wasn't altered after I computed this specific hash," which is completely useless against an attacker who can just recompute a fresh one.
MACs — Message Authentication Codes
A MAC is a hash-like function that also takes a secret key: MAC(key, message). Only someone who holds the key can produce a valid MAC for a given message. The sender computes the MAC and sends it alongside the message; the receiver, who also holds the key, recomputes the MAC independently and checks it matches.
This directly closes the gap from the previous section: an attacker who tampers with the message can no longer just recompute a matching value, because doing so requires the secret key they don't have. A mismatched MAC means either the message was altered, or it wasn't produced by someone holding the real key — either way, it's rejected.
HMAC — Hash-based MAC
Rather than design an entirely new primitive for MACs, HMAC is the standard way of building a MAC out of an existing hash function you already trust (Chapter 7's SHA-256, for instance). Conceptually:
The nested, double-hashing structure isn't decoration — it exists specifically to defend against a real weakness in naive approaches like simply computing Hash(key || message) directly. Some hash constructions (including the Merkle-Damgård structure behind SHA-1 and SHA-2, from Chapter 7) allow an attacker who knows a hash's output — without knowing the original input — to compute a valid hash for that input with extra data appended to it. This is called a length-extension attack, and it's a real, demonstrated weakness in the naive construction. HMAC's specific nested design was engineered to resist it.
Verifying a MAC — Constant-Time Comparison
Encrypt-then-MAC vs. MAC-then-Encrypt vs. Encrypt-and-MAC
Combining a cipher (Chapters 5-6) with a MAC can be done in three different orders, and the choice genuinely matters:
| Scheme | How it works | Verdict |
|---|---|---|
| Encrypt-then-MAC | Encrypt the plaintext, then compute the MAC over the ciphertext | Recommended — the MAC can be checked before decryption is ever attempted |
| MAC-then-Encrypt | Compute the MAC over the plaintext, then encrypt both together | Historically used by early TLS versions; a contributing factor in several real TLS vulnerabilities |
| Encrypt-and-MAC | Encrypt the plaintext and MAC the plaintext independently, send both | Used by SSH; the MAC is computed over unencrypted data, which can leak information in some cases |
Encrypt-then-MAC's advantage is concrete, not theoretical: because the MAC covers the ciphertext, the receiver can verify it and reject a tampered message before ever decrypting attacker-controlled data. This is exactly the standard defense against Chapter 6's padding oracle attacks — if a tampered ciphertext is rejected by the MAC check first, the vulnerable padding-error behavior that a padding oracle attack depends on is never even reached.
AEAD — What GCM Was Actually Doing All Along
Chapter 6 introduced GCM as bundling confidentiality, integrity, and authenticity into one primitive, without fully explaining how. Now it can be stated precisely: GCM's authentication tag is built from GMAC, a MAC construction specialized for GCM's own CTR-mode-based encryption — and the overall structure of GCM is, in essence, encrypt-then-MAC baked directly into a single, efficient primitive, rather than two separate operations bolted together by hand. That's the real technical answer behind Chapter 6's "mode-of-operation-level" preview.
Associated Data — Authenticating Without Encrypting
Sometimes part of a message genuinely needs to stay readable — a network packet's routing header, say, needs to be visible before decryption can even happen — while still being protected from tampering. AEAD ciphers support this directly via associated data: extra data that's included in the authentication tag's computation (so tampering with it is detected) but is never encrypted at all. A network packet with an unencrypted header (needed for routing) and an encrypted payload, both covered by one authentication tag, is the textbook example.
Hands-On Exercises
Walk through, step by step, why sending a message alongside a plain (unkeyed) SHA-256 hash provides no real protection against a tampering attacker, and explain specifically what a MAC adds that a plain hash lacks.
📄 View solutionA developer proposes building a MAC as simply SHA256(key || message) rather than using HMAC. Explain, conceptually, why this naive construction is considered unsafe, and what specific problem HMAC's nested double-hash structure is designed to prevent.
Of encrypt-then-MAC, MAC-then-encrypt, and encrypt-and-MAC, which scheme is safest against Chapter 6's padding oracle attack, and why specifically? Explain what happens differently at the moment a tampered ciphertext arrives.
📄 View solutionChapter 8 Quick Reference
- A plain hash provides no authenticity — anyone can recompute one for tampered data; needs a secret to be meaningful
- MAC = a keyed hash-like function; only the key holder can produce a valid one for given data
- HMAC — the standard way to build a MAC from a hash function; its nested structure defends against length-extension attacks
- MAC comparison must be constant-time — a naive early-exit comparison leaks timing information exploitable byte by byte
- Encrypt-then-MAC is the recommended combination order — lets tampered ciphertext be rejected before decryption is ever attempted, closing off padding oracle attacks
- GCM (Ch.6) is, underneath, essentially encrypt-then-MAC built into one efficient AEAD primitive, using GMAC
- Associated data — authenticated but left unencrypted, for data (like packet headers) that must stay readable
- Next chapter: Public-Key Cryptography — RSA, Diffie-Hellman & Elliptic Curves, leaving the shared-secret world of symmetric crypto behind