HMAC Generator
Generate keyed HMAC signatures — MD5, SHA-1, SHA-256, SHA-384 and SHA-512 — from a message and a secret key, or verify one you were given. Hex or Base64 output. Runs entirely in your browser.
How to Generate or Verify an HMAC Signature
Features
A Hash Proves Integrity. HMAC Proves Who Sent It.
A plain hash answers one question: has this data changed since the hash was computed? Anyone can recompute a SHA-256 hash of a message — the algorithm is public, and no secret is involved anywhere in the process. That's exactly why a bare hash can't prove who sent a message: an attacker intercepting both the message and its hash can simply alter the message, recompute the same public hash function, and hand over a hash that matches their tampered version. Nothing about a plain digest distinguishes a legitimate sender from anyone else who knows the algorithm.
HMAC closes that gap by mixing a secret key into the computation itself, following a specific construction defined in RFC 2104: HMAC(K, m) = H((K ⊕ opad) ‖ H((K ⊕ ipad) ‖ m)). Because producing a valid HMAC requires knowing K — the shared secret — an attacker who doesn't have it cannot forge a signature for a tampered message, even though the hash function H underneath is exactly as public as it would be for a plain hash. This single change is why HMAC is the backbone of webhook verification, API request signing, and the HS256 algorithm used to sign JSON Web Tokens.
Why MD5 and SHA-1 Say LEGACY Here, Not BROKEN
It's worth being precise about this rather than reusing the same warning language a plain hash tool would use. MD5 and SHA-1 are collision-broken as hash functions — researchers can deliberately construct two different inputs that produce an identical digest, which is a serious problem for things like digital signatures and file integrity checks. But HMAC's security proof doesn't lean on collision resistance the way plain hashing does; it depends on different, weaker assumptions about the underlying compression function. As a direct result, HMAC-MD5 and HMAC-SHA-1 have not been practically broken as message authentication codes, despite MD5 and SHA-1 themselves being thoroughly broken for collision-sensitive uses.
That doesn't make them a good choice for anything new. Every major standard has moved to SHA-256 or better for new HMAC deployments, security margins shrink over time as cryptanalysis improves, and there's no real cost to simply using HMAC-SHA-256 instead. This tool tags results LEGACY rather than BROKEN specifically so the distinction is accurate: an existing system using HMAC-SHA-1 isn't in active danger the way a database of raw MD5 password hashes is, but new designs should default to SHA-256 or above regardless.
Key Encoding: The Detail That Silently Breaks Most HMAC Attempts
The single most common reason someone's manually computed HMAC doesn't match a real system's output has nothing to do with the algorithm — it's that the secret key was hashed as the wrong kind of bytes. A key handed to you as Base64, like k3F9x2vQ==, represents a specific sequence of raw bytes once decoded. If you hash the literal 12-character Base64 string as UTF-8 text instead of decoding it first, you get a completely different — and wrong — signature, even though every other input was correct.
This tool's key encoding selector exists precisely to remove that failure mode. Choose UTF-8 for an ordinary typed secret, Hex if your key was given as a hexadecimal string, or Base64 if that's the format your provider (many AWS and cloud services default to this) actually issued it in. The distinction matters just as much on the output side — see the next section — which is why both directions are configurable independently rather than assumed.
Choosing Between Hex and Base64 Output
There's no universal standard here, which is precisely why guessing wrong is so common. GitHub'sX-Hub-Signature-256 webhook header, Stripe's Stripe-Signature header, and most REST API request-signing schemes send a lowercase hex string. Some cloud provider signing schemes and certain token formats prefer Base64 instead, which is roughly 25% shorter for the same number of bytes. Neither is more "correct" in the abstract — match whatever the system on the other end of the comparison actually expects, and if you're not sure, generate both and try each.
Real-World Scenarios
Debugging a failed webhook signature check. An e-commerce integration keeps rejecting incoming payment webhooks as "invalid signature." The developer pastes the exact raw request body they received into this tool along with the webhook secret, generates HMAC-SHA-256 in hex, and compares it against the header value the provider sent — instantly narrowing the problem down to either a body-parsing issue (their framework re-serialized the JSON before verification) or a genuinely wrong secret, instead of guessing blind.
Signing an outbound API request by hand. A backend developer building an integration against a partner API that requires HMAC-SHA-256 request signing constructs the canonical string to sign, computes the HMAC here with the provided API secret, and confirms their production code produces the identical signature before wiring the real request logic into their application.
Manually checking a JWT's HS256 signature. Someone debugging an authentication issue takes the header and payload segments of a JWT, joins them with a period exactly as the token specifies, computes HMAC-SHA-256 with the shared signing secret, and compares the result — in Base64 URL form — against the token's third segment to confirm whether the signature is actually valid, independent of whatever library originally issued it.
HMAC vs a Plain Hash vs Bcrypt — Three Different Jobs
These three tools solve genuinely different problems, and mixing them up leads to real security bugs. The Hash Generator computes a plain, unkeyed digest — perfect for checking that a downloaded file matches a published checksum, useless for proving who sent something, since anyone can recompute it. This HMAC Generator adds a shared secret, which is exactly what you need for webhook signatures, API request authentication, and verifying that a message came from a party who holds the key — but it was never designed for password storage. The Bcrypt Hash Generator exists for that third job specifically: it's deliberately slow and includes an automatic random salt, properties neither a plain hash nor HMAC provide, which is exactly why passwords need bcrypt (or Argon2) rather than either of the other two.
Why It's Safe to Test Real Secrets Here
Every computation in this tool — key parsing, HMAC generation, and verification — runs through the Web Crypto API and local JavaScript entirely inside your browser tab. Nothing you type, including the secret key itself, is ever transmitted to ToollyX or any third party. You can disconnect from the network entirely after the page loads and confirm the tool keeps working exactly as before, which matters when you're debugging with a genuine (if non-production) API secret rather than a made-up placeholder.
Tips for Getting Signatures Right the First Time
- Sign the exact bytes you'll verify later — not a re-serialized version. If you're testing against a webhook payload, use the raw request body verbatim; re-formatting JSON (even just changing whitespace) produces a completely different HMAC.
- Double-check key encoding before assuming the algorithm is wrong. A Base64-issued secret hashed as literal UTF-8 text is the single most common cause of a mismatch — try the other encoding before concluding something deeper is broken.
- Default to SHA-256 for anything new. It's the algorithm nearly every modern API, webhook provider and signing scheme expects; only reach for HMAC-MD5 or HMAC-SHA-1 to match an existing legacy system.
- Use Verify mode instead of eyeballing long hex strings. A single mismatched character is invisible at a glance across a 64-character signature — let the tool do the character-by-character comparison.
- Never substitute HMAC for password storage. If you're building authentication rather than message signing, you want the Bcrypt Hash Generator, not this tool.
When This Tool Isn't the Right Fit
Skip this tool if you're hashing a password for storage — use the Bcrypt Hash Generator instead, since HMAC has no built-in salt or deliberate slowness and was never designed for that job. If you don't actually need authenticity — just a checksum to catch accidental corruption — a plain SHA-256 hash is simpler and doesn't require managing a shared secret at all. And if you need to encrypt data so it can be read again later rather than just signed, you want AES encryption, not HMAC, which — like any MAC — is one-way and never reveals the original message.