Initial Commit
This commit is contained in:
60
packages/foundation/flow/cbor/src/cose/sign1.md
Normal file
60
packages/foundation/flow/cbor/src/cose/sign1.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# `sign1`
|
||||
|
||||
## Purpose
|
||||
|
||||
`COSE_Sign1` (RFC 9052 §4.2) — single-signer COSE message in CBOR tag 18.
|
||||
WebAuthn attestation, COSE-signed firmware, and CWT signature flows all
|
||||
land here. This module ships the encode/decode/verify triple plus a typed
|
||||
`CoseSign1` view.
|
||||
|
||||
## Features
|
||||
|
||||
- `encodeCoseSign1` produces both tagged (default) and tagless wire forms.
|
||||
- `decodeCoseSign1` accepts either form transparently.
|
||||
- `verifyCoseSign1` wires `@suaveplan/crypto-curve` (ES256, EdDSA) and uses
|
||||
the canonical `Sig_structure1` from `sig-structure.ts`.
|
||||
- Public-key argument is polymorphic: typed `Ec2Key` / `OkpKey` (the helper
|
||||
builds the wire-level point form internally) OR a raw byte-string key for
|
||||
callers that already have a primitive shape.
|
||||
- `null` payload (detached signature) decodes correctly; verify rejects with
|
||||
a clear "not yet supported" error.
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
import { decodeCoseSign1, encodeCoseSign1, verifyCoseSign1 } from "@suaveplan/cbor/cose";
|
||||
import { buildSign1Structure } from "@suaveplan/cbor/cose";
|
||||
import * as ed25519 from "@suaveplan/crypto-curve/ed25519";
|
||||
|
||||
// Sign
|
||||
const draft = decodeCoseSign1(
|
||||
encodeCoseSign1({ protectedHeader: { alg: "EdDSA" }, payload, signature: new Uint8Array(64) }),
|
||||
);
|
||||
const tbs = buildSign1Structure(draft.protectedRaw, new Uint8Array(0), payload);
|
||||
const sig = ed25519.sign(tbs, privateKey);
|
||||
const wire = encodeCoseSign1({ protectedHeader: { alg: "EdDSA" }, payload, signature: sig });
|
||||
|
||||
// Verify
|
||||
const msg = decodeCoseSign1(wire);
|
||||
const ok = verifyCoseSign1(msg, publicKey);
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
- `encodeCoseSign1(input: EncodeCoseSign1Input): Uint8Array`
|
||||
- `decodeCoseSign1(bytes: Uint8Array): CoseSign1`
|
||||
- `verifyCoseSign1(msg: CoseSign1, key: Ec2Key | OkpKey | Uint8Array, options?): boolean`
|
||||
- `COSE_SIGN1_TAG = 18`
|
||||
|
||||
`CoseSign1` carries `protectedRaw` (the serialised inner-map bytes) so
|
||||
callers can recompute Sig_structure1 verbatim — critical when verifying a
|
||||
message they did not produce.
|
||||
|
||||
## Notes
|
||||
|
||||
ES256 uses noble-p256's compact `(r||s)` signature form and consumes a
|
||||
SHA-256 digest of the TBS bytes (matches RFC 9053 §2.1). EdDSA verifies
|
||||
the raw TBS bytes directly per RFC 8032 §5.1.7. ES384 and ES512 throw
|
||||
"not implemented" today — `@suaveplan/crypto-curve` does not ship the P-384
|
||||
or P-521 primitives yet, and the bridge surfaces the gap rather than
|
||||
silently falling back.
|
||||
Reference in New Issue
Block a user