Security Runs locally Ready to use Built-in examples No tracking

HMAC Signature Generator

Enter a message and a secret key, pick an algorithm, and get the HMAC signature as lowercase hex plus Base64. Everything runs in your browser: the key is never uploaded or stored.

Signatures on payment gateways, open-platform APIs and webhook callbacks are almost always HMAC: a secret key is mixed into the hash, so without the key a signature cannot be forged — that is the essential difference from a bare SHA-256. This tool supports SHA-256, SHA-1 and MD5 and returns both hexadecimal and Base64, covering the differing requirements of differing API documents.

A signature computed here that disagrees with the server almost always comes down to three things: encoding (fixed to UTF-8 here), message assembly (many APIs require parameters sorted by name or a timestamp appended, rather than the raw payload), and output form (Base64 or uppercase hex). The quickest way to diagnose it is to run the example string from the API documentation and see whether it matches — if it does, the algorithm is right and the assembly is wrong.

How to use

  1. Enter the message.
  2. Enter the secret key and choose the algorithm.
  3. Compare the hexadecimal and Base64 outputs with the server's.
  4. If they disagree, check encoding, message assembly and output form.

How it works

Basic usage

Enter the Secret Key your server gave you into the "key" field, paste the content to sign into the message box, and the signature generates instantly. Changing any character — spaces and newlines included — changes everything; an empty key raises an error, while the message may be an empty string.

Why the server computes something different

The most common mismatches come from three places. Encoding: this tool always uses UTF-8, while some servers use GBK or URL-encode first. Message content: many APIs sign not the raw payload but "parameters concatenated in sorted order" or "timestamp + nonce + payload". Output form: servers may expect Base64 or uppercase hex — confirm all three against the server before comparing.

Which algorithm to pick

For new interfaces, always HMAC-SHA256. HMAC-SHA1 survives only in OAuth 1.0 and legacy payment gateways; HMAC-MD5 only for historical systems. Note that "MD5/SHA-1 is insecure" refers to bare-hash collisions — HMAC mixes in a key so collision attacks don't transfer directly — but with SHA-256 available there's no reason to use the old algorithms in new work.

Method: HMAC per RFC 2104 with SHA-256, SHA-1 (RFC 3174) and MD5 (RFC 1321). The key and message are encoded as UTF-8; keys longer than 64 bytes are hashed first and then zero-padded to the block size. Output is lowercase hex and standard Base64. No timestamp or header assembly, and no constant-time signature verification.

Code example

JavaScript Computing HMAC in Node

const { createHmac } = require("crypto");

createHmac("sha256", secret).update(payload).digest("hex");
createHmac("sha256", secret).update(payload).digest("base64");

// Verify with a constant-time comparison on the server to avoid timing side channels
crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));

PHP Computing HMAC in PHP

// Matches how most payment-gateway docs write it
echo hash_hmac("sha256", $payload, $secret);                       // hex
echo base64_encode(hash_hmac("sha256", $payload, $secret, true));  // Base64

// Note: for keys longer than 64 bytes, RFC 2104 hashes the key first —
// hash_hmac and this tool both do that, so no manual truncation is needed

FAQ

HMAC vs. a plain SHA-256 — what's the difference?

Anyone can compute SHA-256, so an attacker who alters the message can recompute a valid digest. HMAC mixes the key into the computation, making the signature unforgeable without it. Use HMAC to authenticate where a message came from; bare hashes only verify corruption. Internally HMAC is two keyed hash passes (inner XOR 0x36, outer XOR 0x5c), not a naive "hash the key, append the message".

Can the key be any length? What if it exceeds 64 bytes?

There's no hard minimum, but very short keys (say 4 characters) fall to brute force — prefer 32+ random bytes. Keys longer than the 64-byte block size are hashed once before use, per RFC 2104. To see this, hash the same message with a 64-byte and an 80-byte key — this tool ships examples for both.

Is the signature hex or Base64?

Both are valid; it depends on the server's convention. The main result here is lowercase hex of the 32-byte signature (64 characters for HMAC-SHA256), with standard Base64 below. Mind the case: some servers want uppercase hex — convert with the form below the result.

Why doesn't my signature match the server's for the same key and message?

Check three things: encoding (this tool fixes UTF-8), the message itself (servers usually sign sorted-parameter strings or timestamp+nonce+payload, not the raw request), and the output form (Base64 or uppercase hex). The sample values in the API's "signature algorithm" section are the fastest diagnostic — reproduce one exactly; if it matches, the algorithm is right and your assembly is wrong.

Why must the timestamp be part of the signed content?

Replay protection: if the signature covers only business parameters, an attacker can replay a captured request verbatim. Signing the timestamp (often plus a nonce) lets the server reject requests older than 5–10 minutes, shrinking the replay window. The timestamp is message content too — the format (seconds vs. milliseconds, zero-padding) must match the server exactly.

Does the key stay on the page or get uploaded?

It stays. All computation is local; the key is never sent to a server or written to browser storage, and this tool deliberately has no history section. Even so, keep production keys (especially sk_live ones) out of online tools — verify in a test environment, and let production code or the command line handle the real thing.

Why is the HMAC-SHA1 signature only 40 characters?

SHA-1's digest is 160 bits = 20 bytes = 40 hex characters; SHA-256 is 256 bits = 32 bytes = 64 characters; MD5 is 128 bits = 16 bytes = 32 characters. Signature length only mirrors digest length — the real difference is collision resistance, not character count.

Can it verify signatures, not just generate them?

This page only generates. Proper verification: the server recomputes the HMAC with the same key and message, then compares with yours — using a constant-time comparison (like Node's crypto.timingSafeEqual). Ordinary string comparison returns early on the first mismatch, leaking information and opening a timing side channel for forging signatures.