HMAC Generator

Sign a message with a secret key. HMAC proves both that a message is intact and that it came from someone holding the key — which a plain hash cannot do. Your key never leaves this page.

{{ textCount }}

Encoding The same text in a different encoding is different bytes, so it produces a different digest. UTF-8 unless you are matching a legacy system.
Format
Or just start typing…
{{ r.label }} {{ r.bits }} bits · {{ format }} {{ r.secLabel }}

{{ r.value }}

{{ legacyNames }} {{ legacyNames.indexOf(' and ') === -1 ? 'is' : 'are' }} selected. Practical collisions are public for both, so treat the result as a checksum for spotting accidental corruption — not as evidence that a file is authentic.

Export

Drop files here to hash them

or

Up to 100 files · any size · read in 4 MB chunks, never uploaded

Files are read, not uploaded. Each one is streamed through the hash function in chunks straight from disk, so a multi-gigabyte image never lands in memory and never leaves your device.

Encoding The same text in a different encoding is different bytes, so it produces a different digest. UTF-8 unless you are matching a legacy system.
Format
{{ status }}
{{ f.name }} {{ fmtBytes(f.size) }} Done Hashing {{ f.progress }}% Queued Failed

{{ f.error }}

{{ r.label }} {{ r.bits }} bits

{{ r.value }}

Export

The key never leaves this page. It is not sent to a server, not saved to local storage, and not written into the exported files.

Algorithm
Key as Signing secrets from webhook providers are usually published as hex or Base64. Hashing those characters as literal text produces a different, wrong MAC.
Encoding The same text in a different encoding is different bytes, so it produces a different digest. UTF-8 unless you are matching a legacy system.
Format
HMAC-{{ label(hmacAlgo) }} {{ format }}

{{ hmacResult }}

HMAC is not a hash with the key glued on the front. It runs the key through the hash twice with two different pads, which is what makes it resistant to the length-extension attacks that break a naïve hash(key + message).

Drop the file you want to check

or

Hashed in your browser · never uploaded

{{ vFile.name }} {{ fmtBytes(vFile.size) }}
Algorithm A {{ expectedLen }}-character hash could be either of these — pick the one the publisher used. Identified from the hash length.

Hash matches

The {{ vResult.label }} digest of {{ vFile.name }} is identical to the hash you supplied, so this is the file that checksum describes. Letter case and surrounding whitespace were ignored.

Both {{ vResult.computed }}

Hashes match

Both are the same {{ cmpResult.len }}-character value, so they identify identical content. Ignored while comparing: letter case, spaces, line breaks, and any sha256:-style prefix.

Both {{ cmpResult.a }}

Length {{ cmpResult.len }} — consistent with {{ cmpResult.guess }}.

Text, files and secret keys are hashed in your browser. Nothing you enter is ever uploaded to a server.

What HMAC is for

A plain digest proves a message has not changed. It cannot prove who produced it, because anyone can compute a digest. HMAC adds a shared secret, so a valid code proves both that the message is intact and that it was produced by someone holding the key. That is why webhooks are signed with HMAC rather than hashed.

Why not just hash the key and the message together?

Because hash(key + message) is vulnerable to a length-extension attack. The Merkle–Damgård construction behind MD5, SHA-1 and SHA-2 leaks enough internal state in its output that an attacker can append data to your message and compute a valid digest for the longer message without ever learning the key. HMAC runs the key through the hash twice with two different pads, which closes that hole.

The key's encoding matters

This is where most HMAC bugs come from. Stripe, GitHub and AWS publish signing secrets as hex or Base64 strings. If you hash those characters as literal text you are keying with the wrong bytes and every signature will differ from the one the sender computed — with nothing to tell you why. Set Key as to match the form your secret was given in.

Comparing MACs safely

In your own code, compare MACs with a constant-time function such as hash_equals in PHP or crypto.timingSafeEqual in Node. A plain === returns as soon as it finds a differing byte, and that timing difference can leak enough to forge a signature.

See also the full Hash Generator.

What is HMAC?

A keyed message authentication code. It mixes a secret key into the hashing process, so only someone holding that key can produce the result — or check it. A plain digest proves a message is unaltered; an HMAC also proves who produced it.

How is it different from hashing the key and message together?

HMAC runs the key through the hash twice with two different pads. That construction resists length-extension attacks, which break the naive hash(key + message) approach: an attacker can append data to the message and compute a valid digest without knowing the key.

Should my key be text, hex or Base64?

Whatever form the key was given to you in. Webhook signing secrets are commonly published as hex or Base64, and hashing those characters as literal text yields a different, wrong MAC. This is the single most common HMAC mistake.

Which algorithm should I use?

HMAC-SHA256 unless something requires otherwise. HMAC-SHA1 and HMAC-MD5 are still in use and are not broken in the way plain SHA-1 and MD5 are, but there is no reason to choose them for new work.

Is my key sent anywhere?

No. It is used in your browser, is not written to local storage, and is excluded from the exported files. It is masked on screen by default so it does not linger in screenshots or a shared screen.