Lesson 1 pointed out that a plain hash function has no secret involved — anyone can compute the same digest, which means it can't prove a message came from anyone specific. HMAC is the small, elegant fix, and it's the actual mechanism underneath both TOTP codes and HMAC-signed JWTs from Auth.
3 min read
SHA-256(message) is fully public — anyone can compute it, so it can't
prove who sent a message, only that some computable digest exists for
it. To prove authenticity with a hash function, a secret needs to be
folded into the computation somehow, so that only someone who knows the
secret can produce a matching digest.
The naive approach — hash(secret + message) — has a real, exploitable
weakness for certain hash function constructions: due to how many hash
functions are built internally (processing data in blocks, carrying
state forward), an attacker can sometimes extend a message and compute a
valid new hash without knowing the secret at all, exploiting the
internal structure rather than breaking the hash function's core
properties from lesson 1. This is called a length extension attack,
and it's exactly why a dedicated construction was designed instead of
just gluing a secret onto a message.
HMAC (Hash-based Message Authentication Code) processes the secret key through the hash function in a specific pattern — hashing the key combined with the message in two nested passes — that's mathematically proven to avoid the length-extension weakness, regardless of which underlying hash function (SHA-256, SHA-3) it's built on:
The output is an authentication tag — anyone who also knows the secret key can recompute the same tag from the same message and confirm it matches; anyone without the key can't produce a valid tag at all, even though the hash function itself remains completely public.
Auth's JWT lesson described HMAC-signed tokens as an alternative to RSA-signed ones. Mechanically, the server computes an HMAC over the token's contents using a secret key only the server knows, and attaches that as the token's signature. Verifying the token means recomputing the HMAC with the same secret and checking it matches — exactly the process this lesson describes, just applied specifically to a JWT's payload as the "message."
Auth's MFA lesson covered TOTP (the six-digit codes from an authenticator app) without explaining the mechanism generating them. TOTP is HMAC applied to the current time interval, using a secret shared between the server and the authenticator app during setup — both sides compute the same HMAC independently (because they share the same secret and are looking at the same time window), producing the same code without any network communication needed at the moment of verification. Two seemingly unrelated features — signed tokens and one-time authentication codes — turn out to be the exact same underlying primitive, applied to different input.
HMAC's security guarantee depends entirely on the secret key actually being secret and hard to guess — a predictable or short key undermines the whole construction regardless of how sound HMAC's own design is, the same way a strong lock on a door does nothing if the key is left under the mat. Lesson 9 covers what makes a key (or any secret value) genuinely unpredictable, which is precisely the property HMAC's whole security guarantee rests on.
Check your understanding
A quick comprehension check — not tracked, not graded, just for you.
1. Why isn't 'hash(secret + message)' a safe way to build a message authentication code?
2. What do JWT HMAC signatures and TOTP authenticator codes have in common?
3. What does HMAC's security guarantee fundamentally depend on?
Cryptography Fundamentals