HMAC Generator
Compute HMAC-SHA-256 and family with the key and message decoded exactly as your API sees them — entirely on this device.
Text inputs become UTF-8 bytes — use Hex or Base64 for binary keys and messages.
Result
Press ? for shortcuts · Never stored — the key and message stay on this device and are gone when you leave.
This page loads no third-party code — no ads, no trackers, no analytics. Verify in your Network tab.
Do it offline:$ printf '%s' 'hello' | openssl dgst -sha256 -hmac 'secret'
How to use it
- Enter the secret key and choose its reading — Text (UTF-8), hex or Base64. The byte chip catches the classic slip: a hex secret in text mode reads as twice the bytes you meant.
- Paste the message and pick its encoding the same way. For webhooks that means the raw request body, exactly as delivered.
- Select the digest. SHA-256 is the default; SHA-1, SHA-384, SHA-512 and MD5 exist to match what the other side computes.
- Copy the row your comparison needs — hex with a case toggle, Base64, or the full GitHub-style header line.
An HMAC binds a message to a secret key; webhook providers sign each delivery with one, and receivers recompute it to prove authenticity. Paste the key and the message — each with its own text, hex or Base64 reading — pick a digest, and the code lands as lowercase hex, Base64, and a sha256=… header line ready to compare. The key stays on this device: never stored, never in a share link.
Examples
hello88aab3ede8d3adf94d26ab90d3bafd4a2083070c3bcce9c014ee04a443847c0bKey secret, both panes text: six key bytes, five message bytes, this exact answer from any correct HMAC-SHA-256. The Base64 row shows the same 32 MAC bytes: iKqz7ejTrflNJquQ07r9SiCDBww7zOnAFO4EpEOEfAs=.
{"action":"opened"}sha256=eae4ae19919a1185124d078490e2fa74c69ea53ac7b9264a5309f76ad710eb0bWhat an X-Hub-Signature-256 check expects — digest name, equals sign, lowercase hex — with the stand-in key octocat-webhook. Sign the raw delivery bytes: a re-serialized body can shift whitespace and fail the comparison with both secrets correct.
73656372657488aab3ede8d3adf94d26ab90d3bafd4a2083070c3bcce9c014ee04a443847c0bRead as hex, these twelve characters decode to the six bytes of secret — with message hello the MAC repeats example 1 exactly. In text mode they count as twelve ASCII bytes and produce a different code.
hello
171b5670f7b4037fb90bef773b022130e48100fdd40ea023730097da9a68f4ffThe message is hello plus a line feed; no output digit survives it. echo pipes that byte in, printf '%s' does not, and a chip warns when a decoded message ends this way.
Every example on this page is executed against the same engine that powers the tool, on every build.
Gotchas worth knowing
An empty key computes, with a warning
HMAC is defined for a zero-length key — the result starts 4352b26e, and OpenSSL agrees. A blank pane usually means the secret never arrived, so a chip states: empty keys are valid HMAC inputs but almost never what your API expects.
Long keys are hashed down first
Past the block size — 64 bytes through SHA-256, 128 for SHA-384 and SHA-512 — RFC 2104 substitutes the key's own digest first. A chip records it: a very long key is often a Base64 blob that wanted decoding instead.
Binary keys travel as hex or Base64
A secret issued as 736563726574 or c2VjcmV0 is bytes wearing a spelling. Decode it with the key pane's selector — both spellings land on example 1's MAC — instead of hashing the spelling itself.
Unicode means UTF-8 bytes, unnormalized
café is five key bytes with a precomposed é and six with a combining accent, and the two MACs differ. Nothing is normalized on the way in — when input leaves ASCII, agree on bytes.
MD5 and SHA-1 reproduce legacy signatures
Choosing MD5 loads a small WebAssembly module on demand and pins a warning chip — public MD5 collisions date to 2004. Old digests stay because running systems still emit them; GitHub's legacy X-Hub-Signature header is HMAC-SHA-1.
The caps refuse; they never truncate
Keys stop at 64 KB, messages at 8 MB; crossing either line is a stated refusal, because a MAC over part of an input matches nothing. Bigger payloads belong in the openssl line below.
Common errors
`s` at position 1 is not a hex digit- The key pane was set to hex while a plain-text secret sat in it, so the first character fails the 0–9 a–f alphabet. Flip the key encoding to Text (UTF-8), or clean the value to hex pairs if it genuinely is one.
Invalid Base64: character '{' at position 1- A raw JSON body was pasted while the message encoding said Base64. Most webhook payloads read as text, exactly as they arrived; keep Base64 for content that is genuinely encoded bytes.
Message is larger than the 8 MB limit for this tool.- The cap keeps the tab responsive and rules out silent truncation. Sign payloads past 8 MB where they live — pipe the file through the openssl command below with your real key and compare hex.
FAQ
Why doesn't my HMAC match the webhook's signature header?
Check three suspects. The body: providers sign the raw delivery bytes, so pretty-printing or a changed final newline breaks the match — example 4 is the one-byte version. The key: a hex or Base64 secret decoded as text yields the wrong bytes, which the byte chip exposes. The format: compare the whole lowercase sha256=… row, not a truncated or uppercased copy.
Is it safe to paste a real secret key here?
Verify rather than trust: open your browser's Network tab and watch this page make no third-party request while you type — nowhere for a key to go. The key pane is never persisted, and a share link cannot carry it because the link format has no key field to fill. Throwaway secrets remain a good habit even so.
Which digest should I pick?
SHA-256, unless the system you must match dictates otherwise — it is the default here and what current webhook documentation specifies. SHA-384 and SHA-512 appear in higher-assurance stacks; SHA-1 and MD5 exist strictly to reproduce what older integrations emit.
Keyboard shortcuts
- ⌘/Ctrl + Enter
- Run the computation again now.
- ⌘/Ctrl + S
- Download the hex MAC as a .txt file instead of saving the page.
- ⌘/Ctrl + C
- Copy the hex MAC when nothing is selected.
- ⌘/Ctrl + Shift + C
- Copy the hex MAC despite any selection.
- t
- Step to the next theme.
- ? or ⌘/Ctrl + /
- Open the shortcut overlay.
- Esc
- Close the topmost dialog; the input panes are never cleared.