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:
- It verifies nothing — every request is accepted, and it reads a bespoke
Request-Signature header that isn't part of the protocol.
- 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.
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:Two problems:
Request-Signatureheader that isn't part of the protocol.signatures.mdmandates asymmetric signatures: RFC 9421 HTTP Message Signatures (Signature/Signature-Input), an RFC 9530Content-Digestover the raw body,ES256as the MUST-verify baseline in fixed-width rawr||s(explicitly not ASN.1/DER), and signer-key discovery from theUCP-Agentprofile'ssigning_keys. A newcomer following this sample builds HMAC and aRequest-Signatureheader, 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:
--require_signaturesflag, 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 aSignature-Inputheader is present).Request-Signatureheader stays accepted (optional).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 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.