Files
skills/docs/identity/auth/webauthn/src/parser/cose-key.md
2026-05-29 08:20:56 +01:00

3.2 KiB

COSE_Key parser

Purpose

Decodes a COSE_Key byte string (RFC 9052 §7) into the typed CoseKey discriminated union supplied by @suaveplan/cbor/cose. The WebAuthn package never re-implements CBOR — the parser is a thin error-translation wrapper plus an inline parseCoseKeyOne helper that the authenticator-data parser uses to extract the embedded credential public key without knowing its CBOR-encoded length up-front.

Features

  • Strict-mode delegation to @suaveplan/cbor/cose#decodeCoseKey for fully-sized buffers.
  • parseCoseKeyOne for inline streams: uses @suaveplan/cbor#decodeOne to compute the consumed-byte count, slices the head, and re-validates via decodeCoseKey.
  • Cause-chain preservation — every CborError raised by @suaveplan/cbor is captured on .cause of the surfaced WebAuthnError(MALFORMED_RESPONSE).
  • resolveCoseAlg(label) maps numeric COSE alg labels to the named identifiers (ES256, ES384, ES512, EdDSA, RS256) the assertion verifier dispatches on. Unknown labels throw WEBAUTHN.SIGNATURE_INVALID — an unverifiable algorithm cannot be accepted.

Usage: Basic Example

import { parseCoseKey } from "@suaveplan/webauthn/parser";

const key = parseCoseKey(coseKeyBytes);
if (key.kty === "EC2") {
    console.log(key.crv, key.x.byteLength, key.y.byteLength);
}

Usage: Advanced Example

import {
    parseCoseKeyOne,
    resolveCoseAlg,
} from "@suaveplan/webauthn/parser";

const { key, consumed } = parseCoseKeyOne(authDataAfterPrefix);
const remaining = authDataAfterPrefix.subarray(consumed);
if (key.alg !== undefined) {
    const alg = resolveCoseAlg(coseAlgLabel(key.alg));
    // alg is now "ES256" | "ES384" | ...
}

API Reference

  • parseCoseKey(bytes: Uint8Array): CoseKey — full-buffer decode; throws WEBAUTHN.MALFORMED_RESPONSE on failure.
  • parseCoseKeyOne(bytes: Uint8Array): { key: CoseKey, consumed: number } — inline decode; returns consumed-byte count for cursor advancement.
  • SUPPORTED_COSE_ALG_LABELS — frozen map { ES256: -7, ES384: -35, ES512: -36, EdDSA: -8, RS256: -257 }.
  • SupportedCoseAlg / SupportedCoseAlgLabel — narrowed literal types.
  • resolveCoseAlg(label: number): SupportedCoseAlg — numeric → named; throws WEBAUTHN.SIGNATURE_INVALID on unknown.

Implementation Notes

  • The package supports exactly the five algorithms required by W3C WebAuthn L3 §5.10.5 for the typical authenticator: ES256 / ES384 / ES512 (NIST curves), EdDSA (Ed25519), and RS256 (RSA-PKCS1-v1.5). PS256 is not supported because no production authenticator emits it; consumers that need PS256 can wire a custom assertion verifier via the pluggable registry.
  • parseCoseKeyOne uses decodeOne to learn the encoded length first, then re-decodes via decodeCoseKey so the strict-mode validation in the underlying library runs. The double-decode cost is negligible (microseconds) and keeps the cbor / cose abstraction sealed.
  • resolveCoseAlg throws rather than returning undefined because the caller (verifyAssertion) cannot proceed without knowing the algorithm — surfacing an unsupported alg as a verification failure is the safer default than passing it down to a generic fallback verifier.