first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,70 @@
# `jwk`
## Purpose
Round-trip converter between RFC 9052 `COSE_Key` instances and RFC 7517 JWK
shapes. WebAuthn attestation flows often need to hand a public key to a
WebCrypto-style verifier that consumes JWK; conversely, server-issued
JWK-formatted keys may need to land in a CBOR-encoded COSE structure. The
two conversions preserve every field that has a defined cross-format
mapping.
## Features
- `coseKeyToJwk(key)` — accepts any `CoseKey` discriminant (EC2, OKP, RSA,
Symmetric) and emits the matching JWK (`EC`, `OKP`, `RSA`, `oct`).
- `jwkToCoseKey(jwk)` — reverse mapping with full byte-string round-trip.
- Byte-string fields use RFC 4648 §5 base64url encoding without padding.
- `kid` is treated as UTF-8 bytes on the COSE side and a string on the JWK
side; conversion is lossy only if a non-UTF-8 kid is in play (rare, and
RFC 9052 §3.1 documents the convention).
- `alg` round-trips through a fixed COSE↔JWK label table so the typed
algorithm lands consistently on either side.
## Usage: Basic Example
```ts
import { coseKeyToJwk, jwkToCoseKey } from "@suaveplan/cbor/cose";
const jwk = coseKeyToJwk(coseKey);
const back = jwkToCoseKey(jwk);
```
## Usage: Advanced Example
```ts
import { decodeCoseKey, coseKeyToJwk } from "@suaveplan/cbor/cose";
// Attestation key from CTAP2
const cose = decodeCoseKey(attestationKeyBytes);
const jwk = coseKeyToJwk(cose);
// Hand off to WebCrypto
const cryptoKey = await crypto.subtle.importKey(
"jwk",
jwk,
{ name: "ECDSA", namedCurve: "P-256" },
false,
["verify"],
);
```
## API Reference
- `coseKeyToJwk(key: CoseKey): Jwk` — discriminator-aware conversion to JWK.
- `jwkToCoseKey(jwk: Jwk): CoseKey` — reverse conversion.
- `Jwk = Ec2Jwk | OkpJwk | RsaJwk | SymmetricJwk` (typed union).
Throws `CborError(UNEXPECTED_TYPE)` for incompatible curves (EC2 with a
non-P curve, OKP with a non-Ed/X curve), unknown JWK `alg` strings, and
malformed base64url input via the underlying `atob`.
## Implementation Notes
base64url encoding is implemented inline with `btoa`/`atob` rather than
pulling in `@suaveplan/crypto-utils` so this module stays free of crypto
deps. Standard base64 padding (`=`) is stripped on output and re-padded on
input — the RFC 4648 §5 spec allows omission of padding and major JWK
producers do strip it. RSA JWKs use lowercase param names (`dp`, `dq`, `qi`)
per RFC 7518 §6.3.2; COSE_Key uses the labels from RFC 8230 §4 (`-6`, `-7`,
`-8`). The bridge preserves the field-by-field correspondence.