Skip to content

How does an HMAC work and why use it instead of a plain hash?

Short answer

HMAC is a keyed message authentication code: it hashes the message together with a secret key using a nested construction (inner and outer hash with key-derived pads). It proves both integrity (the message wasn't altered) and authenticity (it came from someone holding the key). A plain hash proves neither, since anyone can recompute it; HMAC also resists length-extension attacks.

This question checks whether you understand the difference between integrity (data wasn't changed) and authenticity (data came from a specific party), and why a bare hash gives you neither in an adversarial setting.

Why a plain hash isn't enough

If you send a message plus SHA-256(message), an attacker who modifies the message can simply recompute the hash. There is no secret involved, so the digest proves nothing about who produced it. You might think SHA-256(secret || message) fixes this, but it is vulnerable to a length-extension attack: with hashes like SHA-256 and SHA-1, knowing the digest of secret || message lets an attacker compute a valid digest for secret || message || extra without knowing the secret. That breaks the security you wanted.

How HMAC is built

HMAC solves this with a specific nested construction. It derives two padded keys from the secret (an inner pad and an outer pad) and computes:

HMAC = H( (key ⊕ opad) || H( (key ⊕ ipad) || message ) )

The message is hashed under the key, and that result is hashed again under the key. This double-wrapping is what defeats length-extension and ties the digest to the secret. Anyone holding the key can verify the tag; anyone without it cannot forge one.

What it gives you

A valid HMAC tells the receiver two things at once: the message was not modified and it was produced by someone who knows the shared key. It does not provide confidentiality — the message itself is still readable unless separately encrypted, which is why authenticated-encryption modes exist.

One implementation trap

Comparing the received tag to the computed one must be constant-time. A naive byte-by-byte compare that returns early leaks timing information an attacker can use to forge a tag.

What interviewers look for

Mention the secret key, the integrity-plus-authenticity guarantee, length-extension resistance as the reason for the nested design, and the constant-time comparison detail for bonus points.

Likely follow-ups

  • Why doesn't appending a secret to a message (hash(secret || message)) work safely?
  • What is a length-extension attack and which hashes are vulnerable?
  • Why must HMAC verification use a constant-time comparison?

Sources

Certifications

Get 100 cybersecurity interview questions + answers

Drop your email and we'll send you the free PDF pack and the flashcard deck.

No spam. Unsubscribe anytime.