CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-noble--curves

Audited & minimal JS implementation of elliptic curve cryptography

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

webcrypto.mddocs/

WebCrypto Integration

Native browser WebCrypto API wrappers providing hardware-accelerated elliptic curve operations. These wrappers offer the same API as the main curve implementations but use the browser's built-in cryptographic primitives for better performance and security.

Capabilities

NIST Curves with WebCrypto

Hardware-accelerated ECDSA signatures and ECDH key exchange for NIST P-curves.

import { p256, p384, p521 } from "@noble/curves/webcrypto";

// NIST P-256 (secp256r1)
const p256: WebCryptoNIST;

// NIST P-384 (secp384r1) 
const p384: WebCryptoNIST;

// NIST P-521 (secp521r1)
const p521: WebCryptoNIST;

interface WebCryptoNIST extends WebCryptoBaseCurve, WebCryptoSigner, WebCryptoECDH {
  name: string;
  isAvailable(): Promise<boolean>;
  getPublicKey(secretKey: Key, opts?: WebCryptoGetPubOpts): Promise<Key>;
  sign(msgHash: Uint8Array, privateKey: Key, opts?: WebCryptoOpts): Promise<Uint8Array>;
  verify(signature: Uint8Array, msgHash: Uint8Array, publicKey: Key, opts?: WebCryptoOpts): Promise<boolean>;
  getSharedSecret(priv: Uint8Array, pub: Uint8Array, opts?: WebCryptoOpts): Promise<Uint8Array>;
  utils: {
    randomSecretKey: (format?: Format) => Promise<Key>;
    convertSecretKey: (key: Key, inFormat?: Format, outFormat?: Format) => Promise<Key>;
    convertPublicKey: (key: Key, inFormat?: Format, outFormat?: Format) => Promise<Key>;
  };
}

Usage Examples:

import { p256 } from "@noble/curves/webcrypto";

// Check if WebCrypto P-256 is available
const available = await p256.isAvailable();

if (available) {
  // Generate random secret key
  const secretKey = await p256.utils.randomSecretKey();
  
  // Get public key from secret key
  const publicKey = await p256.getPublicKey(secretKey);
  
  // Sign message hash
  const msgHash = new Uint8Array(32); // Your message hash
  const signature = await p256.sign(msgHash, secretKey);
  
  // Verify signature
  const isValid = await p256.verify(signature, msgHash, publicKey);
  
  // ECDH key exchange
  const alicePriv = await p256.utils.randomSecretKey();
  const bobPriv = await p256.utils.randomSecretKey();
  const bobPub = await p256.getPublicKey(bobPriv);
  
  const sharedSecret = await p256.getSharedSecret(alicePriv, bobPub);
}

EdDSA Curves with WebCrypto

Hardware-accelerated EdDSA signatures for Edwards curves.

import { ed25519, ed448 } from "@noble/curves/webcrypto";

// Ed25519 with WebCrypto
const ed25519: WebCryptoEdDSA;

// Ed448 with WebCrypto
const ed448: WebCryptoEdDSA;

interface WebCryptoEdDSA extends WebCryptoBaseCurve, WebCryptoSigner {
  name: string;
  isAvailable(): Promise<boolean>;
  getPublicKey(secretKey: Key, opts?: WebCryptoGetPubOpts): Promise<Key>;
  sign(msgHash: Uint8Array, privateKey: Key, opts?: WebCryptoOpts): Promise<Uint8Array>;
  verify(signature: Uint8Array, msgHash: Uint8Array, publicKey: Key, opts?: WebCryptoOpts): Promise<boolean>;
  utils: {
    randomSecretKey: (format?: Format) => Promise<Key>;
    convertSecretKey: (key: Key, inFormat?: Format, outFormat?: Format) => Promise<Key>;
    convertPublicKey: (key: Key, inFormat?: Format, outFormat?: Format) => Promise<Key>;
  };
}

Montgomery Curves with WebCrypto

Hardware-accelerated ECDH key exchange for Montgomery curves.

import { x25519, x448 } from "@noble/curves/webcrypto";

// X25519 with WebCrypto
const x25519: WebCryptoMontgomery;

// X448 with WebCrypto  
const x448: WebCryptoMontgomery;

interface WebCryptoMontgomery extends WebCryptoBaseCurve, WebCryptoECDH {
  name: string;
  isAvailable(): Promise<boolean>;
  getPublicKey(secretKey: Key, opts?: WebCryptoGetPubOpts): Promise<Key>;
  getSharedSecret(priv: Uint8Array, pub: Uint8Array, opts?: WebCryptoOpts): Promise<Uint8Array>;
  utils: {
    randomSecretKey: (format?: Format) => Promise<Key>;
    convertSecretKey: (key: Key, inFormat?: Format, outFormat?: Format) => Promise<Key>;
    convertPublicKey: (key: Key, inFormat?: Format, outFormat?: Format) => Promise<Key>;
  };
}

Usage Examples:

import { x25519 } from "@noble/curves/webcrypto";

// Check availability
if (await x25519.isAvailable()) {
  // Generate key pair
  const alicePriv = await x25519.utils.randomSecretKey();
  const alicePub = await x25519.getPublicKey(alicePriv);
  
  const bobPriv = await x25519.utils.randomSecretKey();
  const bobPub = await x25519.getPublicKey(bobPriv);
  
  // Compute shared secret
  const sharedSecret = await x25519.getSharedSecret(alicePriv, bobPub);
}

Availability Check

Utility function to check if a curve is supported by the WebCrypto implementation.

import { supportsWc } from "@noble/curves/webcrypto";

/**
 * Check if WebCrypto curve is available
 * @param curve - WebCrypto curve instance to test
 * @returns Promise resolving to availability status
 */
function supportsWc(curve: WebCryptoBaseCurve): Promise<boolean>;

Usage Example:

import { p256, ed25519, x25519, supportsWc } from "@noble/curves/webcrypto";

// Check multiple curve availability
const p256Available = await supportsWc(p256);
const ed25519Available = await supportsWc(ed25519);  
const x25519Available = await supportsWc(x25519);

console.log(`P-256: ${p256Available}`);
console.log(`Ed25519: ${ed25519Available}`);
console.log(`X25519: ${x25519Available}`);

Core Types

// Key formats supported by WebCrypto
type Format = 'raw' | 'jwk' | 'spki' | 'pkcs8';

// Key input type - either JWK object or raw bytes
type Key = JsonWebKey | Uint8Array;

// JSON Web Key structure
type JsonWebKey = {
  crv?: string;
  d?: string;
  kty?: string;
  x?: string;
  y?: string;
  [key: string]: unknown;
};

// WebCrypto operation options
interface WebCryptoOpts {
  format?: Format;
}

// Public key generation options
interface WebCryptoGetPubOpts {
  secFormat?: Format;
  pubFormat?: Format;
}

// Base curve interface
interface WebCryptoBaseCurve {
  name: string;
  isAvailable(): Promise<boolean>;
  getPublicKey(secretKey: Key, opts?: WebCryptoGetPubOpts): Promise<Key>;
  utils: {
    randomSecretKey: (format?: Format) => Promise<Key>;
    convertSecretKey: (key: Key, inFormat?: Format, outFormat?: Format) => Promise<Key>;
    convertPublicKey: (key: Key, inFormat?: Format, outFormat?: Format) => Promise<Key>;
  };
}

// Signature operations
interface WebCryptoSigner {
  sign(msgHash: Uint8Array, privateKey: Key, opts?: WebCryptoOpts): Promise<Uint8Array>;
  verify(signature: Uint8Array, msgHash: Uint8Array, publicKey: Key, opts?: WebCryptoOpts): Promise<boolean>;
}

// ECDH operations
interface WebCryptoECDH {
  getSharedSecret(priv: Uint8Array, pub: Uint8Array, opts?: WebCryptoOpts): Promise<Uint8Array>;
}

Browser Compatibility

Supported Environments

  • Chrome: Full support for all curves
  • Firefox: Limited raw key format support
  • Safari: Limited raw key format support
  • Node.js: Full support including Ed448
  • Bun: Full support with minor key padding quirks
  • Deno: Full support with export validation

Key Format Limitations

Raw Format Issues:

  • Raw secret key import/export prohibited by WebCrypto spec for security
  • Firefox and Safari have additional raw format restrictions
  • Workaround uses PKCS#8 wrapping for raw secret keys

Point Encoding Differences:

  • WebCrypto returns uncompressed points for NIST curves
  • getSharedSecret returns different output lengths:
    • Noble: 33 bytes (y-parity + x coordinate)
    • WebCrypto: 32 bytes (x coordinate only)
  • X25519/X448 shared secret identical between implementations

Feature Detection

Always check availability before using WebCrypto curves:

import { p256, ed25519 } from "@noble/curves/webcrypto";

const curves = [
  { name: 'P-256', curve: p256 },
  { name: 'Ed25519', curve: ed25519 }
];

for (const { name, curve } of curves) {
  const available = await curve.isAvailable();
  console.log(`${name}: ${available ? 'supported' : 'not supported'}`);
}

Performance Benefits

WebCrypto implementations offer several advantages:

  • Hardware Acceleration: Leverages platform-specific optimizations
  • Native Implementation: Uses browser/Node.js built-in cryptography
  • Security: Operations run in secure contexts with proper key isolation
  • Memory Safety: Reduced JavaScript execution for cryptographic operations

Use WebCrypto wrappers when:

  • Performance is critical
  • Working in browsers with WebCrypto support
  • Need hardware security module integration
  • Want to reduce JavaScript bundle size for basic operations

docs

abstract-primitives.md

curves.md

index.md

utilities.md

webcrypto.md

tile.json