This tool runs entirely in your browser. Nothing you paste is uploaded.
How you can check →HMAC Generator
Security & HashingHMAC-sign or verify a message with hex, base64 or base64url output — with real key-encoding support and the actual Stripe, GitHub, Slack and Shopify signing schemes, not just HMAC(secret, body).
Scheme
Key encoding
This secret looks like it could be hex — if your provider gave you a hex string, switch the key encoding above to Hex, or you'll get a valid-looking, wrong signature.
Output
Signed payload — the exact bytes HMAC'd
Equivalent command or code
No known tool or library computes HMAC with this preset's algorithm and construction — the signed-payload preview above still shows the exact bytes to feed your own code.
Signature
No network activity while you use this tool Show the numbers
- Requests to any other server
- 0
- Requests since you started typing
- —
- Same-origin requests
- 0
Counted live by your browser's own Performance Timeline — the same data the DevTools Network panel reads. It cannot see what a browser extension does, and it is not meant to replace checking for yourself: here is how, in thirty seconds .
HMAC vs. a plain hash of the secret and message
It's tempting to think HMAC is just hash(secret + message), but that construction
is broken for Merkle–Damgård hashes like MD5 and SHA-2: an attacker who knows the digest and
the message's length can compute a valid hash for secret + message + attacker-data
without ever learning the secret, a length-extension attack. HMAC (RFC 2104) fixes this with a
nested construction — the key mixed in twice, once inside and once outside — that is provably
resistant to length extension. This is why every real signing scheme uses HMAC specifically,
not a hand-rolled hash-and-concatenate.
Key encoding: the trap almost nobody handles
An HMAC secret is a byte string, and how you turn text into bytes changes every signature. A 64-character hex secret is 32 raw bytes; read as UTF-8 text instead, those same 64 characters are 64 bytes of ASCII — two different keys, two different signatures, both "valid-looking". AWS-style secrets are often base64; webhook secrets are usually plain UTF-8 text. This page's key-encoding control lets you say which one you actually have, rather than silently assuming UTF-8 the way almost every other HMAC tool does.
The raw-body trap
Every webhook scheme below signs the raw request body — the exact bytes the provider sent — never a re-serialized version of it. If your code parses the JSON, does something with it, and then re-serializes it to compute the signature, the re-formatted bytes (different whitespace, different key order) won't match, and you'll conclude your secret is wrong when your code was. Always sign the raw body you received, before any parsing.
What each preset actually signs
- GitHub — HMAC-SHA-256 of the raw body, hex, prefixed
sha256=. - Stripe — HMAC-SHA-256 of
"<timestamp>.<raw body>", hex, insidet=…,v1=…. - Slack — HMAC-SHA-256 of
"v0:<timestamp>:<raw body>", hex, prefixedv0=. - Shopify — HMAC-SHA-256 of the raw body, base64, not hex.
- Twilio — HMAC-SHA-1 of the full URL plus every POST parameter, sorted by key and concatenated with no separators, base64.
- JWT HS256 — HMAC-SHA-256 of
"<base64url header>.<base64url payload>", base64url, unpadded.
Common use cases
- Signing an API request or webhook payload with a shared secret
- Verifying an incoming Stripe, GitHub, Slack, Shopify or Twilio webhook against its header
- Debugging why a webhook signature doesn't match — usually the raw-body trap above
- Verifying a JWT's HS256 signature when you have the secret
- Computing an HMAC for any other protocol that specifies it
Frequently asked questions
- What's the difference between HMAC and a plain hash of the secret plus the message?
- A plain hash like SHA-256(secret + message) is vulnerable to a length-extension attack: for SHA-256 and other Merkle–Damgård hashes, an attacker who knows the digest and the message length can compute a valid hash for secret + message + extra-data without ever knowing the secret. HMAC's nested construction (RFC 2104) is specifically designed to prevent this — it hashes twice, with the key mixed in both times, which is why HMAC is the standard rather than a hand-rolled 'hash the secret and the message together' scheme.
- My secret is hex — why is my signature wrong?
- Because a secret is a byte string, and hex text isn't the same bytes as the string that spells it. A 64-character hex secret is 32 raw bytes; treated as UTF-8 text instead, it's 64 bytes of ASCII digits and letters — two completely different keys that produce two completely different signatures. This is the single most common HMAC support question, and almost no other tool offers a key-encoding control at all. Set it to Hex here whenever your provider handed you a hex string.
- Why doesn't my webhook signature match what I compute?
- Almost always because the signed payload isn't just the body. Stripe signs "<timestamp>.<body>", Slack signs "v0:<timestamp>:<body>", and both reject anything computed over a re-serialized JSON object — the signature is over the exact raw bytes the provider sent, and re-formatting the JSON (even just reordering keys or changing whitespace) produces different bytes and a different signature. Pick the matching preset here and its signed-payload preview shows you the exact string that gets HMAC'd, separators included.
- Does Shopify really use base64, not hex?
- Yes — X-Shopify-Hmac-Sha256 is base64-encoded, while GitHub's X-Hub-Signature-256 and Slack's X-Slack-Signature are hex. Mixing these up produces a signature that looks plausible and is completely wrong, which is exactly the failure mode this page's per-preset output encoding exists to prevent.
- Can this verify a JWT's HS256 signature?
- Yes, if you have the secret — pick the JWT HS256 preset, paste the token's header.payload as the message (or paste the whole token and the header/payload segments before the last dot are used), enter the secret, and compare the result against the token's third segment. The JWT decoder tool can only read a token's claims; it explicitly cannot verify a signature, which is what this page is for.
- Does this upload my secret anywhere?
- No. HMAC is computed entirely in this tab by JavaScript; your secret and message are never sent anywhere, and this page's key field is deliberately excluded from the shareable-link feature other tools on this site use, so a secret can never end up in a URL. The privacy receipt below the tool measures the actual network requests from this page load, so the claim is checkable rather than asserted.
Explore more tools
Every hash of your text at once — MD5 through BLAKE3 — computed twice and cross-checked against the browser's own crypto.
Decode a JSON Web Token's header and payload instantly.
Checksum any file — even multi-gigabyte ones — with a measured progress bar and a working cancel, entirely in your browser.