Files
2026-05-27 23:29:53 +01:00

104 lines
4.0 KiB
Markdown

# `@suaveplan/crypto-curve` — Add P-384 (`secp384r1`) and P-521 (`secp521r1`) primitives
**Package**: `@suaveplan/crypto-curve` (extension)
**Status**: PROPOSED
**Type**: capability-extension
**Date**: 2026-05-10
**Tier**: universal
## Why
`@suaveplan/cbor` ships RFC 9052 COSE_Sign1 verify but the ES384 / ES512
algorithm branches throw `CborError(UNEXPECTED_TYPE)` with the message
*"not implemented in @suaveplan/crypto-curve yet"* because the curve
primitives were not previously exposed. Downstream consumers (WebAuthn
attestation, federation tokens, FIDO2 device certificates) need both
algorithms to interoperate with mainstream issuers — Apple's WebAuthn
attestation, in particular, signs with ES384 in some configurations.
`@noble/curves@1.9.7` (already installed across the workspace) exposes
`p384` and `p521` with the same surface contract as `p256`. The work is
purely additive — mirroring the existing `p256` per-primitive layout for
two more curves and threading them through to the COSE verifier.
## What changes
### New primitives in `@suaveplan/crypto-curve`
#### P-384
- ADDED: `primitives/p384/p384.ts` — re-exports the select layer.
- ADDED: `primitives/p384/p384.select/p384.select.ts` — selector pinned
to the noble implementation (generated forwarder, mirroring p256).
- ADDED: `primitives/p384/impl/p384.noble/p384.noble.ts` — noble-backed
`getPublicKey`, `sign`, `verify`, `randomPrivateKey`.
- ADDED: `primitives/p384/impl/p384.native/p384.native.ts` —
`PrimitiveNotImplemented` stubs matching the p256 native pattern.
#### P-521
- ADDED: `primitives/p521/p521.ts` and full mirror of the p384 layout
(`p521.select`, `impl/p521.noble`, `impl/p521.native`).
#### Barrel + subpath exports
- ADDED: `export * as p384 from "./primitives/p384/p384.js"` to root barrel.
- ADDED: `export * as p521 from "./primitives/p521/p521.js"` to root barrel.
- ADDED: `./p384` and `./p521` subpath exports in `package.json`.
- ADDED: corresponding entries in `vite.config.ts` external list (so
consumers can tree-shake to the individual primitive).
### COSE wiring in `@suaveplan/cbor`
- MODIFIED: `verifyCoseSign1` switch — `ES384` and `ES512` branches call
`p384.verify(sig, sha384(tbs), pk)` and `p521.verify(sig, sha512(tbs), pk)`
respectively (replacing the `UNEXPECTED_TYPE` placeholder throws).
- MODIFIED: `ec2ToCompressedPoint` — generalised to accept coordinate
length (32 / 48 / 66) so the same helper compresses P-256 / P-384 / P-521.
### Dependencies
No new dependencies. `@noble/curves@1.9.7` is the catalog-pinned version
that ships both `p384` and `p521` subpath exports.
## Out of scope
- WebCrypto-native impls — the existing `p256.native` stub pattern
(`PrimitiveNotImplemented`) is preserved for both new curves; an opt-in
WebCrypto path lands in a separate change when needed.
- COSE Sign1 / Mac0 / Encrypt0 surfaces beyond the alg switch — already
wired generically and need no changes.
## Source mapping
| Requirement | Source | Notes |
|---|---|---|
| P-384 ECDSA | FIPS 186-4 §6 + NIST SP 800-186 | `@noble/curves/p384` |
| P-521 ECDSA | FIPS 186-4 §6 + NIST SP 800-186 | `@noble/curves/p521` |
| COSE ES384 / ES512 | RFC 9053 §2.1 | Already mapped in `alg-map.ts` |
| Per-primitive selector layout | Existing crypto-curve convention | mirrors p256 |
## Verification approach
- `packages/crypto/crypto-curve/src/primitives/p384/p384.test.ts` — noble
- native impl: sign / verify round-trip, signature length, tampered-sig
rejection, native `PrimitiveNotImplemented` throw.
- `packages/crypto/crypto-curve/src/primitives/p521/p521.test.ts` — same.
- `packages/vault/cbor/src/cose/sign1.test.ts` — extend to cover ES384
and ES512 round-trip via the new primitives.
## Migration impact
Additive. No existing consumers break — the deferred branches in cbor
were already throwing.
## Impact
### Affected dependents
`@suaveplan/cbor` — ES384 / ES512 paths become operational; previously
threw `UNEXPECTED_TYPE`.
For all other packages: no behavioural change. The new primitives are
opt-in subpath imports.