What does it do?
It computes the HMAC (hash-based message authentication code) of a message with a secret key, using SHA-256, SHA-384, SHA-512 or SHA-1, and shows it in hex and Base64. Paste the signature you received and the tool tells you whether it matches.
How to use it
- Paste the raw body of the request, byte for byte.
- Type the secret key. If your provider gives it in hex or Base64, change the key format.
- Paste the signature header you received (
sha256=…, t=…,v1=…, hex or Base64) to check it.
Verifying a GitHub webhook in Node.js
import { createHmac, timingSafeEqual } from "node:crypto";
const expected = "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex");
const valid = timingSafeEqual(Buffer.from(expected), Buffer.from(req.headers["x-hub-signature-256"]));
Frequently asked questions
›Why does my webhook signature never match?
Almost always because the body was modified before hashing: parsed and re-serialised as JSON, trimmed or re-encoded. The HMAC must be computed over the raw bytes exactly as they arrived.
›Which format do Stripe and GitHub use?
GitHub sends X-Hub-Signature-256: sha256=<hex>. Stripe sends Stripe-Signature: t=<timestamp>,v1=<hex>, signing the string <timestamp>.<body>. Paste either header in Signature received.
›How should I compare signatures in my code?
With a constant-time comparison (crypto.timingSafeEqual in Node.js, hmac.compare_digest in Python) to avoid timing attacks.