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.