⚿ Cryptography

HMAC Explained: Hash-Based Message Authentication Codes

HMAC (Hash-based Message Authentication Code) is a widely used construction that proves a message is both authentic (from someone holding the secret key) and intact (not modified in transit). It appears throughout modern security: TLS record authentication, API request signing, JSON Web Tokens, cookie integrity, and key derivation all rely on HMAC. Understanding how HMAC works and why its specific structure matters is essential for building systems that resist tampering and forgery.

What Problem HMAC Solves

A cryptographic hash like SHA-256 detects accidental changes, but on its own it does nothing to stop a deliberate attacker. Anyone can recompute a hash after modifying data. What we need is a message authentication code (MAC): a tag computed with a secret key so that only parties holding the key can produce or verify it.

A MAC provides two guarantees simultaneously:

  • Integrity: any change to the message invalidates the tag.
  • Authenticity: a valid tag proves the sender knew the shared secret key.

HMAC is the standard way to build a MAC out of an existing cryptographic hash function such as SHA-256 or SHA-512, and it is standardized in RFC 2104 and FIPS 198.

The Naive Approach and Why It Fails

An obvious but flawed idea is to simply hash the key concatenated with the message as H(key || message). This is insecure with Merkle-Damgard hashes like SHA-256 because of the length-extension attack. Since these hashes output their full internal state, an attacker who sees a valid tag can append data and compute a valid tag for the extended message without knowing the key.

Prepending is not the only broken variant, and appending the key has its own weaknesses. HMAC's nested structure was specifically designed to avoid all of these pitfalls with a construction that has a formal security proof.

How HMAC Is Constructed

HMAC applies the underlying hash function twice, with the key mixed in through two different padding constants. The definition is:

HMAC(K, m) = H( (K' XOR opad) || H( (K' XOR ipad) || m ) )

Where:

  • H is the hash function (for example SHA-256).
  • K' is the key, adjusted to the hash's block size: keys longer than the block are hashed first, and shorter keys are zero-padded to the block length.
  • ipad is the byte 0x36 repeated to fill one block (the inner pad).
  • opad is the byte 0x5C repeated to fill one block (the outer pad).

The mechanics proceed in two passes:

  1. Inner hash: XOR the key with ipad, prepend it to the message, and hash the result.
  2. Outer hash: XOR the key with opad, prepend it to the inner hash output, and hash again.

The nested outer hash is what defeats length-extension attacks: because the attacker never sees the raw inner state (it is wrapped inside a second hash keyed with opad), they cannot extend it. When HMAC uses SHA-256 it is called HMAC-SHA-256, and its security tracks the strength of the underlying hash.

Verifying an HMAC Safely

Verification recomputes the tag over the received message and key, then compares it to the received tag. One subtle but important detail is constant-time comparison. Comparing tags with an ordinary byte-by-byte check that returns early on the first mismatch leaks timing information, which can let an attacker recover a valid tag byte by byte. Secure implementations recompute the expected tag as expected = HMAC(key, message) and compare it against the received tag with a constant-time equality function that always inspects every byte of both values before returning a result. Because the comparison time does not depend on how many leading bytes matched, no timing signal is exposed to the attacker.

Security Properties and Key Management

HMAC's security rests on the secrecy of the key and the properties of the hash function:

  • Key length: a key at least as long as the hash output (for example 256 bits for HMAC-SHA-256) is recommended. Very short keys reduce security to the key's entropy.
  • Resistance to hash weaknesses: HMAC is remarkably robust. Even HMAC-SHA-1 has resisted practical forgery despite SHA-1's collision weaknesses, because HMAC does not require collision resistance in the same way signatures do. New systems should still prefer SHA-256 or stronger.
  • Existential unforgeability: without the key, an attacker cannot produce a valid tag for any new message, even after observing many valid message-tag pairs.

Keys should be generated from a strong random source, stored securely, and rotated according to policy.

Where HMAC Is Used

HMAC is a versatile primitive that appears in many protocols and patterns:

  • API authentication: signing requests so a server can verify the caller holds a shared secret and the request was not altered.
  • JSON Web Tokens (JWT): the HS256 algorithm is HMAC-SHA-256 protecting token integrity.
  • TLS and IPsec: authenticating records and packets, though modern AEAD ciphers increasingly handle this internally.
  • Key derivation: HKDF, a widely used key-derivation function, is built on HMAC to expand and extract keys.
  • Cookie and token integrity: detecting tampering with signed values stored client-side.

HMAC provides authentication but not confidentiality. When you need both, combine it with encryption using an encrypt-then-MAC scheme, or better, use a purpose-built authenticated encryption mode that integrates the MAC for you.

Key Takeaways

  • HMAC turns a cryptographic hash into a keyed message authentication code, providing both integrity and authenticity.
  • Its nested two-pass structure with the ipad (0x36) and opad (0x5C) constants defeats the length-extension attacks that break naive keyed hashing.
  • HMAC-SHA-256 is a common, well-trusted choice, and HMAC remains secure even when the underlying hash has some weaknesses.
  • Always verify tags in constant time and use keys with sufficient entropy, ideally at least the hash output length.
  • HMAC provides authentication only; pair it with encryption or use an AEAD mode when confidentiality is also required.
hmacmessage-authenticationmaccryptographydata-integrity

Frequently asked questions

What is HMAC?

HMAC (Hash-based Message Authentication Code) is a mechanism that combines a cryptographic hash function with a secret key to verify both the integrity and authenticity of a message. Only someone who knows the secret key can generate or validate a correct HMAC, proving the message was not altered and came from a trusted party.

How does HMAC work?

HMAC hashes the message together with the secret key using a specific nested construction that applies the hash function twice with two key-derived pads. The result is a fixed-size tag sent alongside the message, and the recipient recomputes the tag with the shared key to confirm it matches.

What is the difference between HMAC and a regular hash?

A plain hash like SHA-256 only verifies integrity and can be recomputed by anyone, so it cannot prove who created it. HMAC adds a secret key, so a valid tag also proves authenticity, protecting against attackers who could otherwise alter both the message and its hash.

Is HMAC secure?

Yes, HMAC is provably secure and remains strong even when built on hash functions with certain weaknesses, and it resists the length-extension attacks that affect naive keyed hashing. Its security depends on keeping the key secret and long enough, and on verifying tags in constant time to avoid timing attacks.

What is HMAC used for?

HMAC is used for API request authentication, verifying webhook payloads, protecting session tokens and cookies, and ensuring message integrity in protocols like TLS and IPsec. It is also a core component of key-derivation functions such as HKDF and PBKDF2.

What is the difference between HMAC and a digital signature?

HMAC uses a single shared secret, so both parties can create and verify tags, making it fast but unable to prove which specific party sent a message. A digital signature uses a private key to sign and a public key to verify, providing non-repudiation, but it is slower and more complex.

Try it hands-on

K0G is an open toolkit of browser-based security utilities — hashing, encoding, JWT, certificates, crypto and more, all running locally in your browser.

Explore the tools →