Skip to main content
SnipKit

HMAC Generator

Compute and verify HMAC signatures (SHA-1/256/384/512) in your browser via Web Crypto.

Processed locally in your browser

Empty key produces a valid but cryptographically meaningless HMAC.

Privacy: All HMAC computation runs locally via the Web Crypto API. Your message and secret never leave this browser tab — nothing is uploaded, logged, or transmitted. Verification usescrypto.subtle.verifyfor constant-time comparison.

Unlock the full toolkit

Batch processing, no ads, higher limits, and API access.

Go Premium

How to Use

1. Pick a hash algorithm — SHA-256 is the default and matches most webhook providers (Stripe, GitHub, Slack). 2. Paste the message you want to authenticate (raw request body, payload, etc.). 3. Enter the shared secret. 4. The HMAC is computed live in three formats — copy whichever your verifier expects. 5. Switch to Verify mode to check a signature you received against your secret in constant time. To compute plain (non-keyed) digests, use Hash Generator.

Features

  • HMAC with SHA-1, SHA-256, SHA-384, and SHA-512
  • Output in hex, base64, and base64url — all three computed at once
  • Verify mode with constant-time comparison via Web Crypto `subtle.verify`
  • Auto-detect signature format (hex / base64 / base64url) on paste
  • Live recomputation as you type, debounced for large messages
  • Fully client-side — message and secret never leave your browser
  • Drop-in fit for Stripe, GitHub, Slack webhook signature verification
  • One-click copy for every output format

Frequently Asked Questions

What is HMAC and how is it different from a plain SHA hash?
HMAC (Hash-based Message Authentication Code, RFC 2104) combines a cryptographic hash function with a secret key to produce a tag that proves both integrity and authenticity. A plain SHA-256 of `"hello"` is publicly reproducible — anyone can compute it. An HMAC-SHA256 of `"hello"` requires the shared secret, so a recipient who knows the same secret can verify the message has not been tampered with and was sent by someone holding the key. HMAC is what powers webhook signature headers like `X-Hub-Signature-256` (GitHub) and `Stripe-Signature`.
Which algorithm should I pick — SHA-1, SHA-256, SHA-384, or SHA-512?
Use SHA-256 unless your verifier requires otherwise — it is the modern default and what almost every webhook provider expects (Stripe, GitHub, Slack, AWS SigV4). SHA-384 and SHA-512 give larger tags (48/64 bytes) and are useful when you want extra collision resistance margin. SHA-1 is still common in legacy systems (older AWS APIs, GitHub `X-Hub-Signature`) but is generally being phased out — only pick it when explicitly required for compatibility.
Why are three output formats shown (hex, base64, base64url)?
Different webhook providers and protocols pick different encodings for the signature header. GitHub returns hex (`sha256=f7bc...`). AWS uses lowercase hex too. Stripe and many JWT-adjacent flows use base64. URL-safe contexts (JWT signatures, query parameters) use base64url — the same bytes with `+/=` replaced by `-_` and padding stripped. Showing all three lets you copy the format your verifier expects without manual conversion.
Is it safe to paste my webhook secret here?
All HMAC computation runs locally via the browser Web Crypto API — your message and secret never touch our servers, are not logged, and are not transmitted. That said, you should never paste production webhook secrets into any online tool, including this one. Use this tool with throwaway test secrets when iterating, and reserve real production keys for your backend or local CLI. If you suspect a secret has been exposed, rotate it immediately.
How do I verify a Stripe / GitHub webhook signature with this tool?
Both providers send a header containing the HMAC of the raw request body using your endpoint secret. For GitHub: copy the raw request body into Message, paste your webhook secret, pick SHA-256, then in Verify mode paste the value after `sha256=` from `X-Hub-Signature-256` (hex format). For Stripe: extract the `v1=` value from `Stripe-Signature`, sign `<timestamp>.<payload>` joined with a dot, and verify against your endpoint signing secret. The Verify mode here uses constant-time comparison, so it is safe for testing — but production verification should still happen server-side.
Why does Verify mode emphasise "constant-time" comparison?
A naive string comparison (`expected === computed`) returns false on the first differing character — an attacker can measure how long verification takes for a guessed signature and gradually deduce the correct prefix byte by byte. This is a real timing-attack class of vulnerability. `crypto.subtle.verify` in the Web Crypto API is specified to compare in constant time regardless of where the bytes diverge, eliminating that side channel. Server-side equivalents are `crypto.timingSafeEqual` in Node.js and `hmac.compare_digest` in Python.