What is an HMAC?
An HMAC (hash-based message authentication code) combines a secret key with a hash function such as SHA-256 to produce a tag that proves a message was created by someone holding the key and was not altered afterwards. It is what signs HS256 JWTs and most webhook payloads; verifying one means recomputing it with the same key and comparing in constant time.
- 1Raw request bodyThe exact bytes your server received
Branch: Pretty-printed, keys reordered or a trailing newline: different bytesFail
- 2Build the signed payloadGitHub, Shopify: the body · Stripe:
<t>.<body>· Slack:v0:<timestamp>:<body>· Twilio: full URL + POST params sorted by name - 3HMAC with your secretSHA-256; SHA-1 for Twilio; generic HMAC also SHA-1 or SHA-512
- 4Encode the resultThe expected signature: hex or Base64; GitHub adds the
sha256=prefix, Slackv0= - 5Constant-time compareExpected vs the signature header value; for Stripe, each
v1valueBranch: No matchFail
Gate: Stripe, Slack: the signed timestamp must be within the tolerance (default 5 minutes), or the result is INVALID
- 6VALIDThe signature matchesPass
GitLab’s shared token and SHA-256 of body + secret skip the HMAC step: the token is compared as it is, and the other is a plain hash.
How to use Webhook Signature Analyzer
- Paste the raw request body exactly as received (no re-formatting).
- Choose the scheme, enter the secret and paste the signature header value.
- For Slack add the request timestamp; for Twilio add the full request URL.
- Press Verify: VALID/INVALID, expected vs provided signature, notes and a code snippet are shown.
Webhook Signature Analyzer features
- Recomputes the expected signature locally with WebCrypto — secrets never leave the browser
- Generic HMAC-SHA256/SHA1/SHA512 (hex/Base64), Stripe, GitHub, Shopify, Slack, Twilio, GitLab token and SHA-256(body+secret)
- Timestamp tolerance checks for Stripe and Slack (replay protection)
- Shows the exact signed payload and constant-time comparison result
- Ready-to-use Node.js verification snippet for the chosen scheme
Webhook Signature Analyzer example
GitHub X-Hub-Signature-256
Input:
Body {"a":1} · Secret s · Signature sha256=37beaf650f70b40ec9706929c2e9d835cbd63729988f48781e6383a147215f07Output:
VALID — the signature matches
Algorithm: HMAC-SHA256 (hex) with "sha256=" prefix
Expected: sha256=37beaf65…215f07Frequently asked questions about Webhook Signature Analyzer
Which schemes are supported?
Generic HMAC-SHA256/SHA1/SHA512 in hex or Base64, Stripe (t=…,v1=… with timestamp tolerance), GitHub (sha256=…), Shopify (Base64), Slack (v0=… with X-Slack-Request-Timestamp), Twilio (URL + sorted params, Base64 SHA1), GitLab shared token and SHA-256 of body + secret.
Why does a valid webhook show INVALID?
Almost always because the body was re-serialised: pretty-printing, changed key order or trailing newlines alter the bytes. Paste the exact raw body your server received.
Is my secret safe?
Yes — the HMAC is computed with WebCrypto in your browser; the secret and payload never leave the page.
What is the timestamp tolerance?
For Stripe and Slack the signed timestamp must be within the tolerance (default 5 minutes) of now, otherwise a replayed delivery is rejected even if the HMAC matches.
Technical notes
Stripe signs "<t>.<body>" and lists v1 signatures in the header; Slack signs "v0:<timestamp>:<body>"; Twilio signs the full URL followed by the POST parameters sorted by name. Comparisons are constant-time to mirror production verification code.
References
- RFC 2104: HMAC: Keyed-Hashing for Message AuthenticationThe HMAC construction: how a secret key and a hash function produce a message authentication code.
- FIPS 198-1: The Keyed-Hash Message Authentication Code (HMAC)The NIST standard for HMAC, including key-length and truncation guidance.
- RFC 6234: US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)Reference descriptions and code for SHA-1, SHA-224/256/384/512 and their use in HMAC.
- RFC 9421: HTTP Message SignaturesA standard way to sign HTTP messages so a receiver can verify their origin and integrity — the basis of modern webhook signatures.