🔑 HMAC Generator

Generate and verify HMAC-SHA-256, SHA-512, SHA-384 & SHA-1 signatures using the Web Crypto API — 100% client-side.

HMAC‑SHA‑256
256 bit · 64 hex
HMAC‑SHA‑512
512 bit · 128 hex
HMAC‑SHA‑384
384 bit · 96 hex
HMAC‑SHA‑1
160 bit · 40 hex
Quick Presets
✏️
Custom
Blank slate — enter your own message and key
🔗
Webhook
Verify GitHub / Stripe / Shopify webhook payloads
🌐
API Auth
Sign API requests with timestamp + method + path
🎫
JWT Header
Produce the HMAC signature portion of a JWT
🍪
Cookie Sign
Sign session cookies for tamper detection
📄
File MAC
Authenticate file content with a shared secret
Secret Key
0 chars  · 0 bits entropy  ·
Key encoding
Random key length:
output as Hex
Message
Message / Payload 0 chars · 0 bytes
Message encoding
HMAC Signature
Enter a key and message, then click Generate HMAC
All Algorithms
Click "Generate All" to compute all four HMAC variants simultaneously.

HMAC — How It Works & When to Use It

What is HMAC?

HMAC (Hash-based Message Authentication Code) combines a cryptographic hash function with a secret key: HMAC(K, m) = H((K⊕opad) ∥ H((K⊕ipad) ∥ m)) . Unlike a plain hash, it provides both integrity and authenticity — only someone with the key can produce or verify the signature.

Webhook Verification

GitHub, Stripe, Shopify and most major APIs use HMAC-SHA-256 to sign webhook payloads. The platform signs the raw request body with a shared secret and sends the result in a header like X-Hub-Signature-256 . Your server recomputes the HMAC and compares.

JWT Signing

JSON Web Tokens use HMAC-SHA-256 (HS256) to sign the header + payload. The signature is computed over base64url(header) + "." + base64url(payload) with a secret key, then appended as the third JWT segment. This tool lets you reproduce that signature manually.

Constant-Time Verify

This tool uses crypto.subtle.verify() for signature verification, which performs constant-time comparison internally — preventing timing side-channel attacks that could leak whether signatures partially match. Never use string equality ( === ) to compare HMACs in production.

HMAC in the Wild — Where You're Already Relying on It
HMAC shows up in nearly every API you've integrated with. Recognising it helps you implement your own correctly.
Platform / ProtocolHMAC variantWhat it signsHeader / field name
GitHub WebhooksHMAC-SHA256Raw request bodyX-Hub-Signature-256: sha256=<hex>
Stripe WebhooksHMAC-SHA256Timestamp + raw body (replay protection built in)Stripe-Signature: t=<ts>,v1=<hex>
Shopify WebhooksHMAC-SHA256Raw request bodyX-Shopify-Hmac-Sha256: <base64>
AWS Signature V4HMAC-SHA256 (chained)Date → region → service → request — four nested HMACsAuthorization: AWS4-HMAC-SHA256 Credential=...
JWT (HS256)HMAC-SHA256Base64URL(header) + "." + Base64URL(payload).<signature> — the third dot-segment of the token
TOTP / HOTP (2FA)HMAC-SHA1 (HOTP) or HMAC-SHA256/SHA512 (TOTP)Counter or timestampThe 6-digit code is derived from the last 4 bytes of the HMAC output
OAuth 1.0aHMAC-SHA1Normalized request stringoauth_signature parameter
How to Implement Webhook Signature Verification Correctly
Most webhook libraries have done this right. If you're writing your own, these are the places where implementations go wrong.
Use the raw body, not the parsed object

JSON parsers normalise whitespace, reorder keys, and drop unknown fields. If you sign the parsed-then-re-serialised body instead of the original bytes, your HMAC will not match what the sender computed. Buffer the raw request body before it hits any JSON parser. In Express this means express.raw() on the webhook route, not express.json().

Use constant-time string comparison

A regular string comparison (===, ==) exits early on the first differing byte. An attacker can measure response latency to learn how many characters of their crafted signature match the expected value. Use crypto.timingSafeEqual() in Node, hmac.compare_digest() in Python, hash_equals() in PHP. This is not optional.

Verify the timestamp to prevent replay attacks

An HMAC doesn't expire. If you verify only the signature, an attacker who intercepts a valid signed request can replay it minutes or days later. Stripe's webhook format includes a timestamp in the signed payload and rejects requests older than 5 minutes. Build the same pattern into your own webhook handlers.

Key length: at least as long as the hash output

The HMAC spec (RFC 2104) says keys shorter than the hash output length provide reduced security. For HMAC-SHA256, use a key that's at least 32 bytes / 256 bits. In practice, use 32 bytes of cryptographically random data. A human-readable string used as a key is likely too short and has low entropy.

HMAC ≠ encryption — it's authentication

HMAC proves who signed a message and that it hasn't been modified. It does not hide the message content. If your payload contains sensitive data, you still need encryption separately. HMAC + plaintext != confidentiality. For confidentiality + integrity together, use AES-GCM or ChaCha20-Poly1305, which include authentication built in.

HMAC-SHA256 vs JWT asymmetric signing

HMAC requires both parties to share the same secret key. Anyone who can verify an HMAC-signed JWT can also forge one. If you're issuing JWTs to external parties, use RS256 or ES256 (asymmetric) instead — your private key signs, and the public key verifies without being able to forge. HMAC-signed JWTs only make sense for internal, single-service scenarios.

HMAC Algorithm Comparison
Choosing between HMAC-SHA256 and HMAC-SHA512 for new work.
PropertyHMAC-SHA256HMAC-SHA512HMAC-SHA1
Output size32 bytes / 64 hex chars64 bytes / 128 hex chars20 bytes / 40 hex chars
Security level128-bit (collision), 256-bit (preimage)256-bit (collision), 512-bit (preimage)Deprecated for new use
Speed on 64-bit CPUGoodOften faster (larger block = fewer rounds per byte)Fastest
Ecosystem supportUniversal — every library, every platformUniversalUniversal (legacy)
Use for new work?Yes — default choiceYes — prefer for high-value signingNo — only for TOTP/HOTP backward compat
Related Tools
Other free security and hashing tools on IndexCraft.
Common Questions
HMAC is symmetric — both the signer and verifier need the same secret key. This means the verifier could also forge signatures. RSA and ECDSA signatures are asymmetric — a private key signs, and a separate public key verifies. The verifier cannot forge. HMAC is faster and simpler; asymmetric signatures are better when the verifier is untrusted or when you need non-repudiation (proof that only the key holder signed it).
RFC 2104 defines HMAC as H((K XOR opad) || H((K XOR ipad) || message)). The double-pass construction closes off length-extension attacks that affect raw SHA-256 and MD5. With a single-pass construction H(key || message), an attacker who knows the hash but not the key can compute a valid hash for any extension of the message. The outer hash with a different key derivation breaks this.
You technically can, but you shouldn't. Using one key to sign both webhook payloads and API tokens means that a leak of one allows forgery of both. Key separation is a foundational security principle. The standard pattern is to derive purpose-specific keys from a single master key using HKDF: HKDF(masterKey, salt, "webhook-signing") produces a deterministic but purpose-specific subkey. Each derived key is independent.
Treat HMAC secret keys like database passwords — never hardcode in source, never commit to git. Options in order of preference: a secrets manager (AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager), environment variables injected at runtime, encrypted configuration files with the encryption key stored separately. Rotate keys regularly and have a plan for what happens when a key is leaked — can you invalidate all signatures issued with it?