What Is HMAC? Hash-Based Message Authentication

HMAC stands for Hash-based Message Authentication Code. It’s a method for verifying that a message hasn’t been tampered with and that it came from someone who holds a specific secret key. HMAC works by combining a cryptographic hash function (like SHA-256) with a shared secret key to produce a short, fixed-length code that acts as a digital fingerprint for any piece of data.

How HMAC Works

At its core, HMAC takes two inputs: a secret key and the message you want to protect. It runs them through a hash function twice in a specific pattern, producing an output code. If even a single character in the message changes, the resulting code changes completely. And without the secret key, nobody can forge a valid code.

The process uses two rounds of hashing, often called the inner and outer passes. In the first pass, the key is combined with the message and hashed. In the second pass, that result is combined with the key again (in a slightly different way) and hashed once more. This double-pass design is what makes HMAC significantly more secure than simply attaching a hash to a message. A plain hash can be recalculated by anyone, but an HMAC can only be produced or verified by someone who knows the secret key.

The two-pass structure also protects against certain mathematical attacks that can weaken hash functions when used alone. Even if a vulnerability is found in the underlying hash function, HMAC’s layered construction often remains secure.

What HMAC Protects Against

HMAC solves two problems at once: integrity and authentication. Integrity means confirming the message wasn’t altered in transit. Authentication means confirming the sender is who they claim to be, since only someone with the shared secret key could have generated the correct code.

Here’s a simple example. You send a payment instruction to your bank’s server. Alongside the message, you send an HMAC computed using a key only you and the bank know. The bank recalculates the HMAC on its end using the same key and the received message. If the two codes match, the bank knows the message arrived intact and that it genuinely came from you. If an attacker intercepted the message and changed the payment amount, the HMAC would no longer match, and the bank would reject it.

HMAC vs. Digital Signatures

HMAC is a symmetric scheme, meaning both the sender and receiver share the same secret key. Digital signatures, by contrast, are asymmetric: the sender signs with a private key, and anyone can verify using the corresponding public key.

This distinction has practical consequences:

  • Speed: HMAC is much faster to compute than digital signatures because hash functions are lightweight compared to the complex math behind public-key cryptography.
  • Key distribution: HMAC requires both parties to securely share a secret key in advance. Digital signatures only require distributing the public key, which doesn’t need to be kept secret.
  • Non-repudiation: Digital signatures prove to a third party that a specific person signed the message. HMAC can’t do this, because either party holding the shared key could have generated the code.

In practice, HMAC is the go-to choice when two systems that already trust each other need to verify messages quickly. Digital signatures are better when you need to prove authorship to outside parties or when distributing a shared secret isn’t practical.

Where HMAC Is Used in Practice

HMAC is embedded in much of the internet infrastructure you use daily, even if you never see it directly.

Cloud APIs rely heavily on HMAC. Amazon Web Services, for example, uses a signing process called Signature Version 4, where every API request is authenticated using HMAC. When your application talks to AWS, it creates an HMAC from the request details and your secret access key. AWS recalculates the same HMAC on its end. If they match, the request goes through. Your secret key itself never travels over the network.

JSON Web Tokens (JWTs), widely used for login sessions in web applications, commonly use HMAC-SHA256 (labeled HS256) to sign tokens. When a server issues a login token, it generates an HMAC using a secret only the server knows. Each time the token comes back with a request, the server rechecks the HMAC to confirm the token hasn’t been altered. The trade-off is that anyone who discovers the shared secret could forge valid tokens, which is why many authentication providers now default to asymmetric signing (RS256) for JWTs instead.

HMAC also appears in TLS (the protocol behind HTTPS), VPN connections, SSH sessions, and virtually any protocol where two parties need to verify message integrity over a network.

Key Length and Hash Function Choices

HMAC is flexible: it works with any standard cryptographic hash function. The most common pairings today are HMAC-SHA256 and HMAC-SHA384, both based on the SHA-2 family. Older implementations sometimes use HMAC-SHA1 or HMAC-MD5, though these are considered weaker and are being phased out for new systems.

The secret key needs to be long enough to resist brute-force guessing. NIST requires a minimum key length of 112 bits for generating new HMACs. Keys shorter than that are disallowed for creating codes, though they’re still permitted for verifying older, legacy codes. There’s no specified maximum key length, but in practice, keys longer than the hash function’s output size don’t add meaningful security.

The strength of an HMAC depends on both the hash function and the key. A strong hash function paired with a short, guessable key provides no real protection. A 256-bit random key with SHA-256 is considered very strong for current and near-future security needs.

Why Not Just Use a Plain Hash?

A common question is why you can’t just hash the message and send the hash alongside it. The problem is that hash functions are public algorithms. Anyone can compute them. If an attacker intercepts your message, they can change it, recalculate the hash, and send both along as if nothing happened. The receiver has no way to detect the tampering.

HMAC solves this because the secret key is baked into the process. Without the key, an attacker can’t produce a valid code for a modified message. They’d have to guess the key, which, with 112 or more bits of randomness, is computationally infeasible.

Some early systems tried a simpler approach: just prepending or appending the key to the message before hashing. This turns out to be vulnerable to a class of attacks called length-extension attacks, where an attacker can extend the message and compute a valid hash without knowing the key. HMAC’s two-pass design specifically neutralizes this weakness, which is a major reason it became a formal standard through NIST’s FIPS 198 specification.