Initial Commit
This commit is contained in:
103
openspec/archive/2026-05-10-crypto-curve-p384-p521/proposal.md
Normal file
103
openspec/archive/2026-05-10-crypto-curve-p384-p521/proposal.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# `@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.
|
||||
Reference in New Issue
Block a user