first commit
This commit is contained in:
55
docs/foundation/flow/cbor/src/cose/mac.md
Normal file
55
docs/foundation/flow/cbor/src/cose/mac.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# `mac`
|
||||
|
||||
## Purpose
|
||||
|
||||
`COSE_Mac` (RFC 9052 §6.1) — multi-recipient MAC message in CBOR tag 97.
|
||||
Each recipient gets a wrapped copy of the content-MAC key (CMK); the body
|
||||
itself carries one MAC computed over the payload using the CMK. This module
|
||||
ships encode/decode of the wire shape plus a kid-based recipient lookup.
|
||||
|
||||
## Features
|
||||
|
||||
- `encodeCoseMac` builds the 5-tuple `[bodyProtected, bodyUnprotected,
|
||||
payload, tag, recipients]`. Per-recipient triples
|
||||
`[recipientProtected, recipientUnprotected, encryptedKey]` carry the
|
||||
wrapped-key bytes verbatim — wrap/unwrap is delegated to whatever scheme
|
||||
the recipient header declares (direct, KEK, ECDH-ES, etc.).
|
||||
- `decodeCoseMac` recovers the typed `CoseMac` view. Each recipient lands
|
||||
in `msg.recipients[]` with its own `protectedRaw` byte string ready for
|
||||
any per-recipient verification flow that needs it.
|
||||
- `findRecipientByKid` does a constant-time-ish byte compare over the
|
||||
recipient's `kid` (consulted in protected then unprotected headers).
|
||||
- Empty recipient arrays are rejected — RFC 9052 §6.1 requires at least one.
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
import { encodeCoseMac, decodeCoseMac, findRecipientByKid } from "@suaveplan/cbor/cose";
|
||||
|
||||
const wire = encodeCoseMac({
|
||||
protectedHeader: { alg: "HS256" },
|
||||
payload,
|
||||
tag: macTag,
|
||||
recipients: [
|
||||
{ unprotectedHeader: { kid: kidA }, encryptedKey: wrapped },
|
||||
{ unprotectedHeader: { kid: kidB }, encryptedKey: wrappedB },
|
||||
],
|
||||
});
|
||||
|
||||
const msg = decodeCoseMac(wire);
|
||||
const mine = findRecipientByKid(msg, kidA);
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
- `encodeCoseMac(input)` / `decodeCoseMac(bytes)`.
|
||||
- `findRecipientByKid(msg, kid): CoseRecipient | undefined`.
|
||||
- `COSE_MAC_TAG = 97`.
|
||||
|
||||
## Notes
|
||||
|
||||
The body's `tag` is computed over the canonical `MAC_structure` (RFC 9052
|
||||
§6.3) using the CMK. This module does not implement the wrapping/unwrapping
|
||||
of the CMK to each recipient — that lives one layer up, where the recipient-
|
||||
specific algorithm (`A128KW`, `direct`, `ECDH-ES + A256KW`, …) is dispatched.
|
||||
The helper here gives a typed shape for callers to plug those wraps into.
|
||||
Reference in New Issue
Block a user