Skip to main content
Book 07 · SecurityPage 15 of 50

HMAC

Hash-based Message Authentication Code

Pronunciation
AYCH-mak
Updated 2 min read

Share this page

Send the link, quote the definition with a link back, or show it as a card on your own site.

https://softwaredictionary.org/terms/hmac

In short

HMAC combines a secret key with a hash function to produce a tag that proves a message came from someone who knows the key and wasn't changed on the way.

What is HMAC?

A plain hash such as SHA-256 detects accidental changes, but anyone can recompute it after tampering with a message. HMAC mixes a secret key into the hashing, in a carefully designed two-step construction, so only parties who share the key can produce or check a valid tag. It was published in 1996 and standardized in 1997.

It is everywhere in web development. Webhook providers such as Stripe and GitHub sign each request body with HMAC-SHA256 and a secret you share with them, so your server can reject forged events. JWTs signed with the HS256 algorithm use HMAC, cloud APIs such as AWS sign requests with it, and signed cookies use it to detect tampering.

Verifying a tag is simple: recompute the HMAC over the exact bytes received with the shared secret and compare. The comparison must be constant-time, using a function such as crypto.timingSafeEqual or hmac.compare_digest, because an ordinary string comparison stops at the first difference and can leak the correct tag through timing. Including a timestamp in the signed data prevents replaying old messages.

A common misconception is that HMAC encrypts the message. It doesn't hide anything; the message stays readable and the tag only proves integrity and authenticity. Because both sides share the same key, HMAC also can't prove to a third party which side sent a message, which is what digital signatures with public keys are for.

Key takeaways

  • HMAC uses a secret key and a hash to make a tamper-proof tag.
  • Only holders of the shared key can create or verify the tag.
  • Webhooks, HS256 JWTs, API request signing and signed cookies use it.
  • Compare tags in constant time and include timestamps against replays.
  • It proves integrity, not secrecy, and isn't a public-key signature.

Example

Verifying a webhook signature (Node.js)javascript
import crypto from "node:crypto";

export function isValidWebhook(rawBody, signatureHeader, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(rawBody)                 // the exact bytes received, before JSON parsing
    .digest("hex");

  const a = Buffer.from(expected);
  const b = Buffer.from(signatureHeader.replace(/^sha256=/, ""));
  return a.length === b.length && crypto.timingSafeEqual(a, b);   // constant-time compare
}

Readers ask

What is the difference between HMAC and a hash?

A hash can be computed by anyone, so it only detects accidental changes. An HMAC also requires a secret key, so it proves the message came from someone who holds that key and wasn't altered.

What is the difference between HMAC and a digital signature?

HMAC uses one shared secret key on both sides. A digital signature uses a private key to sign and a public key to verify, so anyone can check it and only the key owner could have made it.

Why must HMAC comparison be constant-time?

A normal comparison returns as soon as it finds a mismatched character, so response times reveal how much of a guess was correct. Constant-time comparison takes the same time either way, closing that leak.

See also

Spotted a mistake or something missing on this page?Suggest an edit

Read a random page
Open today's review
Switch to the dark theme
Read this page in Türkçe

More

Settings