HMAC: Securing messages with a secret key
In short: An HMAC is a check value from message and secret key; it proves that the message comes from someone with the key and was not altered in transit.
In more detail: An ordinary hash (for example SHA-256) can be computed by anyone: an attacker changes the message and recomputes the hash. An HMAC (hash-based message authentication code) includes a secret key; without it nobody can produce a valid value.
In Depth
How it works
HMAC(key, message) = Hash( (key ⊕ opad) ‖ Hash( (key ⊕ ipad) ‖ message ) )
Sender and receiver know the same secret key. The sender attaches HMAC-SHA256(key, message); the receiver computes it themselves and compares. If they match, the message is authentic (from the key holder) and unchanged (integrity). The hash alone encrypts nothing.
Example in Python
import hmac, hashlib
key = b"secret-token"
message = b'{"amount": 100}'
sig = hmac.new(key, message, hashlib.sha256).hexdigest()
# Verify (constant-time comparison!)
ok = hmac.compare_digest(sig, received_sig)Use compare_digest (constant-time comparison), otherwise the time difference in comparison reveals how many characters match (timing attack).
Where it is used
- Webhooks: Stripe, GitHub and others sign requests with HMAC; your server verifies the signature before processing.
- API authentication (for example AWS Signature, signed URLs).
- JWT with HS256 (symmetrically signed).
- Signing session cookies, CSRF tokens, password-reset links.
- TLS, IPsec, SSH use HMAC (or AEAD) for integrity.
- TOTP (one-time codes) is based on HMAC.
Important notes
- Key long and random (at least 32 bytes), keep secret, rotate.
- HMAC ≠ encryption: the content remains readable.
- To protect against replay include a timestamp/nonce and check age.
- Asymmetric signatures (RSA, Ed25519) are used when the verifier should not keep the key secret (anyone may verify, only one may sign).
- No home-made
Hash(key + message): vulnerable to length extension; always use HMAC.
See also: Hashing, SHA-256, Webhooks, JWT, Digital signature