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 onkey.kty === "EC2"etc. without explicit casts. - Per-key-type field validation: EC2 (
crv+x+y+ optionald), OKP (crv+x+ optionald), RSA (n+e+ optionald/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-encodedCOSE_Keybyte string into the typed union. ThrowsCborErrorfor any structural defect.encodeCoseKey(key: CoseKey): Uint8Array— deterministic-encode the key.- See
cose.types.tsforCoseKey,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.