5.0 KiB
Capability Spec Delta: crypto-curve (crypto-curve-p384-p521)
Package: @suaveplan/crypto-curve
Status: PROPOSED — additive delta; folded into canonical spec on archive.
ADDED Requirements
Requirement: NIST P-384 (secp384r1) ECDSA primitive
The package SHALL export a p384 namespace from the root barrel and a
matching ./p384 subpath export, providing getPublicKey, sign,
verify, and randomPrivateKey. Private keys SHALL be 48 bytes,
compressed public keys SHALL be 49 bytes, and compact ECDSA signatures
SHALL be 96 bytes. Callers SHALL pre-hash messages; the module operates
on digests. The selector SHALL forward to the noble-backed implementation
by default; the native implementation SHALL throw
PrimitiveNotImplemented("p384") until a WebCrypto bridge lands.
Scenario: P-384 sign + verify round-trip
- GIVEN a freshly-generated P-384 private key and 48-byte digest
- WHEN
verify(sign(digest, sk), digest, getPublicKey(sk))is computed - THEN the result is
true
Scenario: P-384 verify rejects tampered signature
- WHEN a single byte of a valid P-384 signature is XORed with
0xff - THEN
verifyreturnsfalse
Scenario: P-384 verify returns false on malformed inputs
- WHEN
verifyis invoked with non-Uint8Arrayinputs or empty buffers - THEN the call returns
false(does not throw)
Verified by:
packages/crypto/crypto-curve/src/primitives/p384/p384.test.ts::"sign + verify round-trips"
AND …::"verify returns false for tampered signature (no throw)"
AND …::"verify returns false for bogus input (caught)"
Requirement: NIST P-521 (secp521r1) ECDSA primitive
The package SHALL export a p521 namespace from the root barrel and a
matching ./p521 subpath export, providing getPublicKey, sign,
verify, and randomPrivateKey. Private keys SHALL be 66 bytes (521-bit
scalar left-padded to a byte boundary), compressed public keys SHALL be
67 bytes, and compact ECDSA signatures SHALL be 132 bytes. Callers SHALL
pre-hash messages; the module operates on digests. The selector SHALL
forward to the noble-backed implementation by default; the native
implementation SHALL throw PrimitiveNotImplemented("p521").
Scenario: P-521 sign + verify round-trip
- GIVEN a freshly-generated P-521 private key and 64-byte digest
- WHEN
verify(sign(digest, sk), digest, getPublicKey(sk))is computed - THEN the result is
trueand the signature is 132 bytes long
Scenario: P-521 verify rejects tampered signature
- WHEN a single byte of a valid P-521 signature is XORed with
0xff - THEN
verifyreturnsfalse
Scenario: P-521 verify returns false on malformed inputs
- WHEN
verifyis invoked with non-Uint8Arrayinputs or empty buffers - THEN the call returns
false(does not throw)
Verified by:
packages/crypto/crypto-curve/src/primitives/p521/p521.test.ts::"sign + verify round-trips"
AND …::"verify returns false for tampered signature (no throw)"
AND …::"verify returns false for bogus input (caught)"
Requirement: Native stubs preserve layout
The package SHALL ship native-backend placeholder modules
(primitives/p384/impl/p384.native/,
primitives/p521/impl/p521.native/) whose every exported function throws
PrimitiveNotImplemented(<curve>). The placeholders SHALL match the
existing p256.native pattern so the selector switch is mechanical when
a real native implementation lands.
Scenario: P-384 native stub throws on every operation
- WHEN any of
getPublicKey,sign,verify, orrandomPrivateKeyis invoked on the native module - THEN the call throws
PrimitiveNotImplemented("p384")
Scenario: P-521 native stub throws on every operation
- WHEN the same operations are invoked on the P-521 native module
- THEN the call throws
PrimitiveNotImplemented("p521")
Verified by:
…/p384/p384.test.ts::"every operation throws PrimitiveNotImplemented"
AND …/p521/p521.test.ts::"every operation throws PrimitiveNotImplemented"
Requirement: Subpath exports for P-384 and P-521
The package SHALL declare ./p384 and ./p521 entries in
package.json exports so consumers tree-shake to the individual
primitive. The vite.config.ts build entry list SHALL include both new
primitives so the generated dist/ tree carries the expected .d.ts and
.js files at the published path.
Scenario: P-384 subpath resolves
- WHEN a consumer imports
@suaveplan/crypto-curve/p384 - THEN the import resolves with no
Module not founderror and exposesgetPublicKey,sign,verify,randomPrivateKey
Scenario: P-521 subpath resolves
- WHEN a consumer imports
@suaveplan/crypto-curve/p521 - THEN the import resolves with no
Module not founderror and exposes the same four symbols
Verified by: TypeScript compile of consumers (e.g.
packages/vault/cbor/src/cose/sign1.ts) that import these subpaths.