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

2.8 KiB

cose-key

Purpose

Decodes and encodes RFC 9052 §7 COSE_Key structures. The decoder maps an RFC-encoded CBOR map onto a typed discriminated union (Ec2Key | OkpKey | RsaKey | SymmetricKey); the encoder reverses the mapping with deterministic encoding so two keys with identical fields always produce byte-identical output. WebAuthn attestation public keys, COSE_Sign1 signing keys, and CWT verification keys all flow through this module.

Features

  • Discriminated union by kty — TypeScript narrows on key.kty === "EC2" etc. without explicit casts.
  • Per-key-type field validation: EC2 (crv + x + y + optional d), OKP (crv + x + optional d), RSA (n + e + optional d/p/q/ dP/dQ/qInv), Symmetric (k).
  • Common fields (alg, kid, key_ops, baseIV) parsed once and applied uniformly across all key types.
  • Throws CborError(UNEXPECTED_TYPE) for malformed maps, unknown labels, wrong inner types, and missing required fields.
  • Encoder uses RFC 8949 §4.2 deterministic encoding so the byte output is stable across runs — required for COSE structures that include the key bytes in signed/verified payloads.

Usage: Basic Example

import { decodeCoseKey, encodeCoseKey } from "@suaveplan/cbor/cose";

const key = decodeCoseKey(bytes);
if (key.kty === "EC2") {
  console.log("ES256 public key", key.x, key.y);
}
const wire = encodeCoseKey(key);

Usage: Advanced Example

import { decodeCoseKey } from "@suaveplan/cbor/cose";
import { coseAlgToCryptoAlg } from "@suaveplan/cbor/cose";

// WebAuthn attestation flow
const attestationKey = decodeCoseKey(authData.credentialPublicKey);
if (attestationKey.kty !== "EC2") {
  throw new Error("expected EC2 attestation key");
}
const cryptoAlg = coseAlgToCryptoAlg(attestationKey.alg ?? "ES256");
// Hand off to @suaveplan/crypto-curve to verify the signature.

API Reference

  • decodeCoseKey(bytes: Uint8Array): CoseKey — decode a CBOR-encoded COSE_Key byte string into the typed union. Throws CborError for any structural defect.
  • encodeCoseKey(key: CoseKey): Uint8Array — deterministic-encode the key.
  • See cose.types.ts for CoseKey, Ec2Key, OkpKey, RsaKey, SymmetricKey, CoseAlg, CoseCurve, CoseKeyOp.

Implementation Notes

The decoder tolerates extra map entries — RFC 9052 §7.1 explicitly permits forward-compatible additions, and rejecting unknown labels would break forward compatibility. The encoder, by contrast, emits only the fields defined in the typed shape so it cannot accidentally leak extension data that was never modelled. Common fields are read once into a small CommonOut record and spread into every key shape — this avoids drift between the four per-kty readers when a new common field is added in the future.