HomeGuides › HMAC

How to generate and verify an HMAC

A tag only someone holding the shared key could have produced — the standard way to authenticate a webhook or an API request.

An HMAC is a keyed hash. A plain hash can be computed by anyone, so it proves nothing about who produced a message. An HMAC folds a secret key into the calculation, so a correct tag is evidence that whoever produced it held the key.

This is the mechanism behind most webhook signing. Stripe, GitHub, Slack and many others send a signature header; verifying it is how you know the request really came from them and not from someone who guessed your endpoint.

Step-by-step

  1. Enter the shared key. Hex, Base64 or plain text.
  2. Paste the message. For a webhook this is the raw request body, exactly as received.
  3. Choose the hash. SHA-256 unless the other side specifies otherwise.
  4. Generate, or paste an expected tag to verify against.

The raw body, not the parsed one

Nearly every webhook verification bug comes from the same place: the signature covers the exact bytes that were sent, and your framework parsed the JSON and re-serialised it before you got to it. Re-serialising changes key order and whitespace, the bytes differ, and the tag will not match however correct your key is. Capture the raw body before parsing.

Comparing tags

When verifying, compare in constant time rather than with an ordinary string comparison. An ordinary comparison stops at the first differing character, and how long it took is measurable — enough, in principle, to recover a valid tag one character at a time. This tool compares in constant time; so should your code.

Why the long-key case matters

HMAC is defined with a rule for keys longer than the hash's block size: hash the key first, then use that. It is easy to skip, and an implementation that skips it produces plausible-looking tags that disagree with everyone else's. This tool is checked against all the RFC 4231 test vectors, the long-key case included.

Frequently asked questions

Is my key sent anywhere?

No. The key and message stay in your browser, and no analytics event on the page may carry either.

HMAC or a signature?

HMAC uses one shared secret, so both sides can produce tags — good for a service authenticating its own callbacks, useless for proving to a third party who sent something. A signature uses a private key held by one party, so it proves origin to anyone with the public key.

My webhook signature never matches. What is wrong?

Almost always that you are hashing a re-serialised body rather than the raw bytes received. Check also whether the provider signs a constructed string — a timestamp and the body joined in a specific way — rather than the body alone.

Open the HMAC tool →