flashman
← All posts

HMAC hex and Base64 signature debugging

Debug HMAC mismatches by comparing exact message bytes, key encoding, digest algorithm, hexadecimal or Base64 output, and constant-time verification safely.

2026-09-05 · 6 min read · Rahul Chitturi

  • hmac
  • webhooks
  • security

Two systems can use HMAC-SHA-256 and still produce different signature strings. One may sign UTF-8 body bytes and return lowercase hexadecimal, while another signs decoded Base64 data or returns a Base64 digest.

HMAC also requires a secret key; hashing key plus message with an ordinary digest is not an equivalent construction and should not be used as a compatibility shortcut.

Write down the byte contract

Record the exact message bytes, key bytes, HMAC algorithm, output encoding, header prefix, and comparison rules. For webhooks, capture raw non-production request bytes before JSON parsing changes whitespace, escapes, member order, or line endings.

  • Distinguish text secrets from hex or Base64-encoded key material
  • Do not reserialize parsed JSON before verification
  • Decode the received signature exactly once
  • Reject malformed lengths and encodings before comparison

Verify without leaking the secret

Calculate the expected MAC with a maintained cryptographic library and compare decoded values using its constant-time comparison primitive after checking lengths. Authenticate timestamps or delivery IDs when the protocol includes them.

Logs should contain a request identifier, algorithm profile, body length, and broad failure category—not keys, complete signatures, or sensitive request bodies.

A Flashman workflow

Use hash only to label public fixture bytes, Base64 to inspect synthetic encodings, JSON formatter after preserving the raw signed body, and diff to compare documented strings-to-sign. Authoritative HMAC verification belongs in server code.

Test UTF-8 text, CRLF and LF, empty bodies, binary payloads, hex case, standard and URL-safe Base64, header prefixes, stale timestamps, wrong keys, malformed signatures, and retries.

Try these tools