HMAC Generator
HMAC Generator
Sign and verify messages with HMAC. Computes seven algorithms in your browser — no data leaves this page.
Algorithm
Examples
Click a preset to load a known message and key.
About HMAC Generator
HMAC (Hash-based Message Authentication Code) is the workhorse of webhook signature verification. You give it a message and a secret key; it produces a keyed digest that a receiver with the same key can verify. This tool runs seven HMAC variants in your browser — no data is sent to any server — and gives you a per-row copy-as-curl-header and copy-as-Python-snippet action so you can drop the result straight into a shell session or a verifier script.
The seven algorithms
- HMAC-MD5 — legacy (Stripe v1 webhooks, RADIUS, some internal protocols). Included for compatibility only; do not use for new designs.
- HMAC-SHA-1 — still common in legacy webhook providers and AWS v2 signatures.
- HMAC-SHA-256 — the workhorse. Stripe v2, GitHub, Slack, Shopify, and the default for JWT HS256 all use this.
- HMAC-SHA-512 — used by some banking and high-security APIs.
- HMAC-SHA3-256 and HMAC-SHA3-512 — the NIST FIPS 202 SHA-3 family, increasingly used in newer specs and IoT signing protocols.
- HMAC-RIPEMD-160 — used in Bitcoin address derivation and a handful of European banking protocols.
Verify a signature in constant time
The verification half of the tool pastes the inbound signature (with provider-specific prefix parsing — see below) and compares it against the freshly-computed value using a byte-wise XOR-accumulator that runs in time proportional to the length of the input rather than the position of the first differing byte. This is the correct comparison shape when a remote attacker can time your verification path. Toggle off the constant-time mode to see the difference (the match values are identical, but the warning appears as a reminder not to use it in production).
Provider prefix parsing
Real-world inbound signatures are wrapped in provider-specific prefixes: sha256=<hex> for GitHub,
v0=<hex> for Slack, and a compound t=<ts>,v1=<hex>,v0=<hex> for Stripe. The tool
auto-detects these prefixes, strips them, and shows a visible annotation describing what was stripped. Toggle
Treat input literally to disable parsing and normalization (useful for testing the parser itself, or for
providers with non-standard formats).
Copy as a curl header or as a Python verifier
Each row's Copy as curl header action produces a ready-to-paste curl -H 'Header: <hex>' line; the
Copy as Python action produces a snippet using the standard-library hmac module that always
ends with hmac.compare_digest (the standard-library constant-time compare). The Python snippet is
faithful to the active key encoding: hex keys use bytes.fromhex, base64 keys use
base64.b64decode, UTF-8 keys use b'…' literals.
Built-in webhook provider presets
- RFC 2202 / RFC 4231 reference vectors (HMAC-SHA-1 and HMAC-SHA-256 of "Jefe" / "what do ya want for nothing?").
- Stripe v2 webhook (hex-encoded
whsec_key, compoundt=<ts>.<body>message). - GitHub webhook (UTF-8 secret, JSON body,
sha256=prefix). - Slack request signing (UTF-8 secret,
v0:<ts>:<body>message). - JWT HS256 signing (base64-encoded secret,
header.payloadmessage, base64url signature).
Click a preset to load the message, key, expected signature, curl header name, and prefix parser — the corresponding row will show MATCH so you can confirm the tool is correctly implemented before you trust it on your own data.
Common use cases
- Verifying inbound webhook signatures (Stripe, GitHub, Slack, custom).
- Reproducing a signature in a script or terminal to compare against an upstream service.
- Generating the expected signature for a new webhook integration while writing the verifier code.
- Learning the difference between HMAC-SHA-256 and HMAC-SHA3-256 by comparing the same message and key.
- Auditing a third-party library's HMAC implementation against the published test vectors.
Security notes
All computation runs in the browser. No message, key, or computed HMAC is sent to any server. The Clear all button wipes the message, key, and expected-signature fields in one click — but it does not auto-clear on tab-hidden, navigation, or any other automatic trigger, so your workflow (paste a key, alt-tab to a terminal, paste a curl, alt-tab back, tweak) keeps working.
Comments
Please accept the "Functionality" cookie category to view and post comments.
Comments failed to load. You can try again or view the discussion directly on GitHub.
View on GitHub