HMAC Generator

Compute an HMAC signature for any message and secret using SHA-1, SHA-256, SHA-384 or SHA-512, with hex, base64 or base64url output.

Message authentication codes, locally. HMAC combines a hash function with a secret key so a recipient can verify both integrity and authenticity. Computed in your browser via the Web Crypto API.

What HMAC is for

Authentication, not encryption

An HMAC does not hide anything. It answers a different question: was this exact message produced by someone holding the shared secret, and has it been altered since? The output is a fixed-size tag you send alongside the message; the receiver recomputes it with the same key and compares. Matching tags mean the message is authentic and intact. Mismatched tags mean it is neither, and there is no way to tell which.

This makes HMAC the workhorse behind webhook signatures, API request signing, signed cookies and session tokens. Stripe, GitHub and most webhook providers sign their payloads this way so you can verify a request really came from them rather than from someone who guessed your endpoint URL.

Why not just hash the key and message together

The obvious construction — SHA256(key + message) — is broken against Merkle-Damgard hashes like SHA-1 and SHA-256. Those hashes process data in blocks and carry state forward, so an attacker who knows a valid digest can append data and compute a valid digest for the extended message without ever learning the key. This is the length-extension attack, and it is not theoretical; it has broken real APIs.

HMAC's nested construction, H(key XOR opad || H(key XOR ipad || message)), closes that hole. The two passes with different padded keys mean the final digest is not the raw internal state of a hash over attacker-influenced data. This is why you should always reach for HMAC rather than inventing your own keyed hash.

Practical notes

Choose SHA-256 unless something external forces your hand. SHA-1 is still safe inside HMAC because the construction does not rely on collision resistance, but new systems have no reason to use it and auditors will flag it. SHA-512 is not meaningfully stronger for this purpose and is sometimes faster on 64-bit hardware.

Two implementation details matter more than the hash choice. First, compare tags in constant time — a normal string comparison returns early on the first differing byte, which leaks enough timing information to forge a tag one byte at a time. Second, keys should be random bytes of at least the digest length, not a memorable passphrase; HMAC keys are not password hashes and get no stretching.

Open-source note: implemented with the browser-native Web Crypto (crypto.subtle) API. No third-party libraries.

FAQ

Is my secret sent anywhere?
No. The key and message never leave your browser; the signature is computed locally with the Web Crypto API and nothing is transmitted or stored.
Which algorithm should I choose?
Use SHA-256 for new work. SHA-384 and SHA-512 raise the security margin at a small cost; SHA-1 exists only for interoperability with legacy systems.
What is the difference between base64 and base64url?
Base64url substitutes - and _ for + and / and drops the padding, which makes the result safe to place in URLs, filenames and HTTP headers.
Is HMAC a form of encryption?
No. It proves the message came from a holder of the key and was not modified, but the message itself stays fully readable. Add TLS or encryption if you also need secrecy.
Why not just hash the key and message together?
Plain SHA-2 is vulnerable to length extension: an attacker can append data to a signed message and forge a valid digest without knowing the key. HMAC's nested construction blocks that.
How should I compare two HMACs in code?
With a constant-time comparison such as crypto.timingSafeEqual. A normal == exits at the first differing byte, which can leak the correct tag one byte at a time.