Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

noble-curves-extended

higayasuo1.3kMIT0.2.7TypeScript support: included

This project extends @noble/curves to allow randomBytes to be specified externally

cryptography, curves, noble-curves, nist, p256, p384, p521, bls12-381, ed25519, secp256k1

readme

noble-curves-extended

This project extends @noble/curves to allow randomBytes to be specified externally. This is particularly useful for environments where you need to control the source of randomness, such as in testing or when using specific cryptographic hardware.

Features

  • External randomBytes function injection for all curves
  • Support for multiple elliptic curves:
    • Ed25519 (EdDSA signatures)
    • NIST curves (P256, P384, P521)
    • secp256k1 (Bitcoin and Ethereum curve)
    • X25519 (ECDH key exchange)
    • BLS12-381 (Boneh-Lynn-Shacham signatures)
  • Two-layer architecture: low-level curve operations and high-level unified API

Installation

npm install noble-curves-extended

Peer Dependencies

This package requires the following peer dependencies:

npm install @noble/curves @noble/hashes

These dependencies are required because this package is a thin wrapper around @noble/curves and uses @noble/hashes for cryptographic operations.

Architecture

This library provides two layers of functionality:

1. Low-Level Curves (@/curves)

Direct curve implementations with external randomBytes injection. These provide the same API as @noble/curves but allow you to control the randomness source.

2. High-Level Unified API (@/unified)

A unified interface that abstracts curve differences and provides consistent APIs for different cryptographic operations (signatures, ECDH).

Usage

Low-Level Curves (@/curves)

import {
  createEd25519,
  createSecp256k1,
  createP256,
  createP384,
  createP521,
  createX25519,
  createBls12_381,
} from 'noble-curves-extended';

// Create curve instances with your own randomBytes function
const ed25519 = createEd25519(randomBytes);
const secp256k1 = createSecp256k1(randomBytes);
const p256 = createP256(randomBytes);
const p384 = createP384(randomBytes);
const p521 = createP521(randomBytes);
const x25519 = createX25519(randomBytes);
const bls12_381 = createBls12_381(randomBytes);

// Use the curves as you would with @noble/curves
const privateKey = ed25519.utils.randomPrivateKey();
const publicKey = ed25519.getPublicKey(privateKey);

High-Level Unified API (@/unified)

import { Ed25519 } from 'noble-curves-extended';
import { P256, P384, P521, Secp256k1 } from 'noble-curves-extended';
import { X25519 } from 'noble-curves-extended';

// Create dedicated unified curve classes
const ed25519 = new Ed25519(randomBytes);
const p256 = new P256(randomBytes);
const p384 = new P384(randomBytes);
const p521 = new P521(randomBytes);
const secp256k1 = new Secp256k1(randomBytes);
const x25519 = new X25519(randomBytes);

// Use unified API for signatures
const privateKey = ed25519.randomPrivateKey();
const publicKey = ed25519.getPublicKey(privateKey);
const message = new TextEncoder().encode('Hello, World!');
const signature = ed25519.sign({ privateKey, message });
const isValid = ed25519.verify({ publicKey, message, signature });

// Use unified API for ECDH
const alicePrivateKey = x25519.randomPrivateKey();
const alicePublicKey = x25519.getPublicKey(alicePrivateKey);
const bobPrivateKey = x25519.randomPrivateKey();
const bobPublicKey = x25519.getPublicKey(bobPrivateKey);

const aliceSharedSecret = x25519.getSharedSecret({
  privateKey: alicePrivateKey,
  publicKey: bobPublicKey,
});
const bobSharedSecret = x25519.getSharedSecret({
  privateKey: bobPrivateKey,
  publicKey: alicePublicKey,
});
// aliceSharedSecret === bobSharedSecret

// JWK operations
const jwkPrivateKey = ed25519.toJwkPrivateKey(privateKey);
const jwkPublicKey = ed25519.toJwkPublicKey(publicKey);
const recoveredPrivateKey = ed25519.toRawPrivateKey(jwkPrivateKey);
const recoveredPublicKey = ed25519.toRawPublicKey(jwkPublicKey);

Alternatively, you can use factory functions when you want to obtain a curve by its name at runtime:

import { createSignatureCurve, createEcdhCurve } from 'noble-curves-extended';

// Create by curve name (runtime)
const ed25519 = createSignatureCurve('Ed25519', randomBytes);
const p256 = createSignatureCurve('P-256', randomBytes);
const secp256k1 = createSignatureCurve('secp256k1', randomBytes);

const x25519 = createEcdhCurve('X25519', randomBytes);

// Use the same unified API
const privateKey = ed25519.randomPrivateKey();
const publicKey = ed25519.getPublicKey(privateKey);
const message = new TextEncoder().encode('Hello, World!');
const signature = ed25519.sign({ privateKey, message });
const isValid = ed25519.verify({ publicKey, message, signature });

RNG-Disallowed Signature Curves

When you need to forbid RNG usage (e.g., to enforce deterministic behavior or harden code paths), use the RNG-disallowed factory. It returns a signature curve with RNG operations disabled while keeping signing/verification available.

// Helper factory:
const curve = createSignatureCurveRngDisallowed('P-256');

// Example flow using the RNG-allowed factory to obtain a private key,
// then using the RNG-disallowed curve to sign/verify deterministically.
import {
  createSignatureCurve,
  createSignatureCurveRngDisallowed,
} from 'noble-curves-extended';
import { randomBytes } from '@noble/hashes/utils';

// Generate key material with RNG-allowed curve
const allowed = createSignatureCurve('P-256', randomBytes);

// Obtain an RNG-disallowed curve (no randomBytes/randomPrivateKey)
const noRng = createSignatureCurveRngDisallowed('P-256');

const privateKey = allowed.randomPrivateKey();
const publicKey = noRng.getPublicKey(privateKey, false);

// Deterministic sign (RFC 6979 for ECDSA; Ed25519 is deterministic by design)
const message = new TextEncoder().encode('Hello, RNG-free world!');
const signature = noRng.sign({ privateKey, message });
const ok = noRng.verify({ publicKey, message, signature });

API

RandomBytes Type

type RandomBytes = (byteLength?: number) => Uint8Array;

Low-Level Curves (@/curves)

Curve Creation Functions

  • createEd25519(randomBytes: RandomBytes): Creates Ed25519 curve instance
  • createSecp256k1(randomBytes: RandomBytes): Creates secp256k1 curve instance
  • createP256(randomBytes: RandomBytes): Creates NIST P256 curve instance
  • createP384(randomBytes: RandomBytes): Creates NIST P384 curve instance
  • createP521(randomBytes: RandomBytes): Creates NIST P521 curve instance
  • createX25519(randomBytes: RandomBytes): Creates X25519 curve instance
  • createBls12_381(randomBytes: RandomBytes): Creates BLS12-381 curve instance

Each curve instance provides the same API as its counterpart in @noble/curves.

High-Level Unified API (@/unified)

Dedicated Classes

  • new Ed25519(randomBytes: RandomBytes)
  • new P256(randomBytes: RandomBytes)
  • new P384(randomBytes: RandomBytes)
  • new P521(randomBytes: RandomBytes)
  • new Secp256k1(randomBytes: RandomBytes)
  • new X25519(randomBytes: RandomBytes)

Factory Functions

  • createSignatureCurve(curveName: SignatureCurveName, randomBytes: RandomBytes)
  • createEcdhCurve(curveName: EcdhCurveName, randomBytes: RandomBytes)
  • createSignatureCurveRngDisallowed(curveName: SignatureCurveName)

    Returns a signature curve with RNG operations disabled (randomBytes and randomPrivateKey are omitted). Signing remains available and deterministic (ECDSA uses RFC 6979; Ed25519 is deterministic by design).

Supported Unified Curves

Signature: Ed25519, P-256, P-384, P-521, secp256k1

ECDH: P-256, P-384, P-521, secp256k1, X25519

Unified Interface

All unified curve instances provide:

  • curveName: CurveName: The name of the curve
  • keyByteLength: number: The byte length of the key
  • randomPrivateKey(): Uint8Array: Generate a random private key
  • getPublicKey(privateKey: Uint8Array, compressed?: boolean): Uint8Array: Derive public key from private key
  • toJwkPrivateKey(privateKey: Uint8Array): JwkPrivateKey: Convert private key to JWK format
  • toJwkPublicKey(publicKey: Uint8Array): JwkPublicKey: Convert public key to JWK format
  • toRawPrivateKey(jwkPrivateKey: JwkPrivateKey): Uint8Array: Convert JWK private key to raw format
  • toRawPublicKey(jwkPublicKey: JwkPublicKey): Uint8Array: Convert JWK public key to raw format

Signature Curves Additional Methods

  • signatureAlgorithmName: SignatureAlgorithmName: The signature algorithm name
  • sign({ privateKey, message, recovered? }): Uint8Array: Sign a message
  • verify({ publicKey, message, signature }): boolean: Verify a signature
  • recoverPublicKey({ signature, message, compressed? }): Uint8Array: Recover public key from signature (Weierstrass curves only)

ECDH Curves Additional Methods

  • getSharedSecret({ privateKey, publicKey }): Uint8Array: Compute shared secret

BLS12-381 Specific

The BLS12-381 implementation provides:

  • Custom random bytes generation through the randomBytes parameter
  • Field operations over the BLS12-381 scalar field (Fr)
  • Utility functions for key generation and management

Security

This library is a thin wrapper around @noble/curves and inherits its security properties. The only modification is the ability to inject a custom randomBytes function.

License

MIT

changelog

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[0.2.7] - 2025-09-27

Added

  • Added createSignatureCurveRngDisallowed factory to create signature curves with RNG operations disabled (omits randomBytes and randomPrivateKey) while keeping sign, verify, and recovery available.
  • Exported createSignatureCurveRngDisallowed from src/unified/factory/index.ts so it can be imported from the package root.
  • Added createSignatureCurveRngDisallowed.spec.ts tests verifying RNG usage throws, deterministic sign/verify works, and recovery behavior for Weierstrass curves (Ed25519 recovery remains unsupported).
  • Updated README with usage examples for RNG-disallowed signature curves.

[0.2.6] - 2025-09-27

Added

  • Dedicated unified classes for all curves with explicit metadata (including keyByteLength): Ed25519, P256, P384, P521, Secp256k1, X25519

Changed

  • Stopped reading metadata from curve.CURVE; defined required metadata as class properties across all unified classes
  • Unified Weierstrass APIs: weierstrassToJwkPublickKey, weierstrassToJwkPrivateKey, weierstrassToRawPublicKey, and weierstrassToRawPrivateKey now take keyByteLength, curveName, and (where applicable) signatureAlgorithmName
  • Updated Weierstrass tests and Web Crypto usage to pass the new parameters
  • Montgomery JWK/public key tests updated to use explicit 32-byte constants and new function signatures; removed curve.GuBytes.length usages
  • README updated to prefer dedicated unified classes (and retain factory functions as an option)

Removed

  • Removed getWeierstrassCurveName and getWeierstrassSignatureAlgorithm helpers and their tests

[0.2.5] - 2025-09-22

Added

  • Added kid to JwkPublicKey
  • Added key_ops to JwkBase

[0.2.4] - 2025-06-30

Changed

  • Changed error logging from console.error to console.log when catching exceptions to improve readability by avoiding stack trace output

[0.2.3] - 2025-06-26

Changed

  • Improved error messages in toRawPublicKey and toRawPrivateKey functions across all curve types (Weierstrass, Edwards, Montgomery):
    • Removed "Invalid JWK:" prefix from all error messages for cleaner output
    • Made error messages start with capital letters for better readability
    • Enhanced error messages to be more specific and informative
    • Added getErrorMessage utility usage for consistent error handling
    • Updated test expectations to match the new error message format
    • Simplified test structure for non-critical parameters while maintaining comprehensive coverage for key validation

[0.2.2] - 2025-06-25

Added

  • Added createEcdhCurve export to unified factory index.ts

[0.2.1] - 2025-06-25

Changed

  • Changed curveName parameter type to string in createEcdhCurve and createSignatureCurve factory functions

[0.2.0] - 2025-06-24

Added

  • Added support for multiple Weierstrass curves in public key recovery compatibility tests (P-256, P-384, P-521, secp256k1)
  • Added ellipticCurveName property to curve configurations for cleaner mapping to elliptic library
  • Added getEdwardsCurveName function for dynamic Edwards curve name detection
  • Added getMontgomeryCurveName function for dynamic Montgomery curve name detection
  • Added comprehensive test coverage for curve name detection functions
  • Added unified factory functions for creating signature and ECDH curves

Changed

  • BREAKING: Replaced Ed25519 class with generic Edwards class that dynamically determines curve name
  • BREAKING: Renamed signatureAlgorithm property to signatureAlgorithmName in Signature interface and related classes for naming consistency
  • Refactored Montgomery curve utilities to use consistent naming (replaced x25519 with montgomery)
  • Updated all test files to use dynamic length checks based on curve.GuBytes.length for Montgomery curves
  • Moved curve creation to top-level describe blocks in test files for better performance
  • Reorganized unified curve utilities into separate directories for better maintainability
  • Updated export lists to be alphabetically ordered and exclude test directories

Fixed

  • Fixed deprecation warnings in Vitest tests by replacing it.skip.each() with it.each()
  • Fixed type errors with curveName property in Edwards curve implementations
  • Fixed import paths and function names for consistency across the codebase
  • Fixed test structure to use proper curve instantiation patterns

Removed

  • Removed Web Crypto API compatibility tests for public key recovery (not supported by Web Crypto API)
  • Removed redundant test files and consolidated test structure

[0.1.4] - 2025-06-13

Added

  • Added isValidPublicKey property to the NistCurve type returned by createNistCurve in createNistCurve.ts.
  • The isValidPublicKey implementation is provided in isValidPublicKey.ts and allows validation of public keys as valid points on the curve.

[0.1.3] - 2025-06-05

Added

  • Added randomBytes property to the NistCurve type returned by createNistCurve in createNistCurve.ts.
  • Added toRawPrivateKey and toRawPublicKey properties to the NistCurve type returned by createNistCurve in createNistCurve.ts.
  • Added utility functions for converting JWK keys back to raw format:
    • toRawPrivateKey.ts: Converts JWK private keys to raw private key format
    • toRawPublicKey.ts: Converts JWK public keys to raw uncompressed public key format

[0.1.2] - 2025-06-05

Added

  • Added curveName, toJwkPrivateKey, and toJwkPublicKey properties to the NistCurve type returned by createNistCurve in createNistCurve.ts.

[0.1.1] - 2025-06-05

Added

  • Added createNistCurve function in nist.ts to allow dynamic instantiation of NIST curves (P-256, P-384, P-521) with custom random bytes function.

[0.1.0] - 2025-06-01

Added

  • Initial implementation of BLS12-381 curve with custom random bytes generation
  • Field operations over the BLS12-381 scalar field (Fr)
  • Utility functions for key generation and management
  • Support for external randomBytes function injection for all curves
  • Support for multiple elliptic curves:
    • Ed25519 (EdDSA signatures)
    • NIST curves (P256, P384, P521)
    • secp256k1 (Bitcoin's curve)
    • BLS12-381 (Boneh-Lynn-Shacham signatures)

Changed

  • Updated README.md with BLS12-381 specific documentation
  • Fixed function name from createBls12381 to createBls12_381

Security

  • This library is a thin wrapper around @noble/curves and inherits its security properties
  • The only modification is the ability to inject a custom randomBytes function

[Unreleased]

[0.2.7] - 2025-09-27

Added

  • Added createSignatureCurveRngDisallowed factory to create signature curves with RNG operations disabled (omits randomBytes and randomPrivateKey) while keeping sign, verify, and recovery available.
  • Exported createSignatureCurveRngDisallowed from src/unified/factory/index.ts so it can be imported from the package root.
  • Added createSignatureCurveRngDisallowed.spec.ts tests verifying RNG usage throws, deterministic sign/verify works, and recovery behavior for Weierstrass curves (Ed25519 recovery remains unsupported).
  • Updated README with usage examples for RNG-disallowed signature curves.