Prompt and scope
A payment partner requires proof of the sender and integrity of every HTTP request. Using RFC 9421, design signing and verification and explain covered components, replay defense, key rotation, and proxy rewrites.
RFC 9421 separates signature input, covered HTTP components, and parameters such as created, expires, and nonce. The question tests whether the candidate can make “who signed it” and “which bytes were signed” interoperable, rather than merely hashing a body.
What the interviewer evaluates
Evaluate whether covered components bind request semantics; whether both sides canonicalize the signature base identically; whether time, nonce, and key ID stop replay; how proxies, retries, compression, and tenants affect verification; and whether key publication, revocation, and monitoring are operable.
30-second answer framework
“I would require the method, target path, authority, important business fields, and Content-Digest to be covered, with fixed algorithm, parameter order, and clock tolerance. The server parses Signature-Input, rebuilds the same base, finds the key, verifies the signature, checks created, expires, and a one-use nonce, and only then enters business logic. Versioned key IDs support dual verification and revocation. A proxy may rewrite only uncovered fields; otherwise verification fails.”
Step-by-step deep answer
Step 1: Define the property to prove
A signature proves that a key holder signed selected HTTP components and helps detect tampering. It does not replace TLS, authorization, input validation, or business idempotency. State whether the protocol needs authentication, integrity, or non-repudiation.
Step 2: Select covered components
Cover the method, target path, and authority at minimum. Add content-digest, an idempotency key, tenant ID, or critical business fields as needed. Do not sign one replaceable field or blindly cover headers a legitimate proxy rewrites. Version the component list as part of the protocol.
Step 3: Canonicalize the signature base
Both sides must follow RFC 9421 component identifiers, ordering, parameter encoding, and derived-component rules. The server should rebuild the base from the parsed request and Signature-Input, not guess by concatenating raw header strings. Reject unknown or duplicate critical components.
Step 4: Protect the request content
For requests with a body, compute Content-Digest and include it in the signature. Before verification, hash the received bytes so compression, transcoding, or JSON reformatting cannot silently change content. If a proxy decompresses or re-encodes, define whether signing occurs before or after that transformation.
Step 5: Add time and replay defense
Require created, and when useful require expires and a unique nonce. Check the time window and clock skew, and store used nonces briefly per tenant. Retries of the same business request rely on an idempotency key instead of an unlimited signature lifetime. Passing the time check does not make a write safe to execute twice.
Step 6: Discover and rotate keys
The key ID in Signature-Input selects a public key from a controlled directory or JWKS-like endpoint. Cache versioned results. During rotation, publish the new key, allow old and new keys for a bounded overlap, then revoke the old key after traffic drains. Keep private keys at signing endpoints and never log key material or a complete signature base.
Step 7: Define proxy and retry boundaries
Document which layers may add tracing fields, retry requests, or change authority. An unauthorized rewrite of a covered component must fail verification. A proxy cannot copy a one-use nonce or forward a signature to another target. Do not run writes or expensive business logic before verification.
Step 8: Operate failures safely
Record key ID, signature version, failure class, clock skew, nonce collisions, missing components, and proxy source with a request ID. Give partners actionable classes such as expired, unknown key, or digest mismatch, without returning key material or detailed bases that help attackers probe.
Trade-offs and boundaries
Asymmetric signatures versus shared keys
Asymmetric keys simplify multi-party verification and independent revocation but require more infrastructure. Shared HMAC is cheaper, yet every verifier can forge requests; use it only when the trust boundary is explicit.
Coverage versus proxy compatibility
More coverage gives stronger integrity but can fail when a gateway legitimately changes a field. Put the proxy contract in the protocol and re-sign at a boundary when needed instead of silently weakening verification.
Tight windows versus offline retries
Short windows reduce replay risk but require clock synchronization and fast retry. Offline clients should request a new signature rather than reuse a long-lived one; the server may apply bounded partner-specific tolerance.
Failure drills and evolution
A proxy changes the path
Rewrite the path or authority in a test proxy and confirm verification fails before business logic. Allowed tracing-header changes must not affect the signature.
An old request is replayed
Send the same signature and nonce twice and verify the second attempt is rejected. Use a new nonce with the same idempotency key and verify business-layer idempotency.
A key rotates
Publish old and new keys together and verify policy-compliant signatures. After revocation, old signatures must fail and stale caches must not keep them valid indefinitely.
Common mistakes and follow-ups
Mistake 1: Signing only a body hash
Ask whether the signature can be copied to another path or method; covered target components must bind request meaning.
Mistake 2: Assuming HTTPS is sufficient
Ask how the original sender and content are authenticated after an internal TLS-terminating proxy.
Mistake 3: Ignoring nonce and time
Ask whether a captured payment request can be replayed during its validity window; combine time, nonce, and idempotency.
Mistake 4: Deleting the old key immediately
Ask how in-flight requests and multi-region caches overlap; dual-verify before revocation.
Mistake 5: Returning signature-base details on failure
Ask how partners debug without exposing key material, signed input, or internal proxy details.
Extended follow-ups and reference answers
Why include Content-Digest in the signature?
The digest represents body bytes; the signature binds that digest to method, target, and other components so a valid digest cannot be moved to another request.
Should a proxy re-sign after rewriting?
If a rewrite is part of the downstream protocol, the boundary proxy should sign as its own identity. Otherwise it must preserve covered components so the original signature remains verifiable.
How are authentication and authorization different?
Verification proves that a key holder signed the request. Authorization still checks tenant, account, amount, idempotency, and business state; a signature alone cannot authorize execution.