HMAC (Hash-based Message Authentication Code) is one of the most widely used cryptographic primitives in security engineering. You'll find it in API authentication, webhook verification, JWT signing, and โ at the heart of it โ in how TOTP 2FA codes are generated. Understanding HMAC helps you build more secure systems and understand why 2FA works.
In This Guide
What Is HMAC?
HMAC is a cryptographic algorithm that takes two inputs โ a message and a secret key โ and produces a fixed-length output called a MAC (Message Authentication Code). The MAC can be used to verify both that the message hasn't been tampered with (integrity) and that the sender knows the secret key (authenticity).
It was defined in RFC 2104 in 1997 and standardised by NIST. HMAC-SHA256 (using SHA-256 as the underlying hash) is the most widely used variant today.
How HMAC Works
HMAC combines the key and message through the hash function in a specific way to prevent length extension attacks. The formula is: HMAC(K, m) = H((K โ opad) || H((K โ ipad) || m)) where H is the hash function, K is the key, m is the message, and opad/ipad are fixed padding constants.
In practice, you don't implement this yourself โ you use a library function like hmac.new(key, message, hashlib.sha256) in Python, or use our browser-based HMAC generator to compute and verify HMACs without any code.
HMAC vs Plain Hash: The Key Difference
A plain SHA-256 hash of a message always produces the same output โ anyone can compute it without knowing any secret. This is useful for checksums and fingerprints, but useless for authentication because anyone can fake it.
HMAC requires the secret key. Without the key, you cannot compute the correct MAC for any message. This means the recipient of a message with a valid HMAC knows it came from someone who knows the key โ which is the foundation of authentication.
This is why you should never use a plain hash for webhook signature verification or API request signing โ always use HMAC.
Where HMAC Is Used in Practice
Webhook verification: Stripe, GitHub, Shopify, and virtually every major platform send webhooks with an HMAC-SHA256 signature in the headers. Your server computes the HMAC of the payload using a shared secret and compares it to the header โ if they match, the webhook is authentic.
JWT signing: JWTs with algorithm HS256 use HMAC-SHA256. The header and payload are signed with your secret key. The recipient verifies the signature before trusting any claims in the token.
API request signing: AWS Signature Version 4 uses HMAC-SHA256 to sign API requests. The signature proves the request was made by someone with the AWS secret key.
Session tokens: Some session management systems use HMAC to sign session identifiers, preventing session forgery.
HMAC at the Heart of TOTP 2FA
TOTP (Time-based One-Time Password) is built on HMAC. Specifically, it uses HMAC-SHA1 with the secret key and the current time window as inputs. The result is truncated to produce the 6-digit code you see in your authenticator app. This is why TOTP is described in RFC 6238 as "TOTP: Time-Based One-Time Password Algorithm" and why the underlying primitive is called HOTP (HMAC-based One-Time Password).
The HMAC ensures that only someone who knows the secret key can produce valid codes โ and the time component ensures each code is only valid for 30 seconds.
Which HMAC Algorithm Should You Use?
For new systems, use HMAC-SHA256. It produces a 256-bit (32-byte) output, is universally supported, and is considered secure for the foreseeable future. It's the standard for JWTs (HS256), Stripe webhooks, AWS, and most modern APIs.
HMAC-SHA512 is an option for higher security requirements โ it produces a 512-bit output but is otherwise equivalent in use. HMAC-SHA1 should be avoided for new systems, though it's still used internally by TOTP for backwards compatibility with authenticator apps.