HMAC Generator
Generate and verify HMAC digests with five algorithms and hex, Base64 or Base64URL output.
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. This tool offers SHA-256, SHA-384, SHA-512, and clearly marked legacy SHA-1 and MD5, computing only the algorithm you select.
How to use it
- 1Choose SHA-256, SHA-384, SHA-512, or a clearly marked legacy SHA-1/MD5 mode.
- 2Enter the message and key as UTF-8 text, then choose hex, Base64 or unpadded Base64URL output.
- 3Copy the digest or paste an expected signature, including common sha256= prefixes, to get an explicit match or mismatch.
Example
- Input
- Message "hello", key "secret", Hex output
- Output
- HMAC-SHA256: 88aab3ede8d3adf94d26ab90d3bafd4a2083070c3bcce9c014ee04a443847c0b
The selected algorithm is computed from UTF-8 text. A key that is really raw bytes written as hex is treated as those hex characters, a common reason a webhook 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 September 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, while older APIs still use SHA-1 or MD5. The selector also includes SHA-384 and SHA-512, with legacy choices clearly marked. The other is what your key really is: a secret written as 64 hex characters may be intended as 32 raw bytes rather than those characters, and a key of the wrong shape gives a plausible digest that verifies nowhere.
The message needs the same care. An HMAC covers an exact byte string, so parsed-and-reprinted JSON is different from the body that was signed. This page signs UTF-8 text typed or pasted into a browser textarea; that control normalises line endings and cannot reproduce arbitrary raw bytes, so it is useful for text fixtures but not a byte-exact substitute for capturing a webhook request body in server code.
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 the selected HMAC from the message and key as UTF-8 text. Choose SHA-256, SHA-384, SHA-512, or a legacy SHA-1/MD5 integration, then render the same digest bytes as hexadecimal, Base64 or unpadded Base64URL. The secret field is masked by default and nothing appears until both inputs exist. Browser textareas normalise CRLF and CR line endings to LF, and there is no raw-byte, file or hex-key decoder, so use a byte-aware verifier when exact request bytes or a binary key matter. The optional verification field accepts a digest alone or a common algorithm prefix such as sha256=, warns when that prefix names a different algorithm, and compares equal-length text without returning early. That browser-side comparison is useful for debugging; production verification should still use the constant-time primitive supplied by its runtime.
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. Production code must hash the exact raw request bytes before JSON parsing or middleware changes them — reordered keys, one space or CRLF becoming LF produces a different digest. A browser textarea cannot preserve every raw byte or CRLF sequence, so compare here only when the provider's fixture is defined as UTF-8 text. Also check whether the scheme prepends a timestamp or canonicalises the method, path and headers, whether the key is raw bytes rather than displayed hex, and whether the expected digest is hex, Base64 or Base64URL.
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
Related tools
File Hash Checker
Get SHA-1, SHA-256 and SHA-512 checksums for a file, then paste the expected value to confirm a match.
Unicode Escape/Unescape
Turn text into \uXXXX sequences and back; by default only non-ASCII goes, or tick Escape everything.
Base32 Encode/Decode
Encode UTF-8 text or hex bytes as RFC 4648 Base32; strictly decode and download exact bytes.
File to Base64
Encode files locally as Base64 or data URLs, compare SHA-256 and download the full text.