4.7 KiB
ecdsa-p384
(no submodules)
Purpose
Provides ECDSA (Elliptic Curve Digital Signature Algorithm) operations using the NIST P-384 curve and SHA-384 hash, backed by crypto.subtle. P-384 offers 192 bits of security — stronger than P-256's 128 bits — and is required by many compliance frameworks (NIST SP 800-57, CNSA Suite 2.0, NSA Suite B). This module is intended for contexts where P-384 is mandated by policy or interoperability requirements.
The public key format is the 97-byte uncompressed point representation (0x04 prefix followed by 48-byte X and Y coordinates). The private key is PKCS8 DER. Both formats are standard and directly importable by other Web Crypto implementations.
Features
generateKeypair()— generates a P-384 ECDSA keypair usingcrypto.subtle.generateKeysign(privateKey, message)— signs with ECDSA-P384 / SHA-384verify(publicKey, signature, message)— verifies an ECDSA-P384 signature- Public key: 97-byte uncompressed point (raw format)
- Private key: PKCS8 DER bytes
- Signature format: IEEE P1363 (R || S) as returned by
crypto.subtle assertWebCryptoAvailable()guard on every call- Typed
BrowserCryptoErrorfor all failure paths
Usage: Basic Example
import { ecdsaP384 } from "@suaveplan/crypto-browser/ecdsa-p384/ecdsa-p384";
const kp = await ecdsaP384.generateKeypair();
// kp.publicKey is 97 bytes (uncompressed P-384 point)
// kp.privateKey is PKCS8 DER bytes
const message = new TextEncoder().encode("document to sign");
const signature = await ecdsaP384.sign(kp.privateKey, message);
const valid = await ecdsaP384.verify(kp.publicKey, signature, message);
console.log(valid); // true
Usage: Advanced Example
import { ecdsaP384 } from "@suaveplan/crypto-browser/ecdsa-p384/ecdsa-p384";
import { BrowserCryptoError } from "@suaveplan/crypto-browser/errors";
// Issue a signed certificate-like structure
async function issueAttestation(
issuerPrivateKey: Uint8Array,
payload: Uint8Array
): Promise<{ signature: Uint8Array; algorithm: string }> {
try {
const signature = await ecdsaP384.sign(issuerPrivateKey, payload);
return { signature, algorithm: "ECDSA-P384-SHA384" };
} catch (err) {
if (err instanceof BrowserCryptoError) {
throw new Error(`Signing failed: ${err.code}`);
}
throw err;
}
}
// Verify the attestation with a stored public key
async function verifyAttestation(
publicKey: Uint8Array,
payload: Uint8Array,
signature: Uint8Array
): Promise<boolean> {
return ecdsaP384.verify(publicKey, signature, payload);
}
API Reference
ecdsaP384.generateKeypair(): Promise<{ publicKey: Uint8Array; privateKey: Uint8Array }>
Generates a P-384 ECDSA keypair.
Returns: Promise<{ publicKey: Uint8Array; privateKey: Uint8Array }> — 97-byte uncompressed public key and PKCS8 DER private key.
Throws: BrowserCryptoError — BROWSER_CRYPTO.KEY.GENERATION_FAILED or BROWSER_CRYPTO.NOT_AVAILABLE.
ecdsaP384.sign(privateKey, message): Promise<Uint8Array>
Signs message using ECDSA-P384 with SHA-384.
| Parameter | Type | Description |
|---|---|---|
privateKey |
Uint8Array |
PKCS8 DER private key bytes |
message |
Uint8Array |
Bytes to sign |
Returns: Promise<Uint8Array> — IEEE P1363 signature (96 bytes for P-384).
Throws: BrowserCryptoError — BROWSER_CRYPTO.OPERATION.FAILED or BROWSER_CRYPTO.NOT_AVAILABLE.
ecdsaP384.verify(publicKey, signature, message): Promise<boolean>
Verifies an ECDSA-P384 / SHA-384 signature.
| Parameter | Type | Description |
|---|---|---|
publicKey |
Uint8Array |
97-byte uncompressed P-384 public key |
signature |
Uint8Array |
IEEE P1363 signature bytes |
message |
Uint8Array |
Original message bytes |
Returns: Promise<boolean> — true if signature is valid.
Throws: BrowserCryptoError — BROWSER_CRYPTO.OPERATION.FAILED or BROWSER_CRYPTO.NOT_AVAILABLE.
Implementation Notes
SHA-384 is paired with P-384 because the security level of the hash should match that of the curve. Using SHA-256 with P-384 would create a mismatch: the 192-bit curve security would be limited to the 128-bit collision resistance of SHA-256.
The signature output format from crypto.subtle.sign for ECDSA is IEEE P1363 (raw R || S concatenation), not DER/ASN.1. This differs from OpenSSL's default DER encoding. When interoperating with systems that expect DER signatures, a conversion layer is needed.
P-384 key generation is typically 2–5× slower than P-256 due to the larger field size. For high-throughput signing workloads where P-256 security is sufficient, consider using webCryptoEcdsaP256Engine instead.