HMAC is a cryptographic construction combining a hash function with a secret key to verify data integrity and message authenticity per RFC 2104.
A Hash-based Message Authentication Code (HMAC) is a cryptographic algorithm defined in RFC 2104 that combines a cryptographic hash function (such as SHA-256 or SHA-512) with a shared secret key. It provides two vital security guarantees simultaneously: data integrity (verifying that the message has not been altered or tampered with in transit) and data authenticity (proving that the sender possesses the shared secret key).
You can generate and verify cryptographic hashes and HMAC digests using our client-side Hash Generator tool.
| Specification | HMAC-SHA256 | HMAC-SHA512 | HMAC-MD5 (Legacy) |
|---|---|---|---|
| Standard Reference | RFC 2104 / FIPS PUB 198-1 | RFC 2104 / FIPS PUB 198-1 | RFC 2104 (Deprecated) |
| Underlying Hash Function | SHA-256 | SHA-512 | MD5 |
| Output Digest Size | 256 bits (32 bytes) | 512 bits (64 bytes) | 128 bits (16 bytes) |
| Hash Block Size ($B$) | 64 bytes (512 bits) | 128 bytes (1024 bits) | 64 bytes (512 bits) |
| Recommended Key Length | $\ge$ 32 bytes (256 bits) | $\ge$ 64 bytes (512 bits) | Obsolete / Insecure |
| Cryptographic Model | Symmetric (Shared Secret) | Symmetric (Shared Secret) | Symmetric (Shared Secret) |
| Resistance to Length Extension | Immune | Immune | Immune (but MD5 is broken) |
A naive attempt to create a keyed hash might simply concatenate the secret key with the message: Hash(Secret + Message). However, Merkle–Damgård hash functions (including MD5, SHA-1, and SHA-256) are vulnerable to length extension attacks, where an attacker who observes Hash(Secret + Message) can append arbitrary data to the payload and compute a valid signature without ever knowing the secret key!
HMAC completely immunizes against length extension attacks through a two-pass nested hashing construction:
$$\text{HMAC}(K, m) = H\Big((K' \oplus \text{opad}) \mathbin{\Vert} H\big((K' \oplus \text{ipad}) \mathbin{\Vert} m\big)\Big)$$
Where:
0x36 repeated $B$ times.0x5C repeated $B$ times.Step 1: Key (K') XOR ipad ───────────┐
▼
Step 2: [ (K' ⊕ ipad) + Message ] ──► Inner Hash ──┐
▼
Step 3: Key (K') XOR opad ──────────► [ (K' ⊕ opad) + Inner Hash ] ──► Outer Hash (Final HMAC)
Stripe-Signature). Your server recalculates the HMAC to guarantee the webhook originated from Stripe and was not intercepted or forged.HS256 signing algorithm in the JWT specification is HMAC with SHA-256, verifying the claims token across distributed microservices.import crypto from 'node:crypto';
// 1. Generate an HMAC-SHA256 signature
export function signPayload(message, secretKey) {
return crypto
.createHmac('sha256', secretKey)
.update(message, 'utf8')
.digest('hex');
}
// 2. Safely verify an incoming signature (timing-safe)
export function verifySignature(message, incomingSignature, secretKey) {
const expectedSignature = signPayload(message, secretKey);
const expectedBuffer = Buffer.from(expectedSignature, 'hex');
const incomingBuffer = Buffer.from(incomingSignature, 'hex');
// Prevent length-based timing leaks
if (expectedBuffer.length !== incomingBuffer.length) {
return false;
}
// Cryptographically safe constant-time comparison
return crypto.timingSafeEqual(expectedBuffer, incomingBuffer);
}
import hmac
import hashlib
def generate_hmac(message: str, secret_key: str) -> str:
key_bytes = secret_key.encode('utf-8')
msg_bytes = message.encode('utf-8')
return hmac.new(key_bytes, msg_bytes, hashlib.sha256).hexdigest()
def verify_hmac(message: str, signature: str, secret_key: str) -> bool:
expected = generate_hmac(message, secret_key)
# hmac.compare_digest prevents timing attacks
return hmac.compare_digest(expected, signature)
=== in JavaScript or == in Python) terminate execution at the first non-matching character. Attackers can measure response latencies down to nanoseconds to deduce valid signature bytes one by one (a timing attack). Always use crypto.timingSafeEqual() in Node.js or hmac.compare_digest() in Python.A standard hash like SHA-256 takes only data as input and produces a fixed fingerprint; anyone can compute the same hash. An HMAC requires both data and a secret cryptographic key. Without knowing the secret key, an attacker cannot generate a valid HMAC or forge messages.
hash(secret + message)?Because Merkle–Damgård hash functions (like MD5 and SHA-256) process data in sequential blocks, an attacker who intercepts hash(secret + message) can leverage length extension attacks to append new data to the payload and compute the resulting hash without knowing the secret. HMAC was specifically designed to prevent this flaw.
No. HMAC relies on one-way cryptographic hash functions. It is mathematically impossible to reverse or decrypt an HMAC to recover either the message or the secret key. If you need two-way reversible encryption, use a symmetric cipher like AES.
HMAC-SHA256 is the industry standard for webhooks, REST APIs, and microservices. For high-security environments, HMAC-SHA512 is recommended. Avoid legacy HMAC-MD5 or HMAC-SHA1, as their underlying hash algorithms are cryptographically compromised.
Free, browser-based utilities to test, generate, and inspect Hash-based Message Authentication Code (HMAC) payloads directly.