How to Generate HMAC-SHA256 Online (Webhook Signatures, JWT HS256)
Your webhook receiver is rejecting Stripe's payloads as invalid. The signature header doesn't match what your code computes. Somewhere between the raw HTTP body, your endpoint secret, and the HMAC-SHA256 digest, something is off — and you have about ten minutes before someone notices customers aren't getting their receipts. The fastest way out is to compute the HMAC manually, side by side with what your code produces, and find which one drifted.
In this guide you'll learn how to generate HMAC-SHA256 online using PDFFlare's HMAC Generator — paste your message, paste your secret, pick the algorithm, get the digest live as you type. Use it as an hmac generator online, an hmac sha256 generator for webhook signatures, an hmac calculator for AWS Signature v4 chains, or a webhook signature generator when you're building a receiver from scratch. Runs entirely in your browser; your secret never leaves the page.
The same page swaps cleanly between algorithms — flip the selector once and it becomes an hmac sha512 generator for JWT HS512 tokens, an HMAC-SHA-384 calculator for HS384, or an HMAC-SHA-1 tool for legacy Twilio and AWS v2 chains. Switch the output encoding to base64 and you have an hmac base64 generator for the legacy webhooks that still expect that format, or to base64url for jwt hs256 signer use where the digest is appended after the dot. All four algorithms × four output formats are one click apart, so the same page is the hmac calculator onlineyou reach for whether you're debugging Stripe in hex, signing a JWT in base64url, or pasting an old Mailgun digest in base64.
What Is HMAC and Why Do Webhooks Use It?
HMAC stands for Hash-based Message Authentication Code, defined in RFC 2104 with explicit test vectors in RFC 4231. Unlike a plain hash (where anyone with the same input gets the same output), HMAC takes twoinputs: a secret key and a message. Without the secret, you can't reproduce the digest. That's exactly the property a webhook receiver needs.
When Stripe sends you a webhook, the body contains data anyone could fake. The signature header, Stripe-Signature, contains an HMAC-SHA256 of the body computed with your endpoint secret. If your server can recompute the same HMAC from the body it received, the message is authentic. If a forger sends a fake body, they can't produce a matching HMAC because they don't have your secret.
The same construction appears everywhere modern systems sign things: GitHub webhooks (X-Hub-Signature-256), Slack (X-Slack-Signature), Shopify, Discord, Twilio. JWT alg HS256 is HMAC-SHA-256 over base64url-encoded header.payload. AWS Signature v4 chains four HMAC-SHA-256 calls together to derive a signing key. Mastering one HMAC-SHA-256 calculation lets you debug all of these.
How to Generate HMAC-SHA256 Step by Step
- Open the hash generator. Visit /tools/dev/hmac-generator — the dedicated HMAC page on PDFFlare. The tool remembers your last-used algorithm and output format in localStorage, so the next visit lands you exactly where you left off.
- Paste the message. For a webhook this is the raw HTTP request body — exactly the bytes the sender hashed. If you parse the JSON first and re-stringify, spaces and key order can change and your HMAC will diverge. For Stripe, prefix the body with the timestamp from
Stripe-Signaturejoined by a dot:{timestamp}.{body}. - Paste the secret key. Your endpoint secret (Stripe), webhook secret (GitHub), signing secret (Slack), or JWT signing key. The Show / Hide toggle lets you visually verify you pasted the right one without leaving the secret in plaintext on your screen.
- Pick the algorithm. HMAC-SHA-256 is the modern default — Stripe, GitHub, Slack, JWT HS256, AWS Signature v4 all use it. Use HMAC-SHA-512 for JWT HS512, HMAC-SHA-384 for HS384, and HMAC-SHA-1 only for legacy integrations like Twilio or AWS Signature v2.
- Read the digest. The hex digest appears in the output card. For a webhook you compare it against the value in the signature header. For a JWT you base64url-encode the digest bytes and append after the dot.
- Copy and paste it. One-click copy puts the digest on your clipboard. Paste into your terminal, your test fixture, or your stack-trace comparison.
Webhook Signature Recipes (Stripe, GitHub, Slack)
The exact construction varies per provider. The core is always the same — HMAC-SHA-256 over some message with your secret — but the message format and the comparison details differ. Knowing one provider doesn't automatically mean you know the next.
How to verify a Stripe webhook signature
Stripe sends a header like Stripe-Signature: t=1492774577,v1=<hex>,.... Construct the message as {t}.{raw-body} (the timestamp from t=, a dot, then the raw HTTP body string). Compute HMAC-SHA-256 of that with your endpoint secret. Compare the resulting hex digest against the v1= value. Stripe also wants you to reject any request older than five minutes (compare t against current time) — that's the timestamp tolerance check that prevents replay attacks.
How to verify a GitHub webhook signature
GitHub sends X-Hub-Signature-256: sha256=<hex>. The message is just the raw body — no timestamp prefix. Compute HMAC-SHA-256 of the body with your webhook secret, prepend sha256= to the hex digest, and compare against the header. GitHub also sends an older X-Hub-Signature using HMAC-SHA-1 — ignore it; the SHA-256 variant is the canonical one for new code.
How to verify a Slack request signature
Slack sends X-Slack-Signature: v0=<hex> alongside X-Slack-Request-Timestamp. The message is v0:<timestamp>:<raw-body> (note the v0: prefix, the colons, NOT dots). Compute HMAC-SHA-256 with your signing secret. Reject any request older than five minutes for replay protection.
How to verify an AWS Signature v4 derived key
AWS Signature v4 derives a signing key by chaining four HMAC-SHA-256 calls: HMAC("AWS4" + secret, date) → use that result as the key for HMAC(_, region) → that result as the key for HMAC(_, service) → that result as the key for HMAC(_, "aws4_request"). To debug a failing AWS request, compute each stage here and paste the result into the secret field for the next stage. Whichever stage produces a different digest from your code is where the bug is.
Common Mistakes When Generating HMAC-SHA256
Hashing parsed JSON instead of the raw body
The most common bug. Your HTTP framework parsed the JSON for you, you stringified it back, and now spaces, key order, or number precision differ from what the sender hashed. Result: your HMAC never matches. Fix: capture the raw body string before any framework touches it. In Node + Express, use express.raw() for the webhook route. In Next.js, read request.text() not request.json().
Forgetting the timestamp prefix on Stripe / Slack
Stripe's message is timestamp.body. Slack's is v0:timestamp:body. If you forget the prefix your HMAC always diverges. The fix is mechanical — re-read the provider's spec and verify your concatenation matches exactly, dot or colon, character by character.
Using a string-equals comparison instead of constant-time
In production code, comparing your computed HMAC against the header value with === exposes you to timing attacks — an attacker can learn the correct signature byte by byte from response-time differences. Use crypto.timingSafeEqual in Node, hmac.compare_digestin Python, or your framework's constant-time equality helper. This tool is for debugging — your production code needs the constant-time comparison.
Pasting hex when the spec wants base64
PDFFlare's hash generator outputs HMAC digests as lowercase hex (the most common format). Some providers want base64 (Slack actually accepts hex; some Asian providers want base64). Convert hex → bytes → base64 with PDFFlare's Base64 Encode & Decode if you need the alternate encoding.
Treating HMAC like encryption
HMAC is a one-way function. You can't “decrypt” an HMAC to recover the original message. If you need to actually hide the contents of a payload, use real encryption (AES-GCM, libsodium secretbox, JWE) — HMAC only proves the payload wasn't tampered with, not that it's confidential.
Privacy and Security Notes
Computation happens entirely in your browser via the Web Crypto API's crypto.subtle.importKey and crypto.subtle.sign. PDFFlare's hmac generator online never sends your secret to any server, never logs it, never caches it. It's safe to use for development webhook secrets and short-lived signing keys.
That said, an active production webhook secret grants real ability to forge signatures while it's valid. Treat any secret you paste into any tool — including this one — the way you'd treat a password. Close the tab when you're done. Rotate the secret if it might have been exposed (logged, screenshot, copy-pasted somewhere persistent). The Show / Hide toggle exists specifically so you can paste in incognito and never have the plain secret on screen.
Related Tools
- JWT Decoder — once you've generated a JWT HS256 signature here, paste the full token (header.payload.signature) into the decoder to verify the header alg, the payload claims, and the expiration banner all line up.
- Base64 Encode / Decode — convert HMAC hex digests to base64 (or base64url for JWT signatures), encode webhook bodies, decode incoming base64-wrapped tokens.
- UUID Generator — mint
jtivalues for the JWTs you're signing, request IDs for webhook deliveries, and idempotency keys for the API calls you're making with those signatures. - URL Encode / Decode — AWS Signature v4 percent-encodes path components and query params before signing; this tool helps you verify the canonical request matches what AWS expects.
Wrapping Up
HMAC-SHA-256 is the unsung backbone of modern API security — every webhook, every JWT HS256, every AWS request you make touches it. Knowing how to compute one manually turns a mysterious signature mismatch into a five-minute debug session: paste body, paste secret, pick algorithm, compare hex. The mismatch always points at the construction (timestamp prefix? raw body? wrong secret?) — your code didn't break out of the laws of cryptography.
Bookmark the HMAC Generator for the next time a webhook integration breaks at 2 AM. Free, browser-only, no signup — and now the hmac sha256 generator online your team can paste into without thinking twice.