# What is HMAC?

> HMAC is a message authentication code built from a hash function and a secret key. It proves who sent a message and that it wasn't changed. Where it's used.

URL: https://crunu.com/learn/hmac
Language: en
Updated: 2026-10-30

HMAC, short for hash-based message authentication code, is a way to compute a short tag from a message and a secret key using a cryptographic hash function such as SHA-256, so that anyone who holds the same key can check that the message came from a key holder and hasn't been changed.

## How it works

RFC 2104 describes HMAC as "a mechanism for message authentication using cryptographic hash functions", usable with any iterative hash "in combination with a secret shared key", and notes that "the cryptographic strength of HMAC depends on the properties of the underlying hash function" ([RFC 2104](https://www.rfc-editor.org/rfc/rfc2104)). NIST's shorter version: "a message authentication code that uses a cryptographic key in conjunction with a hash function" ([NIST glossary](https://csrc.nist.gov/glossary/term/hmac)).

The sender computes `HMAC(key, message)` and sends the tag with the message. The receiver, holding the same key, recomputes it and compares. Without the key, nobody can produce a valid tag for a changed message.

```sh
printf '%s' '{"event":"test"}' | openssl dgst -sha256 -hmac 'example-shared-secret'
```

## HMAC versus a signature

Both prove integrity and origin, but differently:

- **HMAC** uses one shared secret. Anyone who can verify can also create tags. It is fast and simple, and fits two parties that already share a key.
- **A [digital signature](https://crunu.com/learn/digital-signature)** uses a private key to sign and a public key to verify. Verifiers can't forge signatures, so it suits many verifiers and public checks.

## Where you meet it

- **Webhooks.** Services sign webhook bodies so your endpoint can reject forged calls. GitHub, for example, "uses an HMAC hex digest to compute the hash" it sends in the `X-Hub-Signature-256` header ([GitHub Docs](https://docs.github.com/en/webhooks/using-webhooks/validating-webhook-deliveries)).
- **Tokens.** A [JWT](https://crunu.com/learn/jwt) with the algorithm `HS256` uses "HMAC using SHA-256" ([RFC 7518](https://www.rfc-editor.org/rfc/rfc7518)).
- **Storing tokens safely.** A server can store `HMAC(server_key, token)` instead of the token: it can check a presented token without being able to recreate one from its database.

## Common mistakes

- **Comparing tags with ordinary string equality**, which can leak timing information. GitHub's guide says "never use a plain == operator" and suggests a constant-time comparison such as `crypto.timingSafeEqual`.
- **Short or guessable keys.** The key needs real [entropy](https://crunu.com/learn/entropy); 32 random bytes is a common choice.
- **Signing a different form of the message than you verify,** for example re-serialized JSON instead of the raw body.

## HMAC in Crunu

Crunu uses HMAC in two places:

- **Stored tokens.** For session, invitation, enrollment-code and share-link tokens, the server keeps only an HMAC keyed with its `SERVER_KEY`. It can check a token you present but can't recreate one, and someone with a copy of the database alone can't replay tokens, because `SERVER_KEY` isn't in the database. Service tokens are different again: the server stores only their public keys.
- **Alert webhooks.** When Crunu sends an alert to a webhook channel, the body is signed with HMAC-SHA256 using the channel's secret, so an endpoint you run can check that the alert came from your server. Slack, Microsoft Teams and PagerDuty are reached through their incoming webhooks.

These protect tokens and alerts, not your values; values are encrypted on your devices and never reach the server in plain form. What the server holds is listed in [what the server sees](https://crunu.com/docs/security/what-the-server-sees).

## Sources

- [RFC 2104: HMAC](https://www.rfc-editor.org/rfc/rfc2104), checked October 30, 2026.
- [NIST CSRC glossary: HMAC](https://csrc.nist.gov/glossary/term/hmac), checked October 30, 2026.
- [GitHub Docs: Validating webhook deliveries](https://docs.github.com/en/webhooks/using-webhooks/validating-webhook-deliveries), checked October 30, 2026.
- [RFC 7518: JSON Web Algorithms (JWA)](https://www.rfc-editor.org/rfc/rfc7518), checked October 30, 2026.
