encoding.cose: add COSE (RFC 9052) and CWT (RFC 8392) modules#27111
encoding.cose: add COSE (RFC 9052) and CWT (RFC 8392) modules#27111davlgd wants to merge 3 commits into
Conversation
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 60bfca67ea
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b432f50b4b
ℹ️ 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".
| } | ||
| } | ||
|
|
||
| protected := parse_protected(u.unpack_bytes()!)! |
There was a problem hiding this comment.
Preserve protected bstr bytes when decoding
When this decoder consumes the protected bstr it only stores parsed Headers, and verification later calls encode_protected() to rebuild it. For a decoded COSE_Sign1 whose protected header was signed with a legal non-canonical byte representation (for example a different map key order or length encoding), RFC 9052 requires the Sig_structure to use the original protected bytes; reserializing changes the bytes under verification and rejects otherwise valid third-party messages. Store the raw protected bstr from decode (normalizing only the empty-map special case) and use it in Sign/Sign1/Mac/Mac0 verification.
Useful? React with 👍 / 👎.
This PR adds two complementary modules to the standard library:
encoding.cose— CBOR Object Signing and Encryption, signing + MAC subset of RFC 9052 and RFC 9053.encoding.cwt— CBOR Web Tokens (RFC 8392) built on top ofcose.Both modules sit alongside
encoding.cbor(merged in #27018) and use its codec under the hood. No new C code, no new third-party crypto: everything is built on the primitives already invlib/crypto(ecdsa,ed25519,hmac,sha256,sha512).Why
CBOR is everywhere: WebAuthn / FIDO2 attestations, IETF SUIT (firmware updates over LWM2M), Matter (smart home), CoAP / OSCORE, EDHOC, the European Digital Identity Wallet… All of them serialise their tokens as COSE or CWT.
What's covered
COSE_Sign1COSE_SignCOSE_Mac0COSE_MacES256ES384ES512EdDSAHMAC 256/64HMAC 256/256HMAC 384/384HMAC 512/512CWT models the seven RFC 8392 §3 standard claims (
iss,sub,aud,exp,nbf,iat,cti) plus pass-through for application claims, and handles the optional outer CBOR tag 61 wrapper.Module surface
A complete example program lives at
examples/cose_cwt.v.Conformance / test vectors
The
cose-wg/Examplesrepository is the canonical interop corpus. Its relevant fixtures are vendored undervlib/encoding/cose/tests/cose_wg/andvlib/encoding/cwt/tests/rfc8392/, and run as part ofv test. For deterministic algorithms (EdDSA, all HMAC variants) the V output is validated byte-for-byte; for ECDSA (randomised signatures) each reference message is verified. The negative*-fail-*vectors exercise the verifier's rejection paths against externally produced bad messages.ecdsa-sig-01ecdsa-sig-02ecdsa-sig-03eddsa-sig-01eddsa-01sign1-fail-01..04sign1-pass-02HMac-01HMac-04HMac-05HMac-enc-01HMac-enc-02HMac-enc-03HMac-enc-05In addition to the public corpus:
ec_signature_test.v— DER ↔ R‖S conversion edge cases (leading zeros, MSB-set sign disambiguation, P-521 long-form lengths).structures_test.v—Sig_structure/MAC_structurebyte output matches RFC 9052 §4.4 / §6.3.headers_test.v— canonical key sorting (RFC 8949 §4.2.1), empty-protected-as-zero-length-bstr rule, unknown-label preservation.sign1_test.v/sign_test.v/mac0_test.v/mac_test.v— sign/verify roundtrip per algorithm; tampered-payload and wrong-key rejection paths; detached-payload and external-AAD modes; sanity caps on signer/recipient array counts; unknowncritlabel rejection per RFC 9052 §3.1.cwt_test.v— Claims Set encoding, theaudtstr-vs-array form rule from RFC 7519/8392, optional tag-61 wrapper, RFC 8392 A.3 and A.4 reproduction,nbf/expvalidity-window helper.I've also tested these modules against lib in other languages to check interop.
Out of scope (deliberate)
COSE_Encrypt0/COSE_Encrypt) — needs AES-GCM, AES-CCM, ChaCha20-Poly1305 invlib/crypto, which is a separate effort. Adding the message types later is purely additive.PS256/384/512andRS256/384/512(legacy). Adding them is mechanical ifvlib/cryptoships RSA-PSS, but the demand is small relative to ECDSA + EdDSA.