HMAC Explained: How Hash-Based Message Authentication Works

16 Jun 2026 836 words

HMAC Explained

HMAC (Hash-Based Message Authentication Code) is a mechanism for verifying both the integrity and authenticity of a message using a cryptographic hash function combined with a secret key. Unlike plain hashing, which anyone can compute, HMAC requires knowledge of the secret key to generate or verify the authentication code.

A plain hash like SHA256 tells you that a message has not changed, but it does not prove who created it. An attacker who modifies the message can simply recompute the hash, and the recipient has no way to detect the tampering. HMAC solves this by incorporating a secret key into the hash computation. Only someone with the key can produce a valid HMAC, making it suitable for authenticating messages between parties that share a secret.

How HMAC Works

HMAC uses two passes of the hash function with the secret key. The algorithm is defined in RFC 2104 and works as follows:

  1. The secret key is padded to the hash function's block size
  2. The padded key is XORed with an inner padding constant (ipad = 0x36 repeated)
  3. The message is appended to the inner padded key
  4. The result is hashed
  5. The padded key is XORed with an outer padding constant (opad = 0x5C repeated)
  6. The hash from step 4 is appended to the outer padded key
  7. The result is hashed again
HMAC(K, m) = H((K' ⊕ opad) || H((K' ⊕ ipad) || m))

This double-hashing approach prevents length extension attacks and ensures that even if the underlying hash function has weaknesses, the HMAC construction remains secure.

HMAC vs Plain Hashing

Feature Plain Hash (SHA256) HMAC-SHA256
Key required No Yes
Integrity check Yes Yes
Authentication No Yes
Tamper detection Full recompute Detection without key
Best for File checksums API authentication
Length extension Vulnerable Resistant

Common Use Cases

API authentication — the client signs each request with HMAC using a shared secret. The server recomputes the HMAC and compares it. If they match, the request is authentic.

JWT token signing — although JWT typically uses simpler HMAC or RSA signing, HMAC is a valid algorithm for JWT (HS256, HS384, HS512).

Webhook verification — services like Stripe, GitHub, and Slack sign webhook payloads with HMAC so you can verify they came from the service.

Session tokens — HMAC can generate unforgeable session tokens without storing them in a database.

Code Examples

PHP

$secret = 'my-secret-key';
$message = 'message-to-authenticate';

// Generate HMAC
$hmac = hash_hmac('sha256', $message, $secret);
echo $hmac;

// Verify HMAC
$expected = hash_hmac('sha256', $message, $secret);
if (hash_equals($expected, $providedHmac)) {
    echo 'Authentic';
}

Python

import hmac
import hashlib

secret = b'my-secret-key'
message = b'message-to-authenticate'

# Generate HMAC
hmac_value = hmac.new(secret, message, hashlib.sha256).hexdigest()
print(hmac_value)

# Verify HMAC (constant-time comparison)
expected = hmac.new(secret, message, hashlib.sha256).digest()
received = bytes.fromhex(provided_hmac)
if hmac.compare_digest(expected, received):
    print('Authentic')

JavaScript (Node.js)

const crypto = require('crypto');

const secret = 'my-secret-key';
const message = 'message-to-authenticate';

// Generate HMAC
const hmac = crypto.createHmac('sha256', secret)
    .update(message)
    .digest('hex');
console.log(hmac);

// Verify
const expected = crypto.createHmac('sha256', secret)
    .update(message)
    .digest();

HMAC Algorithms

HMAC can use any cryptographic hash function. The algorithm name typically combines "HMAC" with the hash name.

Algorithm Hash Function Output Size
HMAC-MD5 MD5 128 bits
HMAC-SHA1 SHA-1 160 bits
HMAC-SHA256 SHA-256 256 bits
HMAC-SHA512 SHA-512 512 bits
HMAC-SHA3-256 SHA3-256 256 bits

Use HMAC-SHA256 as the default. HMAC-MD5 and HMAC-SHA1 are deprecated for security-sensitive applications.

Security Considerations

Key size — the key should be at least as long as the hash output. For HMAC-SHA256, use a key of at least 32 bytes (256 bits). Longer keys are hashed down to the block size.

Key secrecy — the security of HMAC depends entirely on the key being secret. Use a key management system or environment variables. Never hardcode keys in source code.

Constant-time comparison — always compare HMAC values using a constant-time comparison function like hash_equals() in PHP or hmac.compare_digest() in Python. A timing attack could otherwise reveal the correct HMAC byte by byte.

Replay attacks — HMAC alone does not prevent replay attacks. Include a timestamp or nonce in the signed message and verify it on the server.

Online Tool

The HMAC Generator on Help2Code computes HMAC values with your choice of algorithm and secret key. Use it to test HMAC implementations or generate test vectors during development.

Conclusion

HMAC provides message authentication using a shared secret and a cryptographic hash function. It is essential for API security, webhook verification, and any scenario where you need to verify both the integrity and authenticity of a message. Use HMAC-SHA256 with a strong secret key and always compare HMAC values using constant-time functions.


About this article

Learn how HMAC (Hash-Based Message Authentication Code) works, how it differs from regular hashing, and how to use it for API authentication.


Related Articles


Related Tools

Help2Code Logo
Menu