Initial Commit
This commit is contained in:
58
packages/foundation/flow/cbor/src/cose/sign.md
Normal file
58
packages/foundation/flow/cbor/src/cose/sign.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# `sign`
|
||||
|
||||
## Purpose
|
||||
|
||||
`COSE_Sign` (RFC 9052 §4.1) — multi-signer COSE message in CBOR tag 98.
|
||||
Use when a payload needs to be co-signed by multiple parties (e.g. multi-
|
||||
party attestation, escrowed signing). Each signer carries its own protected
|
||||
header (typically with its own `alg`) and produces an independent signature
|
||||
over the canonical `Sig_structure` for context `"Signature"`.
|
||||
|
||||
## Features
|
||||
|
||||
- `encodeCoseSign` builds the 4-tuple `[bodyProtected, bodyUnprotected,
|
||||
payload, signatures]` with deterministic encoding and per-signer
|
||||
`[sigProtected, sigUnprotected, signature]` triples.
|
||||
- `decodeCoseSign` recovers the typed `CoseSign` view, including
|
||||
`protectedRaw` byte strings on every level needed to recompute the
|
||||
five-element `Sig_structure`.
|
||||
- `verifyCoseSignAny` walks the signers in order against a 1:1 candidate-
|
||||
key array. Returns the first index whose signature verifies, or `-1` on
|
||||
no match. Caller decides whether one valid signer is enough or whether all
|
||||
signers must verify (loop the array).
|
||||
- Currently dispatches to ES256 + EdDSA via `@suaveplan/crypto-curve`;
|
||||
unsupported algs return `false` (signer is skipped) rather than throwing
|
||||
so the helper can scan a heterogeneous array without aborting.
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
import { encodeCoseSign, decodeCoseSign, verifyCoseSignAny } from "@suaveplan/cbor/cose";
|
||||
|
||||
const wire = encodeCoseSign({
|
||||
payload,
|
||||
signatures: [
|
||||
{ protectedHeader: { alg: "ES256" }, signature: sig1 },
|
||||
{ protectedHeader: { alg: "EdDSA" }, signature: sig2 },
|
||||
],
|
||||
});
|
||||
|
||||
const msg = decodeCoseSign(wire);
|
||||
const matchIndex = verifyCoseSignAny(msg, [keyA, keyB]);
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
- `encodeCoseSign(input)` / `decodeCoseSign(bytes)`.
|
||||
- `verifyCoseSignAny(msg, keys, options?): number` — returns matching index
|
||||
or `-1`. Length mismatch between `keys` and `msg.signatures` throws
|
||||
`UNEXPECTED_TYPE`.
|
||||
- `COSE_SIGN_TAG = 98`.
|
||||
|
||||
## Notes
|
||||
|
||||
Sig_structure for multi-signer is 5-element:
|
||||
`[context, body_protected, sign_protected, external_aad, payload]` — the
|
||||
extra `sign_protected` discriminates the signer's own protected header from
|
||||
the message-wide one. Both must be the SERIALISED byte strings, not the
|
||||
inner maps.
|
||||
Reference in New Issue
Block a user