---
title: "HMAC generator"
canonical: "https://devtools.nicxon.tech/tools/hmac-generator/"
source: "https://devtools.nicxon.tech/tools/hmac-generator/"
generator: devtools.nicxon.tech
---

# HMAC generator

> Compute a keyed HMAC over a message using SHA-1, SHA-256, SHA-384, or SHA-512.

## What this does

HMAC (Hash-based Message Authentication Code) combines a message and a
 secret key into a fixed-size tag using a hash function. This tool computes
 HMAC-SHA1, HMAC-SHA256, HMAC-SHA384, and HMAC-SHA512 with the browser's
 [SubtleCrypto](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/sign).
 The key can be entered as UTF-8 text, hex, or Base64, and the tag can be
 shown as hex or Base64, so you can reproduce whatever format the system
 you're integrating with uses.

Everything runs locally. Nothing about the key or message is transmitted.

## When you'd use it

- Verifying an incoming webhook signature (Stripe, GitHub, Shopify, Slack, and many others sign their payloads with HMAC-SHA256).
- Signing an outgoing API request that uses a shared-secret scheme (for example AWS SigV4-style or older HMAC auth).
- Generating a tamper-evident token or a signed URL parameter.
- Debugging a signature mismatch by isolating which input — body, key encoding, output encoding — is wrong.

## Worked example

Message `id=42&amount=1000`, key `topsecret` (as
 UTF-8 text), HMAC-SHA256, hex output:

```
641bedff29f7168bc87504b5927bf20598fcf9cd5a4f5022b8317310f0de54a9
```

Switch the output to Base64 and the same 32 bytes become
 `ZBvt/yn3FovIdQS1knvyBZj8+c1aT1AiuDFzEPDeVKk=` — this is exactly
 the choice that trips people up when a provider's header is Base64 but
 their example code prints hex. Change the
 key encoding to "Hex" without changing the key text and the result changes
 completely, because `topsecret` is no longer valid hex and the
 bytes it decodes to are different. Reproduce the provider's documented
 example first; once that matches, your real payload will too.

## Limits and gotchas

- **Sign the exact bytes.** For webhooks, that usually means the raw request body before any JSON parsing or reformatting.
- **Key encoding is not cosmetic.** The same characters interpreted as text, hex, or Base64 are three different keys.
- **Output encoding must match** the value you compare against, including any provider prefix like `sha256=`.
- **Production comparisons must be constant-time.** Don't ship a plain `===` check.
- **HMAC-SHA1** is still cryptographically acceptable for HMAC use, but choose SHA-256 for anything new unless a spec forces SHA-1.
- **This is authentication, not encryption.** The message is not hidden; HMAC only detects tampering and proves origin.

## How to use

- **Choose the hash** — SHA-256 is the usual choice. SHA-1, SHA-384, and SHA-512 are also available for matching an existing implementation.
- **Enter the message and key** — Paste the exact message bytes and the shared secret. Set "Key encoding" if your secret is hex or Base64 rather than text.
- **Pick the output encoding** — Hex or Base64, to match what you are comparing against.
- **Compare** — Compute the HMAC and compare it to the value in the webhook header or API signature you are verifying.

## Frequently asked questions

### What is the difference between a hash and an HMAC?

A plain hash of message can be recomputed by anyone. An HMAC mixes a secret key into the hashing process, so only someone who holds the key can produce or check the value. That is what makes it a message authentication code: it proves both that the message wasn't altered and that it came from someone with the key.

### My HMAC doesn't match the webhook's signature header.

The usual causes: (1) hashing the wrong bytes — many providers sign the exact raw request body, so re-serialising the JSON changes it; (2) wrong key encoding — the secret might be hex or Base64, not text; (3) the provider prefixes the value (for example sha256=) or uses Base64 while you used hex; (4) a timestamp or other field is concatenated with the body before signing. Check the provider's signing recipe precisely.

### Why can't I just use == to compare two HMACs in my own code?

A normal string comparison returns as soon as it finds a differing byte, which leaks timing information an attacker can use to recover the correct value byte by byte. Use a constant-time comparison function (crypto.timingSafeEqual in Node, hmac.compare_digest in Python). Comparing here in the browser for debugging is fine; the production check needs to be constant-time.

### Is the secret I type sent anywhere?

No. The key and message are passed to the browser's SubtleCrypto HMAC implementation locally. Nothing leaves the page. Still, prefer a test key over your real production secret when you can.

---
*Source: [https://devtools.nicxon.tech/tools/hmac-generator/](https://devtools.nicxon.tech/tools/hmac-generator/) — generated by devtools.nicxon.tech.*
