Files
skills/docs/foundation/flow/cbor/src/cose/mac.md
2026-05-29 08:20:56 +01:00

2.0 KiB

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

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.