HMAC Generator & Verifier
Generate HMAC-SHA256 and HMAC-SHA512 signatures for webhook validation and API request signing. Verify incoming webhook payloads against their expected signatures. All cryptographic operations run in your browser via the Web Crypto API.
Paste an incoming webhook signature to verify it matches the computed HMAC above.
crypto.subtle.sign() API. Your secret key and payload never leave your browser.
Quick Overview
The HMAC Generator computes HMAC-SHA256 and HMAC-SHA512 signatures using a secret key and a message payload, entirely within your browser. HMAC (Hash-based Message Authentication Code) is a cryptographic construct that combines a hash function with a shared secret to produce a signature that proves both the integrity of a message β that it has not been modified β and its authenticity β that it was produced by someone who knows the secret key. Unlike a plain hash, an HMAC cannot be forged without knowing the secret, making it the standard mechanism for securing webhooks and signing API requests.
Every major SaaS platform that delivers webhooks β GitHub, Stripe, Slack, Shopify, Twilio, and hundreds of others β uses HMAC-SHA256 signatures to allow receiving servers to verify that incoming HTTP requests genuinely came from the platform and were not injected by a third party. Understanding how to compute and verify these signatures is a fundamental skill for any backend engineer building integrations or for SREs responsible for securing event-driven infrastructure.
Technical Details
All HMAC computation uses the browser's native crypto.subtle.sign() API with the HMAC algorithm. The secret key is imported as a CryptoKey object using crypto.subtle.importKey(), which prevents the raw key bytes from being exposed to JavaScript code after import. The message and secret are encoded to UTF-8 bytes using the TextEncoder API before being passed to the cryptographic function. The resulting bytes can be formatted as lowercase hex, standard base64, URL-safe base64, or the sha256=hex prefixed format used by GitHub's webhook verification.
Common Use Cases
- Debugging webhook verification failures: Manually compute the expected HMAC signature for a captured webhook payload to identify whether the mismatch is caused by a wrong secret, incorrect encoding, or a payload transformation issue.
- Testing webhook integrations in development: Generate a valid signature for a test payload so you can send it with curl or Postman and verify your receiving endpoint's signature-checking logic works correctly before going to production.
- Learning the webhook security model: Interactively experiment with different secrets, algorithms, and output formats (hex, base64, prefixed) to understand how platforms like GitHub format their
X-Hub-Signature-256header. - API request signing: Compute HMAC signatures for REST APIs that use signed request authentication, such as AWS Signature Version 4 or custom HMAC-based auth schemes.
Best Practices & Tips
Always sign the raw, unparsed request body bytes β not a re-serialized version of the JSON. If your webhook handler parses the body into an object and then re-serializes it before computing the comparison HMAC, differences in key ordering or whitespace between the original payload and your re-serialized version will produce a different signature and a false-negative verification failure; capture and sign the exact bytes as received, before any JSON parsing. Rotate webhook secrets on a schedule and support two active secrets during the rotation window (verify against either), since most platforms don't offer a zero-downtime secret rotation mechanism on their own. Store the secret in a secrets manager (Vault, AWS Secrets Manager, or your CI/CD platform's encrypted secrets) rather than an environment variable baked into a container image β a leaked image layer should not also leak your webhook secret. Finally, when troubleshooting a signature mismatch, check encoding before assuming the secret is wrong: a secret with a trailing newline (common when copy-pasted from a terminal or a `.env` file) produces a completely different HMAC than the same secret without it, and this is one of the most common causes of "valid secret but invalid signature" reports.
Frequently Asked Questions
What is HMAC?
HMAC (Hash-based Message Authentication Code) is a cryptographic mechanism defined in RFC 2104 that uses a secret key combined with a hash function β typically SHA-256 or SHA-512 β to produce an authentication tag for a message. Unlike a plain hash, which anyone can compute from the data alone, an HMAC requires knowledge of the secret key to produce or verify. This makes HMAC suitable for proving both the integrity of a message (it has not been altered) and its authenticity (it came from someone who holds the same secret). The security of HMAC depends entirely on the secrecy and strength of the key, not on keeping the algorithm secret.
What are HMAC signatures used for?
HMAC signatures are primarily used for webhook payload verification, where a platform signs the HTTP request body with a shared secret so the receiving server can confirm the request is genuine. GitHub sends an X-Hub-Signature-256 header containing sha256=<hex>, Stripe sends a Stripe-Signature header with a timestamp and v1=<hex> components, Slack sends X-Slack-Signature as v0=<hex>, and Shopify sends X-Shopify-Hmac-Sha256 as base64-encoded HMAC. Beyond webhooks, HMAC is used in API authentication schemes, JWT signing (the HS256 and HS512 algorithms in JWTs use HMAC), cookie signing to prevent tampering, and as a key derivation building block in protocols like TLS.
Why should I use timing-safe comparison when verifying HMAC signatures?
Standard string equality operators short-circuit as soon as they find the first non-matching character, which means the comparison takes less time when the strings diverge early. An attacker making thousands of requests with subtly different signatures can measure response times to determine how many leading characters of their forged signature match the expected value β a technique called a timing side-channel attack. Over many requests, this information can be used to reconstruct a valid signature without knowing the secret key. Timing-safe comparison functions like crypto.timingSafeEqual in Node.js, hmac.compare_digest in Python, and hmac.Equal in Go always compare the full length of both strings regardless of where they diverge, eliminating this attack vector. Always use these functions in production webhook verification code.