What is Keyed-Hash Message Authentication Code (HMAC)?
An HMAC (Keyed-Hash Message Authentication Code) is a specific construct for creating a message authentication code using a cryptographic hash function in combination with a secret cryptographic key. Unlike ordinary hash algorithms, HMAC validates both the integrity (verifying data has not changed) and the authenticity (proving the identity of the sender) of a payload.
Standard hash functions are susceptible to length-extension attacks, where an attacker can append data to a signed message and generate a valid signature without knowing the secret key. HMAC prevents this vulnerability by passing the key and message through double-hashing stages using internal and external padding values (ipad and opad).
HMAC vs. Standard Hashing vs. Symmetric Encryption
It is common to confuse these three security mechanisms. Here is how they compare conceptually:
| Security Concept | Requires Secret Key? | Reversibility | Primary Security Objective |
|---|---|---|---|
| Standard Hashing (e.g. SHA-256) | No | One-Way (Irreversible) | Data Integrity Checks (detect accidental modifications) |
| HMAC (e.g. HMAC-SHA256) | Yes | One-Way (Irreversible) | Integrity & Authenticity (detect tampered payloads and verify origin) |
| Encryption (e.g. AES-256) | Yes | Two-Way (Decryptable) | Data Confidentiality (hide secret message contents from unauthorized views) |
Choosing an HMAC Algorithm
Depending on your system capabilities and integration specs, you can choose from several hash backings:
- HMAC-SHA-256: The default choice for modern web architecture. It offers secure 256-bit signatures and is widely supported by languages and cloud providers (AWS, Azure, Stripe).
- HMAC-SHA-512: Higher security profile, optimized for 64-bit CPU architectures. Highly suitable for data-critical enterprise environments.
- HMAC-SHA-1: Legacy choice. Although SHA-1 alone is weak to collision vulnerabilities, HMAC-SHA-1 remains secure but should be deprecated in new projects.
Common Use Case: Webhook Verification
When Stripe or GitHub sends webhooks to your server, they sign the request body. They compute an HMAC signature using a secret signing key shared only with you. This signature is placed in a custom header (e.g. X-Hub-Signature-256).
When your server receives the HTTP POST request, it computes the HMAC of the raw request payload using the same secret. If your locally generated signature matches the signature in the HTTP header, you know the request is genuine, protecting your system from counterfeit API calls.
Security Best Practices for HMAC
- Keep keys confidential: Never commit secret keys to public version control repositories or print them in diagnostic application logs.
- Use random keys: Generate keys using cryptographically secure random number generators (e.g. at least 32 bytes/256 bits of entropy).
- Time-constant comparisons: When verifying signatures in your server code, always use time-constant comparison functions (like Python's
hmac.compare_digestor Node.js'scrypto.timingSafeEqual) to prevent timing side-channel attacks.