Pack Camo

HMAC Generator & Verifier

HMAC-SHA256, SHA-1, SHA-384 and SHA-512 signatures, with hex, Base64 or text keys.

Everything runs locally with zero file uploads.

Secret key

3 bytes

Message

43 bytes

Signature HMAC-SHA-256

  • HexComputing…
  • HEXComputing…
  • Base64Computing…
  • Base64urlComputing…
  • HeaderComputing…

Compute an HMAC, or check the one a webhook sent you

This HMAC generator signs a message with a secret key using HMAC-SHA256, HMAC-SHA1, HMAC-SHA384 or HMAC-SHA512, and shows the signature in lowercase hex, uppercase hex, Base64 and Base64url at once. The key and the message can each be typed as plain text, hex or Base64, so it works with raw binary secrets as well as passwords. Paste the signature you received — <code>sha256=…</code> from GitHub, a Stripe <code>t=…,v1=…</code> header or plain Base64 — and it tells you whether it matches. The calculation uses your browser's Web Crypto API; the key and the message never leave the page.

How to generate or verify an HMAC

  1. 1Pick the hash function: SHA-256 is what most APIs and webhooks use.
  2. 2Type or paste the secret key and choose how it is written: text, hex or Base64. Use Random key to create a new secret of the right length.
  3. 3Paste the message — for a webhook, the raw request body exactly as it arrived, byte for byte.
  4. 4Copy the signature in the encoding you need. To check a signature, paste it into Expected signature; a prefix such as sha256= is understood and ignored.

What is an HMAC?

An HMAC (hash-based message authentication code, RFC 2104) is a short value computed from a message and a secret key. Anyone who knows the key can compute the same value and so check two things at once: that the message was not changed on the way, and that it was produced by someone who holds the key. Without the key, an attacker can neither forge a valid HMAC for a new message nor adjust one after changing the message.

It is not simply a hash of the key and the message stuck together. HMAC hashes twice, with the key mixed into an inner and an outer pad: H((K ⊕ opad) ‖ H((K ⊕ ipad) ‖ message)). That construction is what makes it safe with SHA-256 and SHA-512, which on their own are open to length-extension attacks when used as H(key ‖ message).

Verifying webhook signatures

Most webhook providers sign each request with an HMAC of the body and put the result in a header. To verify one, compute the HMAC of the raw body with your signing secret and compare it with the header value. The commonest mistake is hashing a re-serialised JSON object instead of the bytes that arrived: a different key order or a missing space changes the signature completely.

Some providers sign more than the body. Stripe signs timestamp.body — the t value from the header, a dot, then the payload — and Slack signs v0:timestamp:body. Build that exact string as the message here, and paste the full header into the verify box; the v1= or v0= value is picked out of it.

GitHub
<code>X-Hub-Signature-256: sha256=&lt;hex&gt;</code>, HMAC-SHA256 of the body with the webhook secret as text.
Stripe
<code>Stripe-Signature: t=…,v1=&lt;hex&gt;</code>, HMAC-SHA256 of <code>t.body</code>.
Shopify
<code>X-Shopify-Hmac-Sha256: &lt;Base64&gt;</code>, HMAC-SHA256 of the body.
Slack
<code>X-Slack-Signature: v0=&lt;hex&gt;</code>, HMAC-SHA256 of <code>v0:timestamp:body</code>.

Text, hex and Base64 keys

A key is a sequence of bytes, and how it is written matters. The text abc123 is six bytes; the hex abc123 is three completely different bytes. Many services hand out secrets as hex or Base64 strings but expect you to use the string itself as a text key — GitHub and Stripe both do — while others, such as AWS-style signing chains and Shopify's app proxies, use the decoded bytes. If a signature does not match, switching the key encoding is the first thing to try.

For a new key, use random bytes at least as long as the hash output: 32 bytes for HMAC-SHA256, 64 for HMAC-SHA512. Longer keys add nothing — anything over the hash's block size is hashed down first.

Constant-time comparison

When your server checks a signature, compare it with a constant-time function such as crypto.timingSafeEqual in Node.js, hmac.compare_digest in Python or hash_equals in PHP. A normal string comparison stops at the first differing character, and the time that takes can leak how much of a forged signature was right. This page uses the same constant-time pattern, so the code is a reference as well as a check.

If you only need an ordinary checksum of a file or text, without a key, use the hash generator. For signing tokens, the JWT secret generator creates HS256 keys of the right size.

Frequently asked questions

What is the difference between a hash and an HMAC?
A hash such as SHA-256 depends only on the data, so anyone can recompute it. An HMAC also depends on a secret key, so only someone holding the key can produce or check it. That makes an HMAC proof of authenticity, not just of integrity.
Why does my HMAC not match the one from the API?
Almost always the input differs: the message is not byte-for-byte the raw body (re-serialised JSON, a trailing newline, different line endings), the key is being read as text when the service means hex or Base64 bytes or vice versa, or the provider signs a timestamp plus the body rather than the body alone.
Which HMAC algorithm should I use?
HMAC-SHA256 is the standard choice and what nearly every API uses. HMAC-SHA512 is equally fine and faster on 64-bit servers. HMAC-SHA1 is still secure as an HMAC, despite SHA-1 collisions, but use it only where a protocol requires it.
Is HMAC-SHA1 broken?
No. SHA-1 collisions do not give a way to forge an HMAC-SHA1 without the key, and no practical attack on HMAC-SHA1 is known. It is deprecated for new designs, but verifying legacy HMAC-SHA1 signatures is safe.
Can I compute HMAC-MD5 here?
No. The browser's Web Crypto API, which this page uses, does not implement MD5. HMAC-MD5 survives only in old protocols; use HMAC-SHA256 for anything new.
How long should an HMAC key be?
At least as long as the hash output: 32 random bytes for HMAC-SHA256, 48 for SHA-384, 64 for SHA-512. The Random key button generates exactly that from your browser's secure random number generator.
Can I use an empty key?
HMAC allows it and the result is well defined, so the tool shows it, but an empty or short key gives no security. Anyone could compute the same signature.
Is my secret key sent anywhere?
No. The HMAC is computed by your browser's Web Crypto API on this page. Nothing you type is uploaded or stored.