Toolvore

HMAC Generator

Generate HMAC signatures with a secret key (MD5/SHA1/SHA256/SHA512).

This tool runs entirely in your browser. Your data is never uploaded, never stored, and never leaves your device.

An HMAC is message authentication in one value: a digest only someone holding the secret key can reproduce, and this tool computes four of them — MD5, SHA-1, SHA-256 and SHA-512 — as soon as both a message and a key have been entered.

How to use it

  1. 1Type or paste the message into the top box.
  2. 2Enter the secret key underneath, and choose Hex or Base64 output.
  3. 3Copy the digest from whichever of the four algorithm rows you need.

Example

Input
Message "hello", key "secret", Hex output
Output
HMAC-SHA256: 88aab3ede8d3adf94d26ab90d3bafd4a2083070c3bcce9c014ee04a443847c0b

All four algorithms are computed from the same pair, so comparing them costs nothing. Both fields are read as UTF-8 text — a key that is really raw bytes written as hex is treated as those hex characters, which is the usual reason a signature refuses to verify.

What happens to your data

The digests are produced by the crypto-js library bundled into the page and recomputed on each keystroke, so the key is never posted anywhere. It is held in an ordinary React state variable — not localStorage, not the query string — which means closing or reloading the tab is enough to be rid of it, and nothing about it carries over to your next visit.

Last updated August 2026

A webhook arrives with a signature header, your code computes its own digest from the payload, and the two do not match. Or you are building the sending side and the documentation gives one worked example to check yourself against. Either way you want a digest you can trust, from a message and a key you control, so you can tell whether the fault is in the key, the message or your code.

Two things are worth settling before you start. One is which algorithm the other side actually named — HMAC-SHA256 is the usual answer, but older APIs still sign with SHA-1 and a few with MD5, and all four appear here from the same inputs so you are not guessing. The other is what your key really is: a secret written as 64 hex characters is normally meant to be decoded into 32 raw bytes before use, not fed in as those characters, and a key of the wrong shape gives a digest that looks correct and verifies nowhere.

The message needs the same care. An HMAC covers an exact byte string, whitespace and line endings included, so a JSON body that has been parsed and printed again is a different message from the one that was signed.

And an HMAC is not encryption and not a digital signature. It shows that whoever produced the value held the shared secret; because both ends hold that secret, it cannot show which of them did.

How it works

Toolvore computes four digests from a single pair of inputs. The message and the key are taken as typed characters rather than as bytes, and each algorithm runs the standard HMAC construction over them: the key padded out to the hash function's block size, combined with two fixed constants, and the message hashed twice. All four run again on every change, so there is no button to press, though nothing appears until both boxes have something in them. Hex is the default rendering, and the dropdown re-encodes the same digest bytes as Base64 for every row at once. The limits follow from the inputs. There is no way to supply a key as raw bytes, or as hex to be decoded first, and no way to hash a file — only what you can paste. There is no verify field either, so checking your digest against the one you were sent is left to you or to your own code, which should be doing a constant-time comparison anyway.

Common use cases

  • Working out why a webhook signature will not verify
  • Reproducing a payment provider's worked signing example
  • Signing an API request that requires an HMAC header
  • Comparing SHA-1 and SHA-256 output for a vague spec
  • Confirming a shared secret was copied correctly between environments
  • Generating an expected digest for a unit test fixture

Frequently asked questions

What is the difference between an HMAC and a plain SHA-256 hash?

A plain hash takes one input, so anyone can compute it. That catches accidental corruption and nothing else — someone who alters the message can recompute the digest to match. An HMAC mixes a secret key into the same hash function, so only a holder of the key can produce or check the value, which is why it counts as authentication rather than a checksum. The construction also closes a weakness in the obvious approach of sticking a key on the front of a message: SHA-256 and SHA-1 are open to length extension there, and their HMAC forms are not.

Why does my webhook signature never match?

Usually the message, not the maths. Hash the exact raw request body as received, before any JSON parse or framework middleware touches it — reordered keys or one changed space is a different message. Check whether the scheme signs more than the body; many join a timestamp and the payload with a separator, or build a canonical string from the method, path and selected headers. Check the key for whitespace picked up in a copy, or a test secret pointed at live traffic. Then check the encoding, because a hex digest compared against a Base64 one never matches.

Are HMAC-MD5 and HMAC-SHA1 broken?

Not in the way the bare hashes are. MD5 and SHA-1 are unfit for certificates and signatures because collisions can be manufactured to order, and the HMAC construction does not lean on collision resistance in the same way, so neither has fallen in practice — the six-digit codes from an authenticator app are HMAC-SHA1. That is a reason not to panic about an integration you have inherited, rather than a reason to pick either for something new. For anything new, HMAC-SHA256 is the default: supported everywhere and no harder to implement.

Is it safe to paste a real signing secret into a page like this?

There is nowhere for it to go: the computation happens in the tab as you type, with no upload step and no request leaving the page. That covers the tool, but not everything else in the path. A production secret you have pasted has been through your clipboard, which other applications can read and which may sync between your devices, and it can linger in browser form history depending on your settings. The safer habit is to reproduce the problem with a throwaway key and a sample message, and leave the live secret where it already lives.

How long should an HMAC secret key be?

The usual guidance is at least the length of the hash output — 32 random bytes for SHA-256, 64 for SHA-512. Going past the hash's block size buys nothing, because the construction hashes an over-long key down first. What matters far more is that the key is random rather than chosen. A memorable phrase used as a signing secret can be guessed offline at speed: an attacker holding one message and its digest tests candidates locally, without ever contacting you. Generate it from a cryptographic random source, and keep it out of the repository.

Should a digest be sent as hex or Base64?

Whichever the other side expects; they carry the same bytes and neither is more secure. Hex is twice the length of the raw digest and completely unambiguous, which is why most signature headers use it. Base64 is about a third shorter and turns up where size matters or the surrounding format is already Base64. The trap is the variants: standard Base64 uses plus and slash and pads with equals signs, while the URL-safe form substitutes hyphen and underscore and often drops the padding, so a value can be the right digest and still fail a comparison.

Can an HMAC be reversed to recover the message or the key?

No. It rests on a hash function, which is one-way by design, and the output is a fixed size no matter how large the input — a short line and a large file both reduce to 32 bytes under SHA-256, so most of the input is not in there to recover. Guessing is a different matter. Where the set of possible messages is small, someone holding the key can enumerate them and match digests; where the key is weak, someone holding a message and its digest can do the same to the key.

Why should signatures not be compared with a normal equality check?

Ordinary comparison stops at the first differing byte, and how long that took leaks how many leading bytes were right. Someone who can submit guesses and measure the response can then recover a valid signature a byte at a time, turning a hopeless search into a short one. Use the constant-time comparison your language ships — compare_digest in Python, timingSafeEqual in Node, hash_equals in PHP — on the raw bytes or a consistent encoding, since those functions expect equal lengths. Eyeballing two strings while debugging is fine; it is the code running on every request that matters.

Used in these workflows