Hunt
Skip to content

HMAC Generator

Calculate an HMAC of a message with a secret key, as hex or Base64, or check a webhook's signature: paste the request body, your signing secret and the signature header from GitHub, Stripe, Slack or Shopify, and see whether it matches and exactly what was signed. Your secret never leaves the page.

Runs in your browser

Message

Signed as UTF-8, exactly as typed

HMAC

Verify a webhook signature

What an HMAC is

An HMAC (hash-based message authentication code) is a hash of a message combined with a secret key. Only someone with the key can produce it, so a receiver who shares the key can check that a message is genuine and unchanged. Webhooks use it: the sender signs each request body and puts the HMAC in a header, and your server recomputes it to reject forged requests.

How to use the HMAC Generator

  1. Paste the message and your secret key, or load the GitHub example.
  2. Choose the algorithm and output format to read the HMAC.
  3. To check a webhook, choose the provider and paste its signature header (and, for Slack, the timestamp).

Examples

HMAC-SHA256 as hex

Input
key: key
message: The quick brown fox jumps over the lazy dog
Output
f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8

The same as Base64

Input
key: key
message: The quick brown fox jumps over the lazy dog
Output
97yD9DBThCSxMpjmqm+xQ+9NWaFJRhdZl0edvC0aPNg=

Legacy HMAC-MD5

Input
key: key
message: The quick brown fox jumps over the lazy dog
Output
80070713463e7749b90c2dc24911e275

Some older APIs still use HMAC-MD5. Unlike plain MD5, HMAC-MD5 hasn't been broken in practice, but prefer SHA-256 for anything new.

How each provider signs

  • GitHub: X-Hub-Signature-256: sha256=<hex>, an HMAC-SHA256 of the raw body.
  • Stripe: Stripe-Signature: t=<timestamp>,v1=<hex>, an HMAC-SHA256 of <timestamp>.<body>.
  • Slack: X-Slack-Signature: v0=<hex>, an HMAC-SHA256 of v0:<timestamp>:<body>, with the timestamp from X-Slack-Request-Timestamp.
  • Shopify: X-Shopify-Hmac-Sha256: <Base64>, an HMAC-SHA256 of the raw body.

Why verification fails

Almost always because the body isn't the exact bytes that were signed. Frameworks often parse JSON and hand you an object; serialising it again changes spacing and key order. Verify against the raw request body, before parsing. Also check you're using the right secret for the environment (test or live).

Options

Algorithm
SHA-256 (the default and the most common), SHA-1, SHA-384, SHA-512 or MD5.
Key format
The key as text (UTF-8), hex or Base64. Some providers give secrets in Base64 that must be decoded first.
Output
Hex, Base64 or URL-safe Base64, whichever the receiving system expects.

Limitations

  • The message is signed as UTF-8 text. For binary payloads, use your server's code.
  • Webhook verification checks the signature only; your server should also reject old timestamps and repeated deliveries.

Frequently asked questions

Is my secret sent anywhere?

No. The HMAC is calculated in your browser with the Web Crypto API; the key and message never leave the page.

Why doesn't my signature match?

Check that you're signing the raw body exactly as received, using the right secret (test and live secrets differ) and the right key format. For Stripe and Slack, the timestamp is part of what's signed.

How do I compute an HMAC in code?

Node.js: createHmac("sha256", secret).update(body).digest("hex"). Browsers: crypto.subtle.importKey then crypto.subtle.sign("HMAC", key, data). Python: hmac.new(secret, body, hashlib.sha256).hexdigest(). Compare signatures with a constant-time function such as crypto.timingSafeEqual.