# How to Generate HMAC-SHA256 Online (Webhook Signatures, JWT HS256)

URL: https://pdfflare.com/blog/how-to-generate-hmac-sha256-online
Published: May 6, 2026
Reading time: 10 min read

> Generate HMAC-SHA256 online for Stripe, GitHub, Slack webhook signatures, JWT HS256 tokens, and AWS Signature v4 chains. Browser-based, no signup.

---

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](https://pdfflare.com/tools/dev/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 online**you 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 _two_inputs: 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

1. **Open the hash generator.** Visit [/tools/dev/hmac-generator](https://pdfflare.com/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.
2. **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-Signature` joined by a dot: `{timestamp}.{body}`.
3. **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.
4. **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.
5. **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.
6. **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_digest`in 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](https://pdfflare.com/tools/dev/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](https://pdfflare.com/tools/dev/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](https://pdfflare.com/tools/dev/base64-encode-decode) — convert HMAC hex digests to base64 (or base64url for JWT signatures), encode webhook bodies, decode incoming base64-wrapped tokens.
- [UUID Generator](https://pdfflare.com/tools/dev/uuid-generator) — mint `jti`values 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](https://pdfflare.com/tools/dev/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](https://pdfflare.com/tools/dev/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.

---

## Frequently asked questions

**Q: What's the difference between HMAC and SHA-256?**

A: SHA-256 is a one-input hash — paste a string, get a 256-bit digest. HMAC-SHA-256 is a two-input function — paste a message AND a secret key, get a 256-bit digest only someone with the same secret can reproduce. Webhooks and JWTs use HMAC because the secret proves the message wasn't forged. SHA-256 alone can't do that — anyone can compute it.

**Q: Why does my Stripe webhook signature not match?**

A: Three usual suspects. (1) You parsed the JSON body before hashing — Stripe hashes the raw bytes including their exact whitespace and key order; if your framework re-serialised, the digest diverges. Capture the raw body before parsing. (2) You forgot the timestamp prefix — Stripe's signed payload is `{timestamp}.{body}`, not just the body. (3) Wrong secret — endpoint secrets and webhook signing secrets aren't the same thing in Stripe; use the one for the specific endpoint that received the request.

**Q: Can I use this tool to sign a JWT?**

A: Partly. JWT alg HS256 = HMAC-SHA-256 over base64url-encoded `header.payload`. You can compute the HMAC here, but you'll need to base64url-encode the resulting bytes (this tool returns hex; convert via the Base64 Encode/Decode tool). For full token construction it's usually easier to use a JWT library. This tool shines for verifying that your library produces the same HMAC you compute manually — the cross-check that catches subtle alg or encoding bugs.

**Q: Is HMAC-SHA-1 still safe in 2026?**

A: For HMAC purposes, HMAC-SHA-1 is still considered secure — collision attacks against SHA-1 don't trivially translate to HMAC attacks. But there's no good reason to choose it for new code; HMAC-SHA-256 is faster on most modern hardware and avoids the optics of using SHA-1 for anything. Use HMAC-SHA-1 only for legacy compatibility (older Twilio, AWS Signature v2). For everything else, default to HMAC-SHA-256.

**Q: Does this tool support HMAC-MD5?**

A: No. The browser's Web Crypto API exposes HMAC for SHA-1, SHA-256, SHA-384, and SHA-512 only. HMAC-MD5 is deprecated for security use and any system that still requires it can be implemented from MD5 plus the standard HMAC construction (key xor opad || H(key xor ipad || message)). For new code, use HMAC-SHA-256 — it's better-supported, faster on modern CPUs, and not subject to MD5's collision weaknesses.

---

## About PDFFlare

PDFFlare is a free collection of online tools for working with PDFs, images, text, JSON, and developer utilities. All tools run client-side in your browser — no signup, no upload to our servers, no rate limits.

For the full site index, see https://pdfflare.com/llms.txt.
For the complete content dump in one file, see https://pdfflare.com/llms-full.txt.