SecurityTools & Guides

HMAC SHA-256 Generator – Sign and Verify Webhook Payloads

Generate HMAC-SHA256 signatures and verify webhook payloads instantly

No signup • Runs in browser • Free

Generate HMAC Signature →

A plain SHA-256 hash of a webhook payload proves the payload has not changed — but it does not prove who sent it. Anyone who intercepts the payload can compute the same SHA-256 hash. HMAC-SHA256 solves this by mixing a shared secret key into the hash computation. Without the secret, an attacker cannot compute a valid signature — and your server can reject any request that does not carry one. This is exactly how Stripe, GitHub, Shopify, and virtually every major webhook platform authenticate their event deliveries.

HMAC (Hash-based Message Authentication Code) is a keyed hash: the signature is a function of both the payload and the secret. The same payload with a different secret produces a completely different signature. This means a valid HMAC signature on a webhook confirms both that the payload has not been tampered with (integrity) and that it was signed by someone who knows the secret (authenticity). A hash generator that supports HMAC lets you generate and verify these signatures without a code environment.

# Webhook signature verification — Stripe pattern:
Secret key:  whsec_abc123secret
Payload:     {"id":"evt_1","type":"payment_intent.created","amount":1000}
Timestamp:   1711576800

# Stripe signs: "timestamp.payload"
Signing input:  1711576800.{"id":"evt_1","type":"payment_intent.created","amount":1000}
HMAC-SHA256:    3d9e4f2a8b1c5067d4e9f3a2b8c1d5e6f7a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6

# Your server computes the same HMAC and compares — if it matches, the webhook is authentic
# If the secret leaks, rotate it immediately — all future webhooks use the new secret

Quick summary

  • HMAC combines a secret key with the payload — a valid signature proves both integrity and authenticity.
  • Plain SHA-256 proves integrity only — anyone with the payload can compute the same hash.
  • Stripe, GitHub, Shopify, and most major platforms use HMAC-SHA256 to sign webhook deliveries.
  • DevToolBox tools run entirely in your browser — no signup.

HMAC vs Plain Hash

The distinction matters for security: a plain cryptographic hash (SHA-256, MD5, SHA-512) is a public function. Given any input, anyone can compute the correct hash. This makes plain hashes useful for file integrity — you publish the hash alongside the file, and anyone can verify the download — but useless for authentication, because anyone can also compute the hash of a forged payload.

HMAC introduces a secret key into the computation. The HMAC-SHA256 of a message is computed as HMAC(key, message) using a construction that applies SHA-256 twice with the key mixed in at specific positions. Without the key, the computation cannot be reproduced. With the key, it is deterministic — the same key and message always produce the same HMAC output.

This gives HMAC two properties that a plain hash cannot provide:

  • Authenticity. A valid HMAC signature on a payload proves the signer had access to the secret key. If only your server and the platform know the key, a valid signature proves the platform sent it.
  • Integrity. A changed payload produces a different HMAC, even with the same key. Tampering with the payload invalidates the signature.

For the underlying hash algorithm comparison, see our guide on MD5 vs SHA-256 vs SHA-512. For the basics of hash functions, see Hash Generator Online.

The Webhook Signing Pattern

Every major platform that sends webhooks uses a variant of the same pattern. Understanding it lets you implement verification for any platform.

# Generic webhook verification pattern:

1. The platform sends:
   - The payload (JSON body)
   - A signature header (e.g., X-Hub-Signature-256 or Stripe-Signature)
   - Often a timestamp (to prevent replay attacks)

2. The platform computes the signature as:
   HMAC-SHA256(secret_key, signing_input)
   # signing_input varies by platform:
   # GitHub:  the raw request body
   # Stripe:  "timestamp.body"
   # Shopify: the raw request body

3. Your server:
   a. Reads the raw request body (before JSON parsing)
   b. Reconstructs the signing input
   c. Computes HMAC-SHA256 with your stored secret
   d. Compares using constant-time comparison
   e. Accepts if match, rejects with 401 if not

The critical detail is step (a): always compute the HMAC on the raw bytes of the request body, before any JSON parsing or normalization. Parsing JSON and re-serializing it may change whitespace, key order, or number formatting — producing a different HMAC than what the platform signed.

How to Generate an HMAC Signature

Using the DevToolBox Hash Generator to compute an HMAC-SHA256 takes under a minute.

  1. Open the tool in your browser. No account, no install.
  2. Select HMAC-SHA256 as the algorithm.
  3. Enter your secret key in the key field.
  4. Paste the signing input — the raw payload, or the timestamp-prefixed payload if the platform requires it.
  5. The tool outputs the HMAC-SHA256 digest as a hex string.
  6. Compare this to the signature in the webhook header using a constant-time comparison.

DevToolBox tools run entirely in your browser — nothing you paste is transmitted to any server. You can safely test with real webhook secrets and payloads.

Common HMAC Verification Errors

  • Computing HMAC on the parsed body. If you parse the JSON body first and then re-serialize it for the HMAC computation, the output may differ from what the platform signed — different whitespace, different number formatting, different key order. Always compute HMAC on the raw request body bytes.
  • Not using constant-time comparison. A regular string equality check (===, ==) short-circuits on the first mismatched character. An attacker can use response timing to learn how many leading characters of their forged signature match the correct one. Use a constant-time comparison function — hmac.compare_digest in Python, crypto.timingSafeEqual in Node.js.
  • Including or excluding the timestamp prefix. Stripe's signature covers "timestamp.body", not just the body. GitHub's covers only the body. Using the wrong signing input produces a different HMAC and causes all webhook verifications to fail. Read the platform's documentation for the exact signing input format.
  • Whitespace in the secret key. If you copy-paste a webhook secret and accidentally include a leading or trailing space, the HMAC will be computed with a different key than intended. Trim the secret before use.

Frequently Asked Questions

Why do webhook platforms use HMAC instead of asymmetric signatures?

HMAC is symmetric — the same key is used to sign and verify. Asymmetric signatures (like RSA or ECDSA) use a private key to sign and a public key to verify, which would mean you could verify webhooks without knowing the secret. HMAC is simpler, faster, and sufficient for the webhook use case where both parties (the platform and your server) are trusted. Some newer platforms (like Svix) offer asymmetric webhook signatures for use cases where asymmetry is beneficial.

How should I store the webhook secret?

Treat it like a database password: store it in an environment variable or a secrets manager, never in source code or version control. Rotate it immediately if it is ever exposed. Platforms like Stripe and GitHub provide a one-click secret rotation in their dashboards.

What is a replay attack and how does the timestamp prevent it?

A replay attack captures a valid webhook request and re-sends it later to trigger the same action twice. Including a timestamp in the signing input and rejecting webhooks with timestamps more than a few minutes old prevents replays — the old signature covers an old timestamp, and recomputing with the current timestamp produces a different signature. Stripe rejects webhooks older than five minutes by default.

Conclusion

HMAC-SHA256 is the standard mechanism for webhook authentication because it is simple, fast, and provides both integrity and authenticity guarantees with a shared secret. The implementation is straightforward: compute HMAC on the raw request body with the platform's secret key and compare using a constant-time function. Getting the signing input format right — matching the platform's exact construction — is the only place where implementations typically diverge.

If you need a fast HMAC generator to sign or verify webhook payloads in your browser, DevToolBox does exactly that. DevToolBox tools run entirely in your browser — no signup, no install, nothing sent to a server.

Generate HMAC-SHA256 signatures in seconds

Enter your secret and payload — get the HMAC signature for webhook verification. Free, no signup, browser-only.

Open Hash Generator →

Related Articles

Helpful tools for Security