HMAC generator

Compute a keyed HMAC over a message using SHA-1, SHA-256, SHA-384, or SHA-512.

What this does

HMAC-SHA512 generates a 512-bit message authentication code from a message and a secret key. Unlike a plain SHA-512 hash, only someone with the shared key can reproduce the tag. Choose SHA-512 in this tool when a protocol or existing integration specifically requires it. Use the algorithm required by your protocol or integration.

This tool also computes HMAC-SHA1, HMAC-SHA256, and HMAC-SHA384 with the browser's SubtleCrypto. The key can be entered as UTF-8 text, hex, or Base64, and the tag can be shown as hex or Base64, so you can reproduce whatever format the system you're integrating with uses.

HMAC is defined by RFC 2104; the SHA-512 hash function is specified in NIST FIPS 180-4.

Everything runs locally. Nothing about the key or message is transmitted.

When you'd use it

  • Verifying an incoming webhook signature (Stripe, GitHub, Shopify, Slack, and many others sign their payloads with HMAC-SHA256).
  • Signing an outgoing API request that uses a shared-secret scheme (for example AWS SigV4-style or older HMAC auth).
  • Generating a tamper-evident token or a signed URL parameter.
  • Debugging a signature mismatch by isolating which input — body, key encoding, output encoding — is wrong.

Worked example

Message id=42&amount=1000, key topsecret (as UTF-8 text), HMAC-SHA256, hex output:

641bedff29f7168bc87504b5927bf20598fcf9cd5a4f5022b8317310f0de54a9

Switch the output to Base64 and the same 32 bytes become ZBvt/yn3FovIdQS1knvyBZj8+c1aT1AiuDFzEPDeVKk= — this is exactly the choice that trips people up when a provider's header is Base64 but their example code prints hex. Change the key encoding to "Hex" without changing the key text and the tool rejects it: after non-hex characters are removed, an odd number of digits remains. Reproduce the provider's documented example first; once that matches, your real payload will too.

Limits and gotchas

  • Sign the exact bytes. For webhooks, that usually means the raw request body before any JSON parsing or reformatting.
  • Key encoding is not cosmetic. The same characters interpreted as text, hex, or Base64 are three different keys.
  • Output encoding must match the value you compare against, including any provider prefix like sha256=.
  • Production comparisons must be constant-time. Don't ship a plain === check.
  • HMAC-SHA1 is still cryptographically acceptable for HMAC use, but choose SHA-256 for anything new unless a spec forces SHA-1.
  • This is authentication, not encryption. The message is not hidden; HMAC only detects tampering and proves origin.

Frequently asked questions

What is the difference between a hash and an HMAC?
A plain hash of message can be recomputed by anyone. An HMAC mixes a secret key into the hashing process, so only someone who holds the key can produce or check the value. That is what makes it a message authentication code: it proves both that the message wasn't altered and that it came from someone with the key.
My HMAC doesn't match the webhook's signature header.
The usual causes: (1) hashing the wrong bytes — many providers sign the exact raw request body, so re-serialising the JSON changes it; (2) wrong key encoding — the secret might be hex or Base64, not text; (3) the provider prefixes the value (for example sha256=) or uses Base64 while you used hex; (4) a timestamp or other field is concatenated with the body before signing. Check the provider's signing recipe precisely.
Why can't I just use == to compare two HMACs in my own code?
A normal string comparison returns as soon as it finds a differing byte, which leaks timing information an attacker can use to recover the correct value byte by byte. Use a constant-time comparison function (crypto.timingSafeEqual in Node, hmac.compare_digest in Python). Comparing here in the browser for debugging is fine; the production check needs to be constant-time.
Is the secret I type sent anywhere?
No. The key and message are passed to the browser's SubtleCrypto HMAC implementation locally. Nothing leaves the page. Still, prefer a test key over your real production secret when you can.