# `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 ```ts 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 ```ts 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.