An HMAC-SHA256 tag is a 32-byte keyed-hash output computed by combining a shared secret key with the exact bytes of a message through the SHA-256 compression function, then producing a fixed 64-character hexadecimal string or a 44-character Base64 string that a verifier with the same key can recompute to confirm that the message was not modified. The construction defined in NIST FIPS 198-1 mixes the secret into both the inner and outer hash passes so the secret itself never appears in the digest. The output is deterministic: any party that knows the same secret and feeds the identical byte sequence to the algorithm must arrive at the identical tag. HMAC does not encrypt the message — anyone who sees the plaintext can still read it, and anyone who learns the secret can forge a valid tag, so key handling is what actually determines security. When the task is to generate an HMAC-SHA256 tag with a known key, the practical work is getting the input bytes exactly right and choosing the encoding the receiving endpoint accepts.

What an HMAC-SHA256 Tag Actually Is
HMAC stands for keyed-hash message authentication code. It wraps an underlying hash function — in this case SHA-256 — with two derived keys, one mixed into the message before hashing and one mixed into the result after hashing. The published definition in NIST FIPS 198-1 makes the construction provably secure as long as the underlying hash remains collision-resistant or pseudorandom. The HMAC-SHA256 tag is always exactly 32 bytes long regardless of message size: a one-character message and a multi-megabyte message both produce the same 64-hex-character output.
What the tag proves is two things at once. First, the verifier holding the secret can recompute the tag from the received bytes and confirm it matches, which proves the bytes were not altered in transit. Second, anyone who could compute a matching tag must have known the secret, which authenticates the sender. What the tag does not prove is confidentiality — the plaintext message travels alongside the tag in every common protocol, and anyone intercepting the pair still sees the cleartext.
A third property worth noting is that the tag is not a hash of the message alone. Two messages with similar plaintext produce completely unrelated tags because the secret material is mixed in at every step, so the output cannot be used as a fingerprint for messages exchanged between parties who do not share the secret. An HMAC tag is therefore an authentication and integrity primitive, not a public hash.
Picking the Right Hash and Input Mode
The algorithm choice comes from the receiving system, not from preference. JWTs that use HS256 require HMAC-SHA256; AWS Signature v4 in newer regions uses HMAC-SHA256; some APIs and IoT protocols specify SHA-384 or SHA-512 instead. Switching the hash when the protocol asks for one of them produces a tag the receiving side rejects, so the first decision is reading the protocol spec and confirming it expects a full-length HMAC-SHA256 tag.
The next decision is how the key and message are encoded. UTF-8 mode treats the input as Unicode text, where the obvious-looking string "café" is actually five bytes and emoji such as 🛡 occupy four bytes each. Hex mode accepts only an even number of 0–9 and a–f characters and decodes them as the literal bytes of the field; it rejects "0x" prefixes, internal spaces, colons and odd nibble counts so an accidental formatting character cannot silently change a protocol value. Each decoded field is capped at 1,000,000 bytes, and empty keys and empty messages are rejected by the interface to prevent accidental clicks. The HMAC Generator offers these modes for both the key and the message, and the two can be picked independently.
The key and message can use different modes independently. A common pattern is to enter a published test vector as hex bytes while the message is plain UTF-8 text, or to enter a human-readable key while the message comes from a binary protocol field. The single rule is byte identity: whatever bytes the receiver will feed into HMAC must be the bytes entered here, with no extra whitespace, no trailing newline and no leading identifier.
How to Generate an HMAC-SHA256 Tag
- Confirm the protocol expects a full HMAC-SHA256 tag (32 bytes) and not a truncated value, then choose SHA-256 in the tool.
- Enter the secret key. Switch to UTF-8 mode if the key is human text, or to hex mode if it is a binary or published key — paste the exact bytes with no 0x prefix, no colons and no spaces.
- Enter the message the receiver will hash. Pick UTF-8 or hex for the message independently from the key's mode; if the protocol canonicalizes whitespace, apply that rule before pasting.
- Click generate. The HMAC Generator renders the full tag as lowercase hex and as standard padded Base64 in the same step, so both encodings are available without re-entering anything.
- Copy the encoding the protocol asks for. Use hex for log files, command-line tools and most APIs; use Base64 for HTTP headers, JWTs and environments where compactness matters.
- Do not truncate the tag, do not add a version or algorithm prefix, and do not switch to Base64url unless the receiving system documents that requirement — visually similar strings are not interchangeable.
Reading and Sharing the Output Safely
Hex and Base64 are not different tags — they are two renderings of the same 32 bytes. The hex form is two characters per byte, so a SHA-256 tag is always 64 characters. The Base64 form groups three bytes into four characters and pads to a multiple of four, which for a 32-byte input is 44 characters with a single '=' padding character at the end. Converting between the two is lossless and produces identical bytes when decoded.
What is not interchangeable is standard Base64 and Base64url. The url-safe variant substitutes '-' for '+' and '_' for '/' and typically drops padding, so a token intended for one encoding will be rejected by a strict decoder of the other. The HMAC Generator emits standard padded Base64; only convert to Base64url when the protocol explicitly asks for it. The same caution applies to prefixed outputs such as a literal "hmac-sha256=" or "v1." — those are envelope conventions added by a higher-level protocol, not part of the HMAC tag itself.
Operational hygiene matters as much as byte accuracy. Generate key material from a cryptographically secure random source appropriate for the protocol, distribute it through a protected channel, separate keys by purpose and rotate them after any suspected compromise. A human password is low entropy and must not be used directly — when a password must become a key, run it through the protocol's documented password-based KDF (PBKDF2, bcrypt, scrypt or Argon2) and use the derived bytes as the HMAC key. Never paste a production secret into a shared or untrusted device, and always compare received tags against the recomputed tag on the server using a constant-time function so a timing side channel cannot leak byte-by-byte agreement.
Why Tags Differ Between Tools
When two systems produce different tags for what looks like the same input, the cause is almost always a byte-level mismatch rather than a real interoperability failure. The checklist covers every axis where a stray character can change the result:
- Hash choice — SHA-256, SHA-384 and SHA-512 produce tags of 32, 48 and 64 bytes respectively.
- Key encoding — UTF-8 bytes versus decoded hex bytes; the same word can be different byte sequences depending on accents, normalization and multi-byte characters.
- Message encoding — UTF-8 text, hex bytes or a base64-decoded input, plus the whitespace and newline convention applied before hashing.
- Tag truncation — a tag cut to the first 16 bytes is a different value even though both look related, and the protocol must specify any truncation.
- Output encoding — standard Base64 versus Base64url, or uppercase versus lowercase hex where the receiver is strict.
The HMAC Generator is locked to eight full RFC 4231 conformance tags, covering short keys, binary repeated-byte keys and data, keys smaller than the digest and data crossing hash block boundaries. SHA-256 and SHA-512 are checked for four independent inputs each, and the interface also exposes the WebCrypto-defined SHA-384 option. When the receiver rejects a tag, the fastest path back to agreement is to confirm the exact key and message bytes against a published vector first, then compare the algorithm and output encoding.
Hash variant comparison
| Hash | Output bytes | Hex length | Base64 length | Common use |
|---|---|---|---|---|
| SHA-256 | 32 | 64 | 44 | JWT HS256, AWS Signature v4 |
| SHA-384 | 48 | 96 | 64 | Higher-assurance protocols |
| SHA-512 | 64 | 128 | 88 | Legacy servers and 64-bit native code |
The browser-based implementation imports the chosen bytes as a non-exportable WebCrypto HMAC key, runs subtle.sign with the selected hash and renders the resulting tag independently as lowercase hex and as standard padded Base64 — every input stays in the current tab and never reaches a server.