HTTP Message Signatures (RFC 9421) API Integrity Playbook
Date: 2026-03-29
Category: knowledge
Audience: API platform / security engineering / gateway owners
1) Why this matters in real systems
TLS protects a single transport hop, but many production APIs traverse multiple hops (CDN, WAF, API gateway, service mesh, app). RFC 9421 gives you a way to sign selected HTTP components end-to-end so downstream verifiers can detect tampering even across intermediary boundaries.
This is especially useful when you need:
- message integrity across proxy chains,
- sender authenticity bound to application-managed keys,
- replay-resistant request validation for high-risk endpoints.
2) What RFC 9421 gives you (and what it does not)
It gives you
- A canonicalized signature base over selected HTTP fields + derived components.
- Two transport fields for signature metadata and value:
Signature-InputSignature
- Replay-hardening hooks (
created,expires,nonce) and explicit component coverage control.
It does not give you
- Confidentiality (still use TLS).
- Automatic payload coverage by itself.
- For message content integrity, include and sign
Content-Digest/Repr-Digestfrom RFC 9530.
- For message content integrity, include and sign
- Safe defaults for your application semantics.
- You must define required covered components and verification policy.
3) Protocol facts operators should memorize
- Both fields are required for a valid signature:
Signature-Input(how signature was created)Signature(actual signature bytes)
- Signature labels must be unique in a message and must appear in both fields.
- Covered component list is ordered and must be preserved.
@signature-paramsis required in signature base construction and is the last line of the base.- Derived components (e.g.,
@method,@target-uri,@authority,@path,@query,@status) are first-class and often safer than raw headers. - Trailers are possible for signature fields, but not recommended in most deployments because intermediaries may drop trailers.
4) Coverage policy: the most important design choice
RFC 9421 security guidance is explicit: insufficient coverage means attackers can alter unsigned message parts without invalidating signatures.
Request baseline (good production default)
For state-changing API requests (POST/PUT/PATCH/DELETE), require signature coverage of:
@method@authority@path(or@target-uridepending on architecture)content-digest(when body exists)content-type(if semantics depend on media type)- authorization context identifier header(s) if used by your API contract
Response baseline (if you sign responses)
@statuscontent-digestfor response body integrity (if body present)- request-binding components via
reqparameter when needed (to cryptographically bind response to originating request context)
Practical rule
Only trust signed components. If unsigned components can influence business logic, strip or ignore them before deeper processing.
5) Replay resistance model
Replay risk exists even when signatures verify cryptographically.
Use all three controls together:
created: enforce max age (e.g., 60-300s).expires: enforce hard expiry.nonce: require uniqueness in verification window (store in Redis or similar short-TTL cache keyed by signer + nonce).
Optional active defense:
- Use
Accept-Signaturewith server-chosen nonce to force fresh signatures in challenge-like flows.
6) Payload integrity: pair RFC 9421 with RFC 9530
RFC 9421 intentionally does not directly sign opaque message content bytes. In practice:
- Generate
Content-Digest(orRepr-Digestwhere representation semantics matter). - Include that digest field in covered components.
- Verify digest first (or alongside signature base reconstruction) and fail closed.
This pattern gives you robust metadata + payload integrity together.
7) Algorithm and key policy
RFC 9421 registry starts with active algorithms such as:
ed25519ecdsa-p256-sha256ecdsa-p384-sha384rsa-pss-sha512rsa-v1_5-sha256hmac-sha256
Operational recommendations:
- Prefer asymmetric keys for cross-organization/API-consumer scenarios.
- Use strict allowlists per endpoint or issuer (
alg, key type, key length/curve). - Resolve keys via controlled
keyidmapping with rotation metadata. - Reject algorithm/key mismatches and ambiguous key resolution paths.
- Use HMAC only where shared-secret blast radius is acceptable.
8) Gateway/proxy pitfalls (where deployments fail)
- Signing unstable fields
- Example: intermediaries rewrite
host, normalize paths, or reorder field formatting.
- Example: intermediaries rewrite
- Canonicalization mismatch across stacks
- Different frameworks expose different URI/path abstractions.
- Mixing legacy draft-cavage signatures with RFC 9421 syntax
- Treat as separate schemes; avoid silent dual parsing.
- Trailer dependence
- Signatures in trailers can disappear in transit.
- Signature confusion with multiple labels
- Enforce application-specific
tagand required label policy.
- Enforce application-specific
9) Minimal implementation contract (what to write down in your API security spec)
Define these explicitly per protected endpoint group:
- required covered components,
- required signature parameters (
created,expires,nonce,keyid, optionaltag), - allowed algorithms,
- key discovery/resolution rules,
- clock skew and expiry windows,
- nonce uniqueness scope + retention TTL,
- failure behavior (hard fail, audit fields, response codes),
- migration strategy from any legacy HTTP signature format.
If this contract is undocumented, interop and security drift are almost guaranteed.
10) Rollout sequence (safe production path)
Phase 0 โ discovery
- inventory all hops that can rewrite request elements,
- capture canonical request/response samples per language stack,
- detect legacy signature variants in the wild.
Phase 1 โ verify-only shadow mode
- validate incoming signatures without enforcement,
- emit structured reason codes (missing component, expired, bad nonce, key not found, base mismatch).
Phase 2 โ soft enforcement
- enforce on low-risk routes/clients first,
- keep explicit allowlisted bypasses with expiry date.
Phase 3 โ strict enforcement
- require signatures for target operations,
- require digest+signature pairing for body-bearing requests,
- remove legacy bypasses and monitor replay/verification error SLOs.
11) Fast incident runbook
When signature verification failures spike:
- Check system clock skew/NTP drift first.
- Inspect recent key rotations and
keyidmapping updates. - Diff canonicalization behavior across gateway/app versions.
- Separate replay failures (nonce reuse) from cryptographic failures.
- Check if a proxy update changed path/authority normalization.
- If emergency bypass is required, scope tightly by route+principal+TTL and record incident justification.
12) Example header shape (illustrative)
Signature-Input: sig1=("@method" "@authority" "@path" "content-digest");created=1711692000;expires=1711692060;nonce="n-7f4a";keyid="client-key-42";alg="ed25519";tag="payments-v1"
Signature: sig1=:Base64EncodedSignatureBytes:
(Exact covered components and parameter policy must be application-defined.)
References
- RFC 9421 โ HTTP Message Signatures
https://www.rfc-editor.org/info/rfc9421 - RFC 9530 โ Digest Fields
https://www.rfc-editor.org/info/rfc9530 - RFC 8941 โ Structured Field Values for HTTP
https://www.rfc-editor.org/info/rfc8941 - RFC 9110 โ HTTP Semantics
https://www.rfc-editor.org/info/rfc9110