If you've ever worked with payment APIs, webhooks, cloud services, or third-party integrations, you've probably seen something that looks like:
```text id="3n8x5k"
X-Signature: 9d7f3a...
At first glance, it just looks like another random hash.
But sometimes that signature is actually an **HMAC**.
HMAC is one of those security concepts that sounds more complicated than it really is. Once you understand what it's doing, you'll start noticing it everywhere in API authentication and request verification.
## What is HMAC?
HMAC stands for **Hash-based Message Authentication Code**.
The basic idea is pretty straightforward.
You have:
1. A message
2. A secret key
3. A cryptographic hash function
The HMAC algorithm combines the message and secret key to produce a signature.
Conceptually:
```text id="1x6u8e"
HMAC(secret_key, message) → signature
For example, an API might have a shared secret:
```text id="g4s6hf"
my-super-secret-key
and a request payload:
```json
{
"amount": 100,
"currency": "USD"
}
The sender generates an HMAC signature using the secret key.
The receiving server already knows the same secret key, so it can calculate the signature again.
If the signatures match, the server has a reasonable way to verify that the message was generated by someone who knows the secret.
That's the important part.
Hashing isn't the same as HMAC
This is where things can get confusing.
A normal cryptographic hash might look like:
```text id="xk4h6z"
SHA-256(message)
There's no secret involved.
Anyone with the message can calculate the same hash.
HMAC is different:
```text id="0p6t5c"
HMAC-SHA256(secret, message)
The secret key is part of the authentication process.
So if someone modifies the message but doesn't know the secret key, they shouldn't be able to generate a valid HMAC for the modified message.
This is why HMAC is useful for verifying the integrity and authenticity of data.
A common API example
Imagine you're receiving a webhook from a payment provider.
The provider sends:
{
"event": "payment.completed",
"id": "12345",
"amount": 500
}
Along with something like:
```text id="p0q4a6"
X-Signature: abc123...
Your server receives the request and uses your shared secret to calculate its own HMAC signature.
Conceptually:
```text id="o1h2ly"
expected = HMAC-SHA256(secret, request_body)
Then it compares the generated signature with the signature sent by the provider.
If they match, the request passes the signature check.
If they don't, something is wrong.
Maybe the request was modified.
Maybe the wrong secret was used.
Maybe the payload was interpreted differently.
Or maybe someone is trying to send a fake webhook.
The exact bytes matter
This is one of those details that can cause an annoying debugging session.
HMAC operates on the actual message bytes.
That means these two JSON strings may represent the same data to you:
{"amount":100,"currency":"USD"}
and:
{
"amount": 100,
"currency": "USD"
}
But their raw byte representations are different.
If one side calculates the HMAC from one representation and the other side calculates it from another, the signatures won't match.
That's why webhook implementations often tell you to calculate the signature against the raw request body, rather than parsing the JSON first and then serializing it again.
Tiny implementation detail.
Huge debugging headache.
Which hash algorithms can HMAC use?
HMAC isn't itself a hash function.
It's a construction that can be used with different hash functions.
The tool I built supports:
- HMAC-SHA-256
- HMAC-SHA-384
- HMAC-SHA-512
- HMAC-SHA-1
SHA-256 is a common choice for modern applications.
SHA-384 and SHA-512 are also available when required by a particular protocol or integration.
SHA-1 is included mainly for compatibility with older systems.
For new security-sensitive designs, you generally shouldn't choose SHA-1 simply because it's available.
If an existing API explicitly requires it, though, you'll occasionally need to generate an HMAC-SHA-1 signature.
Legacy software has a remarkable talent for refusing to retire.
I built an HMAC generator
I made a small HMAC Keyed-Hash Signature Generator for quickly generating and testing HMAC signatures.
👉 https://omnikite.vercel.app/tools/security/hmac-generator
You can enter your message, provide the secret key, select the hashing algorithm, and generate the resulting HMAC signature.
It's useful when you're:
- Debugging an API integration
- Testing webhook signatures
- Checking an authentication implementation
- Comparing signatures between two systems
- Learning how HMAC works
- Troubleshooting a request-signing issue
Sometimes you don't need an entire cryptography library setup just to answer:
"Why the hell don't these two signatures match?"
A small tool is enough.
Everything happens in the browser
Since HMAC involves secret keys, I didn't want the generator to require sending your input to a backend.
The tool runs entirely on the client.
Your message and key stay in the browser, with zero data egress.
Of course, you should still use common sense.
Don't paste production credentials into random tools just because the page says "private."
For real secrets, use tooling and environments you trust.
HMAC doesn't encrypt anything
Another important distinction:
HMAC does not encrypt your message.
If you calculate:
```text id="5gk7p2"
HMAC-SHA256(secret, "hello")
the result doesn't allow someone to decrypt `"hello"`.
HMAC is primarily about **authentication and integrity**, not confidentiality.
If you need to keep the message secret, you need encryption.
If you need to verify that the message hasn't been tampered with and that the sender knows the shared secret, HMAC can be a good fit.
Different problem.
Different tool.
## HMAC in the real world
You'll find HMAC-style request signing in many places.
For example:
**Webhooks**
A provider signs the payload and your server verifies the signature.
**API authentication**
A client can sign requests using a shared secret.
**Cloud APIs**
Some cloud services use request-signing mechanisms built around HMAC.
**File or message integrity**
A system can use HMAC to detect unauthorized modification when the communicating parties share a secret.
The exact protocol varies, but the fundamental idea remains the same:
> Both sides know the secret. Only someone with that secret should be able to produce a valid signature.
## Try it yourself
If you're currently debugging an API signature or simply want to understand how HMAC works, you can try the generator here:
👉 **HMAC Keyed-Hash Signature Generator**
https://omnikite.vercel.app/tools/security/hmac-generator
It supports SHA-256, SHA-384, SHA-512, and SHA-1 HMAC signatures and runs entirely client-side.
Sometimes understanding cryptography doesn't require reading a 400-page specification.
Sometimes you just need to enter a message, enter a secret, press a button, and finally figure out why the API keeps saying:
**"Invalid signature."**
Top comments (0)