HMAC Generator

Share:

Generate HMAC signatures with SHA-1, SHA-256, SHA-384 or SHA-512. Output as hex, base64 or base64url. All computation in your browser.

RT-CW3-001 · Crypto & Web3

HMAC Generator Tool

Privacy: All HMAC computation happens inside your browser using the native SubtleCrypto API. Your secret key and message never leave this page. We do not log or proxy any inputs.
Advertisement
After results · AD-W1 Responsive · Post-tool — peak engagement

How to use the HMAC generator

Paste your secret key

This is the shared secret between you and whoever you're signing data for — typically the value the API or webhook provider issued you.

Paste the message

The exact bytes you want to sign — a webhook payload, an HTTP request body, the canonical request string for AWS signature v4, etc.

Pick the algorithm

SHA-256 is the modern default. SHA-512 is used by some banking APIs. SHA-1 is legacy — only use it for webhook providers that still mandate it.

Copy the signature

Three output encodings: hex (most common for AWS, Stripe, GitHub), base64 (Slack, Shopify), base64url (JWT-style). Copy whichever matches your destination.

Advertisement
After how-to · AD-W2 Responsive

HMAC — what it is, why APIs use it

HMAC stands for Hash-based Message Authentication Code. It is a cryptographic construction that takes two inputs — a secret key and a message — and produces a fixed-size signature that anyone who knows the same secret key can verify but no one without the key can forge. The original specification was published as RFC 2104 in 1996, and it has remained essentially unchanged since. HMAC is one of the most-deployed cryptographic primitives in production today; almost every webhook-driven API on the internet uses it for request signing.

Where you'll see HMAC in practice

Webhook signatures are the most-common use. When Stripe, GitHub, Shopify, Razorpay (the Indian payments giant), Xendit (the dominant Indonesian fintech infrastructure provider) or NETS (Singapore's domestic payment scheme) send a webhook to your server, they include an HMAC signature in the request headers. Your server independently computes the HMAC of the request body using the shared secret, then compares — if the signatures match, the request really came from the provider and wasn't tampered with in transit. AWS signature version 4 (used to sign every authenticated AWS API call) is HMAC-SHA256 under the hood. JSON Web Tokens signed with the HS256, HS384 or HS512 algorithm are HMAC underneath. Even older APIs like Twitter's OAuth 1.0a flow used HMAC-SHA1.

HMAC versus a plain hash

A common mistake is to "sign" a message by computing SHA256(secret + message) directly. This is not secure — it is vulnerable to a class of attacks called length-extension attacks, where an attacker who has seen one valid signature can compute valid signatures for longer messages without knowing the secret. HMAC's construction (which involves two nested hash operations with carefully-chosen XOR'd keys) is provably immune to length extension. The performance cost is roughly one extra hash operation; the security benefit is the difference between a sound construction and a broken one.

Constant-time verification

When you verify a webhook signature, do not compare strings directly with === or strcmp. Use a constant-time comparison function instead — hash_equals in PHP, crypto.timingSafeEqual in Node.js, hmac.compare_digest in Python. The reason is a timing attack: a naive string comparison returns false at the first byte that differs, leaking information about how many leading bytes were correct. A constant-time comparison takes the same time regardless of where the strings differ, denying that side-channel. This matters specifically for verification, not for the HMAC computation itself.

Picking the right output encoding

HMAC produces bytes. Bytes have to be encoded as text for transmission in HTTP headers or JSON bodies. The three common encodings are hex (twice as long as the raw bytes, lower-case alphanumeric only — used by GitHub, Stripe, AWS), base64 (about 33% longer than raw, includes +/= characters which sometimes need URL-encoding — used by Slack, Shopify), and base64url (same length as base64 but uses -_ instead of +/ and drops padding — used by JWTs). The right encoding depends on the destination; check the API provider's documentation. The tool above shows all three so you can match without re-running.

Common implementation mistakes

Three traps catch most teams the first time they implement HMAC verification. First, signing the wrong bytes — many webhook providers sign the raw request body, but a JSON-parsing middleware can re-serialise it before your handler runs, mangling whitespace and breaking the match. Always sign the original raw bytes. Second, leaking the secret in logs or error messages. Third, rotating the secret without a grace window that accepts both old and new for a few minutes.

10 HMAC facts every developer should know

01

HMAC was specified in RFC 2104 in 1996 and has been essentially unchanged since. It's one of the longest-lived cryptographic primitives still in active production use.

02

HMAC is provably immune to length-extension attacks that affect raw SHA(secret+message) constructions. The double-hash design is exactly what closes that gap.

03

The recommended HMAC key length matches the underlying hash output: 32 bytes for HMAC-SHA256, 64 bytes for HMAC-SHA512. Longer keys offer no extra security.

04

AWS signature version 4 — used to sign every authenticated AWS API call worldwide — is HMAC-SHA256 with a layered key-derivation chain that includes the region and service name.

05

Webhook signature timing attacks have been demonstrated in the wild. Use hash_equals (PHP), crypto.timingSafeEqual (Node.js) or equivalent for verification — never plain ===.

06

HMAC-SHA1 is still considered cryptographically sound for new deployments, despite SHA-1's collision weakness — HMAC's construction does not require collision resistance of the underlying hash.

07

JSON Web Tokens with the HS256 algorithm are HMAC-SHA256 underneath. The "HS" stands for "HMAC SHA-" — and the JWT signature is exactly this output, base64url-encoded.

08

Slack's webhook signing uses HMAC-SHA256 with base64 output and a v0= prefix in the header. The prefix is purely versioning — current Slack signatures are all v0.

09

Shopify's webhook secret can be rotated without downtime — Shopify accepts signatures from both old and new secrets for a 24-hour overlap window after rotation.

10

The browser SubtleCrypto API supports HMAC-SHA1/256/384/512 natively. No JavaScript library is needed; modern web apps can verify signatures client-side with about 10 lines of code.

Frequently asked questions

A plain hash like SHA-256 turns a message into a fingerprint that anyone can verify without a secret. HMAC adds a secret key into the construction so only people with the same key can compute or verify the signature. Webhooks use HMAC; file checksums use plain hashes.
For HMAC purposes yes — HMAC's construction does not require collision resistance of the underlying hash, so SHA-1's well-known collision weakness does not break HMAC-SHA1. Many production webhooks still use it. For new deployments, prefer SHA-256.
Take the request body exactly as received (raw bytes, before any JSON parsing). Compute HMAC using the shared secret and same algorithm the provider used. Compare your output to the provider's signature using a constant-time comparison function. Match means valid; mismatch means reject.
Naive string comparison returns false at the first byte that differs. An attacker measuring the response time learns how many leading bytes of their forged signature were correct, then iterates to discover the rest. Use hash_equals in PHP, crypto.timingSafeEqual in Node.js, or hmac.compare_digest in Python.
HMAC is deterministic — same key, same message, same algorithm always produces the same signature. That's what makes verification possible. If you need a different signature every time, you need a different message (e.g. include a timestamp or nonce).
Stripe webhooks use HMAC-SHA256 with hex output, prefixed by a timestamp in the Stripe-Signature header. Format: t=1234567890,v1=hex_signature. The signed payload is timestamp.body, not just the body.
GitHub webhooks use HMAC-SHA256 with hex output, sent in the X-Hub-Signature-256 header. Format: sha256=hex_signature. The signed payload is the raw request body.
No. HMAC is for message integrity, not password storage. For passwords, use bcrypt, scrypt or Argon2 — they are deliberately slow to compute, which is the wrong property for an HMAC but the right property for password hashing.
Standard base64 uses + and / as the 63rd and 64th characters and = for padding. These characters have special meaning in URLs, so base64url replaces them with - and _ and drops padding. JWT signatures use base64url.
Yes. The tool uses the browser's native SubtleCrypto API. Your secret and message never leave the page; nothing is sent to any server. You can verify this by opening the browser network tab and confirming no requests fire when you generate a signature.

Related News

You may be interested in these recent stories from our newsroom.

View all news →
Advertisement
Pre-footer · AD-W3 728 × 90

75 more free tools

Calculators, converters, security tools — no signup.