🔐 Crypto & Encoding
HMAC Explained: How Webhook Signatures Work
By Justin Le
· 6 min read · Updated June 27, 2026
If you've integrated a webhook from Stripe, GitHub, Slack or similar, you've met
HMAC — usually as a header like X-Hub-Signature-256 you're told to
verify. This guide explains what HMAC actually is and how to check those signatures
correctly.
What is HMAC?
HMAC (Hash-based Message Authentication Code) combines a hash function with a secret key to produce a tag that proves two things at once: the message wasn't altered (integrity) and it was produced by someone who knows the key (authenticity). You'll see it written as HMAC-SHA256, meaning HMAC built on the SHA-256 hash.
Why not just a plain hash?
A plain hash like SHA-256(message) only proves the message hasn't
changed accidentally — anyone can recompute it, so it proves nothing about
who sent it. HMAC mixes the secret key into the computation, so only parties
who share the key can produce or verify a valid tag. That difference is the whole
point: HMAC authenticates the sender, a bare hash does not.
How webhook signing works
When a provider sends you a webhook, they compute
HMAC(your_signing_secret, raw_request_body) and put the result in a
header. Your endpoint repeats the calculation with the same secret and the exact
bytes you received, then compares. If the two match, the request genuinely came from
the provider and wasn't tampered with in transit. If they don't, you reject it.
- The provider signs the raw payload with the shared secret and sends the signature in a header.
- You read the raw request body — before any parsing or re-serialising.
- You compute HMAC over those exact bytes with your copy of the secret.
- You compare your result to the header using a constant-time comparison.
Two mistakes that break verification
- Hashing the re-serialised body. If your framework parses JSON and you then re-stringify it, the bytes can differ (key order, spacing), and the HMAC won't match. Always sign and verify the raw body.
-
Using a normal string comparison. A naive
==can leak timing information that helps an attacker forge a signature. Use a constant-time comparison function from your crypto library.
HMAC and JWTs
You've already met HMAC if you've used JWTs: the signature on an HS256 token is literally an HMAC-SHA256 over the token's header and payload. Same primitive, different application. See our guide to JWTs for that side of the story.
Choosing the algorithm and key
Use SHA-256 or stronger; HMAC-SHA1 is still cryptographically acceptable for compatibility but SHA-256 is the modern default. The security rests on the key, so use a long, random secret — not a human-chosen word. Match the output format (hex or Base64) to whatever the provider specifies.
Try it
Compute HMACs in hex or Base64 with different algorithms and keys using our HMAC generator — paste a sample body and secret to reproduce exactly what a provider would send. To build the JWT side, use the JWT generator.
Frequently asked questions
What is the difference between a hash and an HMAC?
A plain hash only proves integrity and can be recomputed by anyone. HMAC mixes in a secret key, so it also proves authenticity — only someone with the key can produce or verify it.
How do I verify a webhook signature?
Compute an HMAC over the exact raw request body with your signing secret and the provider's algorithm (usually SHA-256), then compare it to the signature header using a constant-time comparison.
Why does my webhook signature check fail?
The most common cause is hashing a re-serialised body instead of the raw bytes the provider signed. Parsing and re-stringifying JSON can change spacing or key order, breaking the match.
Try the related tools
- HMAC Generator (SHA-1, SHA-256, SHA-512) Compute an HMAC from a message and secret key using SHA-1/256/384/512, as hex or Base64.
- JWT Generator (HS256) Create and sign a JSON Web Token (HS256/384/512) from a payload and secret.
- Hash Generator (MD5, SHA-1, SHA-256, SHA-512) Compute MD5, SHA-1, SHA-256, SHA-384 and SHA-512 digests from any text.
Related guides
- What Is a JWT and How Does It Work? How JSON Web Tokens really work — the header, payload and signature, what signing proves, and the security mistakes that bite teams.
- What Is Base64 Encoding? (And Why It's Not Encryption) Base64 turns binary data into safe text — but it is not encryption. Here's how it works, why it grows your data by a third, and when to reach for it.
- MD5 vs SHA-1 vs SHA-256: Which Hash Should You Use? MD5 and SHA-1 are broken — but not for the reason most people think. Here's what each hash is for, why collisions matter, and which to actually use.