Skip to main content
Skip to main content
SecurityJuly 1, 20266 min read

HMAC Explained: Message Authentication

Understand how HMAC verifies that messages haven't been tampered with and confirms the sender's identity.

Generate secure HMAC signatures with our HMAC Tool. Verify message authenticity without sharing secrets.

The Webhook Incident

Friday evening. Your payment processor sends a webhook notification. A customer paid $1000. Your system processes the order and ships the product.

Monday morning, you discover the webhook was fake. Someone forged the notification. You shipped $1000 worth of product to a scammer.

How do you prevent this? You need to verify the webhook actually came from your payment processor. This is where HMAC comes in.

What is HMAC?

HMAC stands for Hash-based Message Authentication Code. It is a way to verify both the integrity and authenticity of a message.

Unlike a simple hash, HMAC uses a secret key. Only someone with the key can generate a valid HMAC. This proves the message came from someone who knows the secret.

When you receive a message with an HMAC, you calculate your own HMAC using the same secret key. If they match, the message is authentic.

How HMAC Works

HMAC combines a hash function (like SHA-256) with a secret key. The process is:

1. The sender creates an HMAC by hashing the message combined with the secret key

2. The sender sends both the message and the HMAC

3. The receiver calculates their own HMAC using the same key and message

4. If the HMACs match, the message is authentic and has not been tampered with

Real-World Uses of HMAC

HMAC is used extensively in web security:

  • API authentication - Prove API requests came from authorized clients
  • Webhook verification - Verify webhooks came from the expected service
  • Signed URLs - Create URLs that expire or can only be used once
  • Password reset tokens - Secure tokens that prove the request is legitimate
  • Data integrity - Ensure data was not modified in transit

Implementing HMAC

Here is how to implement HMAC in popular languages:

Node.js (crypto)

const crypto = require('crypto'); // Generate HMAC const hmac = crypto.createHmac('sha256', secretKey) .update(message) .digest('hex'); // Verify HMAC const isValid = crypto.timingSafeEqual( Buffer.from(receivedHmac), Buffer.from(calculatedHmac) );

Python (hmac)

import hmac import hashlib # Generate HMAC signature = hmac.new( secret_key.encode(), message.encode(), hashlib.sha256 ).hexdigest() # Verify HMAC (constant-time comparison) is_valid = hmac.compare_digest(received_sig, signature)

Security Considerations

Always use constant-time comparison when verifying HMACs. Regular string comparison stops at the first difference, which can leak information through timing attacks.

Keep your secret key safe. If someone gets the key, they can forge HMACs. Store keys in environment variables or secret management systems, never in code.

Use a strong hash function. SHA-256 is recommended. Avoid MD5 or SHA-1 as they are considered weak.

HMAC in 2026: still the default for webhooks

HMAC-SHA256 remains the default signing scheme for most webhook ecosystems: GitHub, Stripe (v1), Twilio, and many others verify payloads with a shared-secret HMAC plus a timestamp replay window.

Newer providers also offer Ed25519 signatures (for example, GitHub and Stripe v2), which use asymmetric keys so anyone can verify without holding the signing secret. If you control both signer and verifier, HMAC-SHA256 with a 256-bit random key is still a strong, simple choice.

In the browser, the Web Crypto API's subtle.sign supports HMAC, so you can verify webhook-style payloads client-side without a library—always compare signatures in constant time and include a timestamp in the signed message to prevent replay.

FAQ

Q.HMAC vs simple hash?

A.A simple hash proves integrity (data has not changed) but not authenticity (who sent it). HMAC proves both because it requires the secret key.

Q.How long should the secret key be?

A.At least 256 bits (32 bytes) for SHA-256. Generate using a cryptographically secure random number generator.

Q.Which hash algorithm should I use?

A.Use SHA-256. It is widely supported and considered secure. Avoid MD5 and SHA-1 as they have known weaknesses.

Q.How do I prevent webhook replay attacks?

A.Include a timestamp in the signed message and reject messages outside a small window (usually 5 minutes). Providers sign the payload together with a timestamp header; verify both, and store recently seen signatures if you need stricter replay protection.

Q.HMAC or Ed25519 for webhooks in 2026?

A.Both are fine: HMAC-SHA256 with a shared secret is the simplest and most common choice, while Ed25519 is better when the verifier should not hold the signing secret. Providers are increasingly offering Ed25519 (for example, GitHub and Stripe v2), but HMAC remains a supported, secure default.

References

This article is based on industry standards and best practices from authoritative sources:

  • RFC 2104 - HMAC: Keyed-Hashing for Message Authentication: https://www.rfc-editor.org/rfc/rfc2104

Create HMAC signatures

Generate HMAC-SHA256, SHA-1, or MD5 signatures locally — your secret stays on your device.

Conclusion

HMAC turns a shared secret into verifiable authenticity. Create and test signatures locally with the HMAC Generator.