Free tools

Webhook signature generator

Compute or check an HMAC signature the way Delay, Stripe, GitHub, Shopify and Slack sign their webhooks, and get the code to verify it on your server.

Signature format

Signed exactly as typed, spaces and line breaks included.

String that gets signed

—

Signature

—

Headers

—

Verify it on your server

—

Runs in your browser. Nothing you type here is sent to a server.

Signed requests, on a schedule

Delay calls your endpoints on a cron schedule or when your code asks, and signs every request with your team's secret, so your endpoint can turn away anyone else. Each run keeps the request and the response for debugging. Free for 1,000 requests a month.

How webhook signatures work

The sender and the receiver share a secret. For each request, the sender computes an HMAC of the body (often with a timestamp in front) using that secret, and puts the result in a header. The receiver computes the same HMAC from the body it got and compares. Only someone with the secret can produce a matching signature, so a request from anyone else is rejected.

The timestamp, when there is one, stops replays: the receiver also rejects requests signed more than a few minutes ago, so a captured request can't be sent again later.

Why a correct signature fails to match

Almost always because the receiver didn't sign the exact bytes that were sent. Frameworks parse JSON before your code runs, and encoding it again changes spacing, key order or escaping. {"a":1} and {"a": 1} have different signatures. Read the raw body, verify it, and only then parse it.

The other usual causes: a secret with a stray space or newline, the test-mode secret used for live events, or a different timestamp than the one in the header. Compare in constant time (hash_equals, timingSafeEqual, compare_digest) so the check doesn't leak how much of a guess was right.

How Delay signs requests

With a signing secret set, every request Delay sends to your endpoints carries X-Delay-Signature, an HMAC-SHA256 in hex of the timestamp, a period and the raw body, and X-Delay-Timestamp in Unix seconds. The example loaded above is the one from Delay's docs, so you can check your own code against it.

Questions

Is it safe to paste my webhook secret here?

The signature is computed in your browser with the Web Crypto API, and nothing you enter is sent anywhere. Still, treat a production secret like a password: use a test secret when you can, and rotate any secret you think has leaked.

What is the difference between hex and base64 signatures?

They are two ways to write the same HMAC bytes. Hex uses 0-9 and a-f (64 characters for SHA-256), base64 is shorter (44 characters). Stripe, GitHub, Slack and Delay use hex. Shopify uses base64. Compare in the same encoding the sender used.

Why does Stripe's header have t= and v1=?

Stripe-Signature holds the timestamp (t) and one or more signatures (v1). The signed string is the timestamp, a period and the raw body. Paste the whole header into the check field and the tool uses its timestamp.

Should I use SHA-1 or SHA-256?

SHA-256. HMAC-SHA1 isn't broken the way plain SHA-1 is, but senders have moved on: GitHub still sends X-Hub-Signature (SHA-1) for compatibility and recommends checking X-Hub-Signature-256.

How long should a signing secret be?

At least 32 random bytes, from a secure random generator, not a password someone typed. Store it in your secrets manager or environment, and rotate it when people with access leave.

Schedule your first cron job

Free for 1,000 requests a month. No credit card.

Read the docs