Skip to content

Flower Shop verify_signature accepts every request and its docstring describes HMAC — spec requires RFC 9421 asymmetric signatures #121

Description

@vishkaty

The Python Flower Shop server does not actually verify request signatures, and its placeholder describes the wrong mechanism.

rest/python/server/dependencies.py (main @ ebb4935), lines 109-127:

async def verify_signature(
  request_signature: str = Header(..., alias="Request-Signature"),
) -> None:
  """Verify the request signature.

  Note: This is a placeholder implementation that bypasses validation if the
  signature is "test". A real implementation would verify the HMAC-SHA256
  signature of the request body.
  ...
  """
  if request_signature == "test":
    return
  # In sample implementation, we don't enforce signature validation
  return

Two problems:

  1. It verifies nothing — every request is accepted, and it reads a bespoke Request-Signature header that isn't part of the protocol.
  2. The docstring points implementers the wrong way. It describes HMAC-SHA256, but signatures.md mandates asymmetric signatures: RFC 9421 HTTP Message Signatures (Signature/Signature-Input), an RFC 9530 Content-Digest over the raw body, ES256 as the MUST-verify baseline in fixed-width raw r||s (explicitly not ASN.1/DER), and signer-key discovery from the UCP-Agent profile's signing_keys. A newcomer following this sample builds HMAC and a Request-Signature header, neither of which interoperates.

Since this is the reference server, it's the natural place to show the signature layer working end to end.

Would you accept a PR that replaces the stub with a real RFC 9421 verifier (and has the demo client sign)? I have one ready and would value your view on the approach before opening it. It is designed to change nothing by default:

  • Verification is real but enforcement is opt-in (a --require_signatures flag, default off). With it off, a present signature is verified and the result logged, but unsigned or invalid requests are still accepted — so existing clients and the official conformance suite are unaffected (no profile fetch happens unless a Signature-Input header is present).
  • The bespoke Request-Signature header stays accepted (optional).
  • ES256 (raw r||s) + Ed25519, the RFC 9421 coverage gate, SSRF-guarded profile fetch (with a localhost carve-out flag for demos), and the spec's error codes.
  • The demo client signs by default with an ephemeral key it publishes from a small local profile server, so the full sign-then-verify loop runs in the happy path.
  • Scope is inbound request verification + client signing; webhook and response signing would follow in a second PR (the spec's "webhooks MUST be signed").

The implementation is built and tested — correctness anchored to the RFC 9421 Appendix B and RFC 9530 test vectors, an explicit DER-must-fail check, and a differential cross-check against an independent RFC 9421 library; ~58 new tests; the official conformance suite still passes 13/13 with it applied.

Branch: https://github.com/vishkaty/samples/tree/feat/rfc9421-signatures — happy to open the PR whenever you'd like.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions