HMAC Generator — Sign Messages with SHA-256
Compute HMAC-SHA256, HMAC-SHA384, or HMAC-SHA512 signatures for any message and secret key, in hex and base64. Runs locally with Web Crypto.
Input
How it works
- HMAC wraps the chosen hash algorithm with a secret key: the key is padded, XOR-mixed into two inner/outer pads, and hashed in a specific order.
- The result has the same length as the underlying hash — 256, 384, or 512 bits — regardless of message or key length.
- Computing the same HMAC requires the shared secret, so a valid signature proves the message came from someone who knows the key.
- Everything is calculated in your browser with
crypto.subtle; no data is sent anywhere.
About HMAC
HMAC (Hash-based Message Authentication Code) is a keyed hash: it combines a hash function such as SHA-256 with a shared secret to produce a signature that verifies both integrity and authenticity. Unlike a plain hash, which anyone can recompute, an HMAC is unpredictable without the key — changing even one bit of the message produces a completely different signature. The secret is the root of trust, and the message can be stored or transmitted openly.
Use HMAC whenever two parties share a secret and need to prove messages were not tampered with or forged: API request signing, webhook payload verification, and session tokens are the most common cases. Never use a plain hash for these — an attacker can recompute MD5 or SHA-256 without the key. Keep the secret key out of client-side code, rotate it periodically, and use separate keys for different purposes. The signature authenticates, but it does not encrypt: if confidentiality is also needed, combine HMAC with encryption (for example, AES-GCM).
Why HMAC-SHA256 became the default
A plain digest is public knowledge: anyone can recompute SHA-256 over your payload, so it detects corruption but offers no protection against forgery. HMAC folds a shared secret into the computation, which means producing a valid tag requires a value the verifier alone holds. That combination — keyed, fixed-length, no key exchange, cheap to verify — is why Stripe, GitHub and Slack webhook signatures all settled on HMAC-SHA256.
The key is zero-padded to the 64-byte block size, or hashed first if it is longer, and the two XOR pads are what make the construction resistant to length-extension style attacks that would break a naive `hash(key || message)`. The result is always 256 bits for SHA-256 regardless of message size, and any single-bit change anywhere in the input yields an unrelated tag.
Details that break real integrations
Encoding is part of the contract, not a presentation choice. This page prints lowercase hex and standard base64, and base64 of a tag contains `+` and `/`, both of which need percent-encoding in a query string or a URL path segment. Most libraries default to lowercase hex, so match whatever your provider documents rather than assuming the base64 form is interchangeable.
Any key length is accepted because Web Crypto pads to the block size internally — a short key works, and a short key is still a weak key. Use at least 32 random bytes drawn from a CSPRNG. Whitespace is part of the message: signing a JSON string signs the exact bytes including spaces and newlines, so both sides must serialise identically or the tags will never match.
Signing is not verifying
This page signs and does not verify, and verification is where the subtle bug lives. Comparing two tags with `===` short-circuits at the first differing byte, leaking through response timing how much of a forged tag was correct — enough to recover a valid tag one byte at a time. Use `crypto.subtle.verify('HMAC', key, tag, message)`, which compares in constant time internally and returns the boolean without you writing the loop.
One boundary condition to note: the UI rejects an empty message, so a zero-length body cannot be signed here. If a provider allows one, sign it with your own code. And keep the two properties separate in your head — an HMAC proves the message came from someone holding the secret and was not altered, but says nothing about confidentiality. For that, combine HMAC with an authenticated cipher such as AES-GCM.
Frequently Asked Questions
How do I compute an HMAC?
Why use HMAC instead of a regular hash?
Is my data sent to a server?
Do I need an account or API key?
Can I use these tools offline?
All processing happens in your browser. No uploads, no tracking, no servers. Your API keys, configs, and private payloads stay private — 100% client-side.