How To · Guide

How to Generate an HMAC-SHA-256 Signature

How do I generate an HMAC-SHA-256 signature?

SHORT ANSWER

Pick the tool for your stack. In Node.js use crypto.createHmac("sha256", secret).update(message).digest("hex"). In Python use hmac.new(key, msg, hashlib.sha256).hexdigest(). On the command line use openssl dgst -sha256 -hmac <secret>. All three produce the same value for the same message and key.

The inputs

An HMAC signature needs exactly three things: the message, the shared secret key, and the hash algorithm, SHA-256 here. The output format matters too: hex is 64 characters and base64 is shorter. The receiver must use the same format you do.

Node.js

const crypto = require("crypto"); const sig = crypto.createHmac("sha256", secret).update(message).digest("hex");. Swap "hex" for "base64" when the receiver expects base64.

Python

import hashlib, hmac; sig = hmac.new(key.encode(), msg.encode(), hashlib.sha256).hexdigest(). The hmac module ships with Python, so there is nothing to install.

OpenSSL on the command line

printf '%s' "$message" | openssl dgst -sha256 -hmac "$secret" -hex prints the hex signature. Append -binary | base64 for base64 output. This is convenient in shell scripts and CI pipelines.

A worked example

With the message The quick brown fox jumps over the lazy dog and the key key, HMAC-SHA-256 in hex is f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8. Use a known vector like this to confirm a library is producing correct output.

Verify with constant time

Never compare signatures with a plain equality check. Use timingSafeEqual in Node or hmac.compare_digest in Python so the comparison time does not leak information about the key.

TRY IT LOCALLY

Try it in your browser with our HMAC Generator. No upload, no server.

Open HMAC Generator →

FAQ

Is hex or base64 better?

Both are fine as long as sender and receiver agree. Hex is longer and convenient for logs, while base64 is more compact for headers.

Can I generate HMAC without a library?

Yes, but do not. OpenSSL covers it from the command line, and Node.js and Python have it built in. Hand-rolled HMAC is a common source of subtle bugs.

How do I verify an incoming signature?

Recompute HMAC with your secret key and the exact received message, then compare in constant time with timingSafeEqual or compare_digest.