HMAC Generator
Generate HMAC signatures with various algorithms and keys.
- HMAC (Hash-based Message Authentication Code) combines a key with a hash function
- Provides both authentication and integrity verification
- Commonly used in APIs, webhooks, and JWT signing
- SHA-256 is recommended for most use cases
About HMAC Generator
HMAC (Hash-based Message Authentication Code) is a cryptographic authentication technique that combines a secret key with a hash function to verify both data integrity and authenticity. Unlike simple hashing (MD5, SHA), HMAC uses a secret key, making it impossible for attackers to forge messages without knowing the key. HMAC is the industry standard for API authentication (AWS Signature, OAuth), webhook verification (GitHub, Stripe, Slack), JWT signing, and secure message verification. Our HMAC Generator tool supports all major algorithms (HMAC-SHA256, SHA512, SHA1, MD5) and lets you instantly generate and verify HMACs for API testing, webhook debugging, and security implementations - all processed securely in your browser.
What is HMAC?
HMAC (Hash-based Message Authentication Code), pronounced "H-MAC" or "HMAC", is a cryptographic mechanism for verifying message authenticity and integrity using a secret key and a hash function. Defined in RFC 2104 (1997), HMAC combines a message with a secret key through a specific algorithm, then applies a hash function (like SHA-256) to produce a fixed-length authentication code. The key difference from simple hashing: anyone can compute hash("message"), but only parties with the secret key can compute HMAC(key, "message"). This makes HMAC perfect for scenarios where you need to verify: (1) Message came from legitimate sender (authentication). (2) Message wasn't modified in transit (integrity). (3) Sender possesses the shared secret key (authorization). HMAC is used everywhere: API request signing (AWS, Azure, Google Cloud), webhook signatures (GitHub, Stripe, Shopify), JWT tokens (HS256 algorithm), cookie security (session tokens), password reset tokens, and secure two-way communication. It's faster than public-key cryptography but requires both parties to securely share the secret key beforehand.
How to Use This Tool
- Enter Message: Type or paste the data you want to authenticate
- Choose Algorithm: Select HMAC-SHA256 (recommended), SHA512, SHA1, or MD5
- Input Secret Key: Enter your shared secret key (API key, webhook secret, etc.)
- Generate HMAC: Instantly compute the authentication code
- Output Format: View HMAC in hex (default), Base64, or binary formats
- Verify HMAC: Paste expected HMAC to compare with generated value
- Copy Result: One-click copy for API headers or webhook verification
- Test Webhooks: Verify webhook signatures from GitHub, Stripe, Slack
- API Authentication: Generate Authorization headers for signed requests
- Case Sensitivity: Message and key are case-sensitive - exact match required
- Privacy Guaranteed: All computation happens locally - keys never leave your browser
Common HMAC Use Cases
- API Authentication: AWS Signature v4, Azure Shared Key, Google Cloud signed URLs
- Webhook Verification: GitHub webhooks, Stripe webhooks, Slack events, Shopify webhooks
- JWT Signing: HS256 (HMAC-SHA256) algorithm for JSON Web Tokens
- API Rate Limiting: Generate time-based tokens that expire automatically
- Session Cookies: Sign session IDs to prevent tampering
- Password Reset Tokens: Generate secure, time-limited reset links
- File Integrity: Verify downloaded files haven't been modified
- Message Queues: Authenticate messages in RabbitMQ, Kafka, SQS
- OAuth 1.0: Request signing (OAuth 2.0 uses different methods)
- Database Encryption Keys: Derive encryption keys from master key + context
- IoT Device Authentication: Lightweight authentication for embedded devices
- Two-Factor Authentication: Generate TOTP codes (time-based one-time passwords)
HMAC vs Simple Hash: Key Differences
- Authentication: HMAC proves sender knows secret key, hash does not
- Security: HMAC resists length-extension attacks that break hash(key + message)
- Forgery: Anyone can compute SHA256("data"), only key holders can compute HMAC
- Use Hash For: Checksums, file integrity (MD5/SHA256 of downloads), password storage (with proper hashing like bcrypt)
- Use HMAC For: Message authentication, API signing, webhook verification, proving identity
- Key Requirement: HMAC requires shared secret, hash is keyless
- Collision Attacks: HMAC is immune to hash collision attacks (MD5 collisions don't break HMAC-MD5)
- Performance: Hash is slightly faster (no key mixing), but difference is negligible
- Example: SHA256("hello") is public knowledge, HMAC-SHA256(secret, "hello") proves you know the secret
- Wrong Pattern: hash(key + message) is vulnerable - always use proper HMAC construction
HMAC Algorithm Selection
- HMAC-SHA256: Industry standard, fast, secure. Recommended for all new projects
- HMAC-SHA512: More secure (512-bit output), slower. Use for high-security needs
- HMAC-SHA1: Legacy support (160-bit). Avoid for new projects, but still safe for HMAC (unlike plain SHA1)
- HMAC-MD5: Legacy only (128-bit). Avoid unless required by old APIs. Still secure for HMAC despite MD5 weaknesses
- Key Size: Minimum 128 bits (16 bytes), 256 bits (32 bytes) recommended
- Output Length: SHA256=32 bytes (64 hex chars), SHA512=64 bytes (128 hex), SHA1=20 bytes (40 hex)
- Speed: MD5 โ SHA1 > SHA256 > SHA512 (but differences are small on modern CPUs)
- Industry Standard: AWS uses SHA256, GitHub uses SHA256, Stripe uses SHA256
- Future-Proof: SHA256 will be safe for decades, SHA512 for extra margin
- Never Use: Plain MD5/SHA1 hashes for security, but HMAC-MD5/SHA1 are still okay if required
Webhook Signature Verification
Webhooks are HTTP callbacks that notify your server of events (payment received, PR opened, etc.). To prevent attackers from sending fake webhooks, services sign requests with HMAC. Verification process: (1) Extract signature from webhook headers (X-Hub-Signature-256, Stripe-Signature, etc.). (2) Read raw request body (exact bytes - don't parse JSON first!). (3) Compute HMAC using your webhook secret and raw body. (4) Compare computed HMAC with received signature (use constant-time comparison to prevent timing attacks). (5) Reject request if signatures don't match. Common providers: GitHub sends sha256=<hmac> in X-Hub-Signature-256 header. Stripe sends t=<timestamp>,v1=<hmac> with timestamp to prevent replay attacks. Slack sends signature in X-Slack-Signature with timestamp. Shopify uses X-Shopify-Hmac-SHA256. Critical: always use raw body bytes, not parsed JSON. Verify timestamp to prevent replay attacks (reject if >5 minutes old). Use constant-time comparison to prevent timing side-channels.
AWS Signature Version 4 (Sigv4)
- Purpose: All AWS API requests must be signed with your secret access key
- Algorithm: HMAC-SHA256 with multi-stage key derivation
- Process: (1) Create canonical request (method, URI, headers, payload hash)
- (2) Create string to sign (algorithm, timestamp, scope, hashed canonical request)
- (3) Derive signing key: HMAC(HMAC(HMAC(HMAC(secret, date), region), service), "aws4_request")
- (4) Calculate signature: HMAC(signing_key, string_to_sign)
- (5) Add Authorization header: AWS4-HMAC-SHA256 Credential=..., SignedHeaders=..., Signature=...
- Why Complex: Prevents signature reuse across regions/services, binds signature to request details
- Libraries: Use AWS SDKs (boto3, aws-sdk-js) - don't implement manually unless necessary
- Testing: Use this tool to debug signature mismatches by checking intermediate HMAC values
- Common Errors: Clock skew (signature timestamp too old/future), wrong canonical request format, payload hash mismatch
JWT with HMAC (HS256, HS384, HS512)
JSON Web Tokens can be signed with HMAC (symmetric) or RSA/ECDSA (asymmetric). HMAC algorithms: HS256 (HMAC-SHA256), HS384 (HMAC-SHA384), HS512 (HMAC-SHA512). How it works: JWT header and payload are Base64URL-encoded, concatenated with a dot, then signed with HMAC. Format: base64(header).base64(payload).base64(HMAC(secret, base64(header).base64(payload))). Advantages: Faster than RSA (no public-key crypto), simpler key management, smaller signatures. Disadvantages: Shared secret - both issuer and verifier need the key (can't give to untrusted clients), key rotation is harder. Use HMAC (HS256) when: Auth server and API are same organization, performance is critical, key sharing is acceptable. Use RSA (RS256) when: Distributing public keys to many services, clients need to verify tokens, key rotation flexibility needed. Security: Use 256-bit (32-byte) random secret minimum. Never expose JWT secret in client-side code. Validate exp (expiration) claim. Consider short lifetimes (15 min) with refresh tokens.
HMAC Key Management Best Practices
- Key Length: Minimum 128 bits (16 bytes), 256 bits (32 bytes) recommended for SHA256
- Key Generation: Use cryptographic random generator - crypto.randomBytes(32) in Node.js
- Never Hardcode: Store keys in environment variables, secrets manager (AWS Secrets Manager, HashiCorp Vault)
- Key Rotation: Rotate keys periodically (every 90 days), support multiple keys during transition
- Separate Keys: Different keys for different purposes (webhooks, API auth, JWT signing)
- Access Control: Limit who can read keys - use IAM policies, least privilege principle
- Transmission: Never send keys over unencrypted channels (use HTTPS, TLS)
- Client-Side: NEVER put HMAC secrets in browser JavaScript or mobile apps
- Logging: Never log secret keys, even in debug mode
- Backup: Store encrypted backups of keys, but protect backup encryption key separately
- Revocation: Have process to revoke/rotate compromised keys immediately
- Documentation: Document which keys are used where (but not the key values themselves)
HMAC Security Considerations
- Timing Attacks: Use constant-time comparison for HMAC verification - prevents attackers from guessing signature byte-by-byte
- Replay Attacks: Include timestamp in signed message, reject old signatures (>5 min)
- Key Length: Shorter keys are faster to brute-force - use 256+ bits
- Algorithm Choice: SHA256/SHA512 recommended, avoid MD5/SHA1 for new projects
- Message Encoding: Always specify encoding (UTF-8) - different encodings change HMAC
- Constant-Time Comparison: crypto.timingSafeEqual() in Node, hmac.compare_digest() in Python
- Truncation: Don't truncate HMAC output - use full hash length for security
- Side Channels: Protect against timing, cache, power analysis attacks in sensitive contexts
- HMAC is NOT Encryption: HMAC proves integrity/authenticity but doesn't hide data - use encryption separately
- Length Extension: HMAC construction prevents length-extension attacks that break naive hash(key + message)
- Known Plaintext: HMAC is safe even if attacker knows message - they still can't forge without key
Common HMAC Implementation Mistakes
- Wrong: hash(key + message) - vulnerable to length-extension attacks
- Wrong: Comparing signatures with === or == - timing attacks leak information
- Wrong: Using parsed JSON for webhook verification - byte-level changes break signature
- Wrong: Storing HMAC key in client-side code - anyone can extract and forge
- Wrong: Short keys (< 128 bits) - brute-forceable with modern hardware
- Wrong: Ignoring timestamp validation - allows replay attacks
- Right: Use library HMAC functions (crypto.createHmac, hashlib.hmac)
- Right: Constant-time comparison (timingSafeEqual, compare_digest, subtle.ConstantTimeCompare)
- Right: Verify against raw request bytes before parsing
- Right: Include nonce/timestamp in signed data to prevent replay
- Right: Generate keys with crypto-secure random (not Math.random())
Programming Language HMAC Examples
- JavaScript/Node.js: const crypto = require("crypto"); const hmac = crypto.createHmac("sha256", secret).update(message).digest("hex");
- Python: import hmac, hashlib; signature = hmac.new(key.encode(), message.encode(), hashlib.sha256).hexdigest()
- Java: Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(key, "HmacSHA256")); byte[] hmac = mac.doFinal(message.getBytes());
- C#: using (var hmac = new HMACSHA256(key)) { byte[] hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(message)); }
- PHP: $hmac = hash_hmac("sha256", $message, $secret);
- Go: import "crypto/hmac"; import "crypto/sha256"; h := hmac.New(sha256.New, key); h.Write([]byte(message)); signature := h.Sum(nil)
- Ruby: require "openssl"; hmac = OpenSSL::HMAC.hexdigest("SHA256", key, message)
- Rust: use hmac::{Hmac, Mac}; use sha2::Sha256; let mut mac = Hmac::<Sha256>::new_from_slice(key).unwrap(); mac.update(message); let result = mac.finalize();
- Swift: import CryptoKit; let key = SymmetricKey(data: keyData); let signature = HMAC<SHA256>.authenticationCode(for: messageData, using: key)
- Bash: echo -n "$message" | openssl dgst -sha256 -hmac "$key"
Frequently Asked Questions
What is the difference between HMAC and a regular hash?
A regular hash (like SHA256, MD5) is a one-way function that converts data into a fixed-size string - anyone with the data can compute the same hash. HMAC (Hash-based Message Authentication Code) combines a hash function with a secret key, so only parties who know the secret can generate or verify the HMAC. This means: Hash proves data integrity (file wasn't corrupted), but anyone can compute it. HMAC proves authenticity (message came from someone with the secret key) and integrity. Use hash for checksums and file verification. Use HMAC for API authentication, webhook signatures, and proving message origin. Example: SHA256("hello") is always the same for everyone, but HMAC-SHA256(secret, "hello") is different for each secret key.
Which HMAC algorithm should I use - SHA256, SHA512, SHA1, or MD5?
Use HMAC-SHA256 for almost all use cases - it's the industry standard, fast, and secure. Use HMAC-SHA512 if you need extra security margin or your security policy requires it. Avoid HMAC-MD5 and HMAC-SHA1 for new projects - while they're still secure for HMAC purposes (unlike plain MD5/SHA1 which are broken), there's no reason to use them over SHA256. Legacy systems might require them. Key considerations: SHA256 produces 32-byte (64 hex chars) signatures, SHA512 produces 64-byte (128 hex chars). Speed differences are minimal on modern CPUs. GitHub, Stripe, AWS all use SHA256 as their standard. For maximum compatibility and security, stick with HMAC-SHA256.
How do I verify webhook signatures from GitHub, Stripe, or Slack?
Each service has slight differences but the core process is the same: (1) Extract signature from request headers (GitHub: X-Hub-Signature-256, Stripe: Stripe-Signature, Slack: X-Slack-Signature). (2) Get your webhook secret from the service's dashboard. (3) Compute HMAC using the RAW request body (don't parse JSON first - use exact bytes received). (4) Compare computed HMAC with received signature using constant-time comparison. (5) For Stripe/Slack, also verify timestamp to prevent replay attacks (reject if >5 minutes old). Critical: Use req.body as raw string/buffer, not parsed JSON. Use crypto.timingSafeEqual() for comparison, not ===. GitHub prefixes with "sha256=", Stripe uses "v1=" format. This tool can help debug mismatches by computing expected HMAC values.
Why can't I just use hash(key + message) instead of HMAC?
Hash concatenation (hash(key + message)) is vulnerable to length-extension attacks. With algorithms like SHA256, if you know hash(key + message), you can compute hash(key + message + extra) without knowing the key! Attackers can append data and forge valid signatures. HMAC uses a specific construction (two hash iterations with key padding) that prevents this attack: HMAC(k, m) = hash((k โ opad) || hash((k โ ipad) || m)). This design ensures that knowing HMAC(k, m) doesn't help you compute HMAC(k, m + extra). Always use proper HMAC functions from crypto libraries, never roll your own by concatenating. Even if your hash function isn't vulnerable to length-extension (like SHA-3), HMAC is still the correct, standardized, and well-tested approach.
What key length should I use for HMAC?
Minimum: 128 bits (16 bytes). Recommended: 256 bits (32 bytes) for HMAC-SHA256, 512 bits (64 bytes) for HMAC-SHA512. Longer keys don't improve security once you match the hash output size. For HMAC-SHA256, a 32-byte (256-bit) key is perfect. Generate keys using cryptographically secure random generators: crypto.randomBytes(32) in Node.js, secrets.token_bytes(32) in Python, SecureRandom in Java. Never use weak keys like "password123" or predictable patterns. Never derive HMAC keys from user passwords directly - use PBKDF2/bcrypt to derive a strong key first. Store keys securely in environment variables or secrets managers (AWS Secrets Manager, HashiCorp Vault), never hardcode in source code.
How do I prevent timing attacks when verifying HMAC signatures?
Never use simple string comparison (===, ==, strcmp) to verify HMAC signatures - it leaks timing information that attackers can exploit to guess signatures byte-by-byte. Use constant-time comparison functions that always take the same time regardless of where strings differ. Node.js: crypto.timingSafeEqual(bufferA, bufferB). Python: hmac.compare_digest(a, b). Go: subtle.ConstantTimeCompare(a, b). PHP: hash_equals($a, $b). Java: MessageDigest.isEqual(a, b). These functions compare every byte even after finding a difference, preventing timing side-channels. This is critical for security - timing attacks are practical and have been exploited in real systems. Always use these functions when verifying any cryptographic signature, not just HMAC.
Should I use HMAC (HS256) or RSA (RS256) for JWT tokens?
Use HMAC-SHA256 (HS256) when: Auth server and resource server are same organization/codebase, you control all services that verify tokens, performance is critical (HMAC is faster). Use RSA-SHA256 (RS256) when: Multiple independent services need to verify tokens, you want to distribute public key widely (can't share HMAC secret), easier key rotation (just update public key), client-side verification needed. HMAC pros: Faster, simpler, smaller signatures. HMAC cons: Shared secret means everyone who verifies can also sign tokens, harder key rotation. RSA pros: Verifiers don't need signing key, better for distributed systems. RSA cons: Slower, more complex, larger tokens. Most single-app auth systems use HS256. Microservices and public APIs often use RS256. Never put HS256 secret in client-side code!
Can I use HMAC for password hashing?
No! HMAC is designed for message authentication, not password storage. Use bcrypt, Argon2, scrypt, or PBKDF2 for password hashing. Here's why: Password hashing needs to be intentionally slow (to resist brute-force), HMAC is intentionally fast. Password hashing needs per-user salt, HMAC uses a shared key. HMAC with the same key produces the same output for same input - bad for passwords. Correct password storage: (1) Use bcrypt.hash(password, 10) or Argon2. (2) Each password gets unique random salt (automatic in bcrypt/Argon2). (3) Slow by design - takes 100ms+ per password. (4) Comparing is done with library-specific verify functions (timing-safe). You can use HMAC in authentication flows (like HMAC-based session tokens), but never for the password storage itself.
How do I handle HMAC key rotation without breaking existing signatures?
Support multiple active keys simultaneously during rotation: (1) Add new key while keeping old key active. (2) Update signing to use new key immediately. (3) Update verification to try both keys (new first, then old). (4) Monitor which key is used - when old key usage drops to zero, remove it. Implementation: Store keys in array [currentKey, previousKey, ...]. Sign with keys[0]. Verify by trying each key until one matches. Include key version in signed data or header so you know which key was used. Set rotation schedule (every 90 days). Use secrets manager for centralized key storage. For JWT: Include kid (key ID) in header. For webhooks: Include X-Key-Version header. Never rotate all keys simultaneously - gradual rotation prevents breaking active signatures/sessions. Emergency rotation (compromised key): Immediately sign with new key, accept old key for 5 minutes only, then reject.
What encoding should I use for HMAC - hex, Base64, or binary?
HMAC output is binary (raw bytes). Encoding is for display/transmission: Hexadecimal (hex): Most common for debugging and APIs (e.g., GitHub uses sha256=a1b2c3...). 64 characters for SHA256. Base64: More compact (44 characters for SHA256), common in JWT, HTTP headers. URL-safe Base64 (Base64URL) for URLs. Binary: Most efficient but can't use in text formats (HTTP headers, JSON). Use for binary protocols. Recommendation: Use hex for human readability and debugging, Base64 for space efficiency (HTTP headers, tokens). Most HMAC libraries default to hex or let you choose: Node.js: .digest("hex") or .digest("base64"). Python: .hexdigest() or base64.b64encode(.digest()). Whichever you choose, be consistent - mixing encodings between signing and verification causes mismatches. Document your choice in API specs.