HMAC Generator
Generate HMAC-SHA256/384/512 signatures for webhook verification, API auth, and JWT signing
Keep this secret. Anyone with the key can forge signatures.
You’ve just implemented a GitHub webhook handler and need to verify that the incoming requests are genuinely from GitHub. Or you’re debugging why your AWS API signature isn’t matching. Or you’re building an API and need to test that your HMAC-SHA256 signing logic produces the correct output before shipping. This tool computes HMAC signatures entirely in your browser using the Web Crypto API — no data is sent anywhere.
What Is HMAC?
HMAC (Hash-based Message Authentication Code) is a mechanism for verifying two things simultaneously:
- Integrity — the message hasn’t been modified in transit
- Authenticity — the message came from someone who knows the secret key
A plain hash (like SHA-256) only proves integrity. Anyone can compute a SHA-256 hash of a modified message and present a valid-looking checksum. HMAC adds a secret key to the computation, so only parties who know the key can produce or verify the signature.
The HMAC construction is: HMAC(key, message) = H((key ⊕ opad) || H((key ⊕ ipad) || message))
In practice, you don’t implement this yourself — every major language has a standard library HMAC implementation. But understanding the construction helps: the key is mixed into both the inner and outer hash rounds, making it cryptographically impossible to forge a valid HMAC without knowing the key.
Common Real-World Uses
Webhook signature verification: GitHub, Stripe, Slack, Shopify, and most webhook providers sign their payloads with HMAC-SHA256. Your server computes the HMAC of the incoming body using the shared secret, then compares it to the signature in the request headers. If they match, the webhook is genuine.
// Verify a GitHub webhook in Node.js
import { createHmac, timingSafeEqual } from 'crypto';
function verifyGitHubWebhook(payload, signature, secret) {
const expected = 'sha256=' + createHmac('sha256', secret)
.update(payload)
.digest('hex');
return timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}
API request signing: AWS Signature Version 4, many REST APIs, and custom token systems use HMAC to sign requests. The client signs the request with a shared secret; the server verifies before processing.
JWT signatures: The HS256, HS384, and HS512 algorithms in JSON Web Tokens are HMAC-SHA256/384/512. The JWT header and payload are signed with a secret key, and the signature is embedded in the token.
# Manual HMAC-SHA256 in Python (what JWT HS256 does internally)
import hmac, hashlib, base64, json
header = base64.urlsafe_b64encode(json.dumps({"alg":"HS256","typ":"JWT"}).encode()).rstrip(b'=')
payload = base64.urlsafe_b64encode(json.dumps({"sub":"1234567890"}).encode()).rstrip(b'=')
message = header + b'.' + payload
signature = hmac.new(b'your-secret', message, hashlib.sha256).digest()
token = message + b'.' + base64.urlsafe_b64encode(signature).rstrip(b'=')
Cookie and session integrity: Django, Flask, and Rails sign session cookies with HMAC to prevent client-side tampering. The server-side secret key means users can read their session data but can’t modify it without invalidating the signature.
Choosing the Right HMAC Algorithm
| Algorithm | Output Size | Security | Use When |
|---|---|---|---|
| HMAC-SHA-256 | 256 bits (32 bytes) | Strong | Default choice — widely supported, excellent security |
| HMAC-SHA-384 | 384 bits (48 bytes) | Stronger | Extra security margin, niche requirements |
| HMAC-SHA-512 | 512 bits (64 bytes) | Strongest | Maximum security, 64-bit optimized hardware |
| HMAC-SHA-1 | 160 bits (20 bytes) | Legacy | Only when the receiving system requires it |
Recommendation: Use HMAC-SHA256 unless a specific protocol requires otherwise. SHA-1 is cryptographically deprecated — only use HMAC-SHA1 when forced to by an external system that hasn’t upgraded (some legacy APIs still require it).
Hex vs. Base64 Output
This tool outputs two formats:
- Hex (
a3f2b1...) — lowercase hexadecimal. Used by GitHub webhooks (sha256=<hex>), AWS signatures, and most security protocols. Easy to compare character-by-character. - Base64 (
o/Kx...) — compact binary-to-text encoding. Used by JWT, HTTP Authorization headers, and APIs where shorter strings are preferred. Base64 is ~33% shorter than hex for the same data.
The underlying HMAC value is identical — it’s just two representations of the same bytes.
Security Considerations
Always use timingSafeEqual for comparison: Don’t compare HMAC signatures with === or ==. Standard string comparison short-circuits on the first differing character, leaking timing information that can enable side-channel attacks. Use your language’s constant-time comparison:
// Node.js — correct way
import { timingSafeEqual } from 'crypto';
timingSafeEqual(Buffer.from(computed), Buffer.from(received));
// Python — correct way
import hmac
hmac.compare_digest(computed, received)
// Go — correct way
import "crypto/subtle"
subtle.ConstantTimeCompare(computed, received) == 1
Key length matters: HMAC keys shorter than the hash’s block size (64 bytes for SHA-256) are padded. Keys shorter than the output size (32 bytes for SHA-256) reduce security. Use keys of at least 32 bytes for HMAC-SHA256 in production.
HMAC is not encryption: HMAC proves authenticity but does not hide the message content. Anyone who intercepts the message can read it — they just can’t forge a valid signature without the key. If you need confidentiality as well, encrypt the message (AES-GCM) and then sign with HMAC.
Frequently Asked Questions
Is this HMAC generator private?
Yes. All computation happens in your browser using the Web Crypto API (SubtleCrypto.sign). Your message and secret key never leave your device. The tool has no backend, no analytics that capture inputs, and no server-side processing.
What’s the difference between HMAC and a digital signature? HMAC uses a shared secret key — both parties need the same key to sign and verify. Digital signatures (RSA, ECDSA) use asymmetric keys — you sign with a private key and verify with the public key. HMAC is faster and simpler; digital signatures enable public verifiability without sharing secret keys.
Can I use HMAC for password hashing? No. HMAC is fast by design, which is exactly wrong for passwords (see bcrypt, Argon2, scrypt). Use HMAC for message authentication — proving that a message came from a trusted source. Use purpose-built password hashing functions for storing passwords.
Why does GitHub use sha256= prefix in its webhook signatures?
The prefix explicitly identifies the algorithm used, making it impossible to confuse SHA-1 and SHA-256 signatures (GitHub previously used SHA-1 and added SHA-256 support later). When comparing, always verify the prefix matches the algorithm you expect.