ToolzYard

Fast, practical, browser-based developer tools

Crypto Tool • Free Online • No Signup

HMAC Generator Online

Generate HMAC SHA256 signatures using a message and a secret key. This tool is useful for API authentication, webhook verification, signed requests, message integrity checks, and testing cryptographic workflows without writing code first.

Ready to generate HMAC values.
Fast • Free • Browser-Based

Create HMAC SHA256 signatures for APIs, webhooks, and verification flows

HMAC combines a message with a secret key to produce a keyed hash that can be used to verify authenticity and integrity. Unlike a regular hash, HMAC depends on both the message and the secret, which makes it useful when two systems need to confirm that content has not been changed and was signed with the expected key.

✅ HMAC SHA256
✅ Secret key support
✅ Copy or download result
✅ Browser-based generation

Your message and key stay in the browser

This HMAC generator is designed to run in the browser. That means the text and secret key you enter can be processed locally on your device instead of being uploaded as part of the signing workflow. This is helpful when testing request signatures, webhook payloads, or private development data.

For more detail about site usage and analytics, read our Privacy Policy.

How to use this HMAC Generator

Enter the message you want to sign, provide your secret key, and click Generate HMAC. The page will create an HMAC SHA256 value that you can copy or download for use in tests, request signing, webhook validation, or debugging.

  1. Paste or type the message you want to sign.
  2. Enter the secret key.
  3. Click Generate HMAC.
  4. Copy the generated signature or download it as a text file.

To reproduce a signature correctly, the exact input text, secret key, encoding, and signing rules must match the system you are testing.

Example use case

Suppose an API requires you to sign a request body with a shared secret. You can paste the exact payload here, enter the same secret used by the API, and generate the HMAC value to compare against the expected signature.

Common scenarios

  • Webhook signature testing
  • API request signing
  • Message integrity checks
  • Auth flow debugging
  • Cryptographic verification experiments

Why HMAC exists instead of hash(secret + message)

The obvious way to authenticate a message with a shared secret is to hash them together — SHA256(secret + message) — and send the digest along. It looks correct and it is badly broken. The reason is a property of the hash function's internal design, not of your code.

SHA-256, SHA-1, and MD5 are Merkle–Damgård constructions: they absorb the message block by block and emit their entire internal state as the digest. That means the digest is the machine's resumable state. Given SHA256(secret + message) and the length of the secret — which an attacker can simply guess — they can resume hashing and compute a valid digest for secret + message + padding + anything they append, all without knowing the secret. This is a length-extension attack, and it lets an attacker forge authenticated messages. (SHA-3, BLAKE2, and SHA-512/256 are not vulnerable, but the widely used hashes are.)

How HMAC is built — the nested inner and outer hash

HMAC (RFC 2104) defeats length extension by hashing twice with the key mixed in at both ends. Written out, it is H((K ⊕ opad) ‖ H((K ⊕ ipad) ‖ message)), where ipad is the byte 0x36 repeated and opad is 0x5c repeated across a full block.

The message is hashed with the inner-padded key first, and that result is hashed again with the outer-padded key. Because an attacker only ever sees the outer hash of the inner state — never the raw internal state — they cannot resume the computation, so the length-extension trick simply does not apply. This is why you should never invent your own keyed-hash scheme: HMAC already solved a subtle problem you would probably get wrong.

Verifying an HMAC requires a constant-time comparison

Generating the HMAC is only half the job. When you check an incoming signature, how you compare the two values matters as much as the algorithm. A normal string or byte comparison (==) returns as soon as it hits the first differing byte, so the time it takes leaks how many leading bytes were correct.

An attacker who can measure that timing can recover a valid signature one byte at a time, never needing the secret — a classic timing attack. Compare with a constant-time function that always examines every byte: crypto.timingSafeEqual in Node.js, hmac.compare_digest in Python, hash_equals() in PHP. Never gate authentication on a plain equality check.

The canonical use: verifying webhook signatures

When Stripe or GitHub sends your server a webhook, it signs the request with a shared secret and puts the HMAC in a header — Stripe-Signature, or X-Hub-Signature-256 for GitHub. Your job is to recompute the HMAC over the payload with the same secret and compare, in constant time, against the header.

The gotcha that breaks nearly every first attempt: you must sign the exact raw bytes of the request body. If your framework parses the JSON and you re-serialise it before hashing, a reordered key or a changed space produces a completely different digest and every signature "fails." GitHub prefixes its value with sha256=, and Stripe folds a timestamp into the signed string so old captured requests cannot be replayed — read the provider's exact signing recipe rather than assuming.

Frequently Asked Questions

Why not just hash the secret and the message together?

Because SHA256(secret + message) is vulnerable to a length-extension attack. SHA-256 emits its full internal state as the digest, so an attacker who guesses the secret's length can append data and forge a valid digest without knowing the secret. HMAC's nested inner/outer hashing prevents exactly this.

Is HMAC encryption? Can I recover the message from it?

No. HMAC is a keyed hash, not a cipher. It is one-way and produces a fixed-size tag, so the original message cannot be recovered from it. Its purpose is to prove integrity and authenticity, not to hide the message contents.

Why does my signature not match the provider's?

Almost always because the bytes differ. Sign the raw request body before any JSON parse-and-re-serialise, watch for a trailing newline or charset difference, and confirm whether the expected value is hex or Base64 and whether it carries a prefix like sha256=. HMAC changes completely if a single input byte changes.

How should I compare two HMAC values in code?

With a constant-time comparison — crypto.timingSafeEqual, hmac.compare_digest, or hash_equals(). A normal == exits early on the first mismatched byte and leaks, through timing, how much of the signature was correct, which an attacker can exploit to reconstruct it.

Is HMAC-SHA256 still safe even though MD5 and SHA-1 are broken?

Yes. HMAC's security depends on the hash's resistance to certain attacks in a way that the collision breaks against MD5 and SHA-1 do not directly defeat — HMAC-SHA-1 remained practically secure long after SHA-1 collisions appeared. HMAC-SHA256 is a solid modern choice; use it rather than HMAC-MD5.

What algorithm does this page use, and does it send my secret anywhere?

It computes HMAC using SHA-256 in the browser, so your message and secret are processed on your device. That also means it is a testing and debugging aid — verify signatures in your backend with a constant-time comparison, not by pasting production secrets into web pages.