net.http.signature: add HTTP Message Signatures (RFC 9421) module#27113
Open
davlgd wants to merge 4 commits into
Open
net.http.signature: add HTTP Message Signatures (RFC 9421) module#27113davlgd wants to merge 4 commits into
davlgd wants to merge 4 commits into
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b79a1623db
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Member
|
vfmt |
f3e774d to
f9dea48
Compare
Contributor
Author
Sorry I missed it before the last push. It's fixed. |
Collaborator
|
Run |
Member
|
Contributor
Author
|
So I should add |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds
vlib/net/http/signature— a pure-V implementation of RFC 9421 (HTTP Message Signatures). Sign and verify HTTP requests and responses with the four algorithms backed byvlib/crypto:hmac-sha256,ecdsa-p256-sha256,ecdsa-p384-sha384,ed25519.No new C code, no new third-party crypto: everything sits on
vlib/crypto(ecdsa,ed25519,hmac,sha256) andvlib/crypto/pemforKey.from_pem.Why
RFC 9421 was published in February 2024. It supersedes the long-running Cavage drafts (
draft-cavage-http-signatures-*) that ActivityPub / Mastodon-style federation has been using in non-interoperable variants for years, and gives the ecosystem a single normative spec with stable header names and a stable signature-base format. The signed-request model authenticates HTTP messages end-to-end across TLS terminators and lets multiple per-hop signatures (client → proxy → backend) coexist on the same request. The new IETF Web Bot Auth draft is built directly on top of it. Withvlib/net/httpalready in the stdlib, V apps could not produce or verify RFC 9421 signatures until now.What's covered
hmac-sha256ecdsa-p256-sha256ecdsa-p384-sha384ed25519The RFC 9421 §2.2 derived components implemented are
@method,@target-uri,@authority,@scheme,@request-target,@path,@query,@status— the@query-paramselector (§2.2.8) is the only one missing and is called out below as deferred. Plain HTTP fields are matched by lowercased name, multi-value joined as", ", OWS trimmed (RFC 9421 §2.1). Optional outer behaviours: multiple co-existing signatures merged into a single Structured Field per RFC 8941 §3.2;expiresenforced when the caller passesnow_unix > 0.rsa-pss-sha512andrsa-v1_5-sha256are intentionally out of scope —vlib/cryptodoes not yet ship an RSA implementation. Adding them is mechanical once it does.@query-param,sf/key/bsparameter handling are deferred to a follow-up PR.Module surface
Key.from_pemaccepts the canonical PKCS#8 / SPKI / SEC1 PEM blocksopenssl genpkeyand friends produce; the raw-coordinate constructors (Key.ed25519_private(seed),Key.ecdsa_p256_public(x, y), …) remain for callers that have JWK-shaped material.createddefaults totime.now().unix()when omitted, since RFC 9421 §7.2.1 RECOMMENDS it for replay protection.A complete example program lives at
examples/http_signature.v.Conformance / test vectors
RFC 9421 Appendix B vectors are vendored under
vlib/net/http/signature/tests/rfc9421/and exercised byrfc9421_test.v:hmac-sha256ed25519ecdsa-p256-sha256Both byte-exact tests reproduce the RFC reference signature down to the last base64 character; the ECDSA case verifies the reference signature and adds an independent sign-then-verify roundtrip.
In addition to the public corpus:
http_message_test.v— sign/verify roundtrips for HMAC, Ed25519, ECDSA P-256 (RFC key) and ECDSA P-384 (fresh keypair viaecdsa.generate_key); tampered-URL rejection; missing-header rejection;expiresenforcement; two-signature coexistence;algmismatch rejection; label grammar (Structured Field key form).structured_field_test.v— Inner List + parameter serialisation pinned (("@method" "host");created=N;keyid="…"byte-for-byte), escape rules for quoted strings, multi-entry / single-entry parsing, rawsignature_params_valuepreservation, and non-canonical wire-order verification — proves the verifier replays the wire param substring verbatim instead of re-serialising in a fixed canonical order, which is what makes interop with stacks that emit;keyid=…;created=…(instead of the inverse) work.key_test.v—Key.from_pemround-trip with the RFC §B.1.3 P-256 PEM and §B.1.4 Ed25519 PEM, byte-exact RFC §B.2.6 signature reproduction viaKey.from_pem, and rejection of unsupported PEM block types (RSA PRIVATE KEYetc).I've also tested these modules against lib in other languages to check interop.
Out of scope (deliberate)
rsa-pss-sha512andrsa-v1_5-sha256need an RSA-PSS implementation invlib/crypto, which is a separate effort. Adding them is purely additive once it lands.@query-paramderived component (RFC 9421 §2.2.8) — defers per-parameter selection rules; rare in practice and easy to add later.sf,key,bsfrom §2.1.x) — used when signing structured-field values themselves; out of v1 to keep the parser narrow.Components.fieldsalready supports —Content-Digestis signed as a regular header field; computing the digest itself stays the caller's concern (matches what every other RFC 9421 stack does).