2026-09-05 · 8 min read
- hmac
- webhooks
- security
HMAC combines a secret key, a cryptographic hash function, and an exact message byte sequence to produce a message authentication code. It is not the same as hashing a concatenated key and message, and it does not encrypt the message.
Most integration failures are representation failures: one side signs parsed or normalized content, decodes the key differently, includes a timestamp or prefix in another order, or renders the digest as hex while the other expects Base64.
Specify every byte and encoding
Write the protocol as an ordered byte construction. State the HTTP method, target, selected headers, timestamp, separators, body bytes, character encoding, key representation, HMAC algorithm, digest encoding, and any header prefix.
- Treat a text key, hexadecimal key, and Base64 key as different inputs.
- Distinguish standard Base64 from URL-safe Base64.
- Define hexadecimal case and whether a prefix is included.
- Do not normalize line endings unless the protocol says to.
Verify the raw request before parsing
For webhook signatures over the request body, retain the raw received bytes before a framework parses JSON or forms. Parsing and reserialization can change whitespace, escape sequences, member order, duplicate handling, Unicode representation, and terminal newlines.
After successful authentication, parse and validate the payload normally. Bound request size and reject malformed signature encodings before allocating unnecessary work.
Add replay and key controls
Use a maintained cryptographic library and compare equal-length decoded MAC values with its constant-time primitive. Validate a signed timestamp and delivery identifier when the protocol provides them, then enforce a bounded acceptance window and duplicate-delivery policy.
- Select keys through a constrained server-side identifier.
- Support rotation with a short, explicit overlap window.
- Never fetch key material from untrusted signed input.
- Log identifiers and failure categories, not secrets or bodies.
Create public conformance fixtures
Use Flashman's hash tool only to label public message fixtures, Base64 for synthetic encodings, JSON formatter after preserving signed bytes, diff for strings-to-sign, and timestamp converter for replay-window examples. Compute and verify HMAC in trusted application code.
Test empty and binary bodies, UTF-8, CRLF and LF, hex and Base64 digests, URL-safe variants, malformed lengths, wrong keys, key rotation, stale and future timestamps, duplicate deliveries, body limits, and framework middleware order.