Socket
Socket
Sign inDemoInstall

@noble/curves

Package Overview
Dependencies
Maintainers
1
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@noble/curves - npm Package Compare versions

Comparing version 0.1.0 to 0.2.0

lib/edwards.d.ts

11

lib/esm/modular.js
/*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
// Utilities for modular arithmetics
const _0n = BigInt(0);

@@ -100,3 +101,2 @@ const _1n = BigInt(1);

* Calculates square root of a number in a finite field.
* Used to calculate y - the square root of y².
*/

@@ -150,1 +150,10 @@ export function sqrt(number, modulo) {

}
// Little-endian check for first LE bit (last BE bit);
export const isNegativeLE = (num, modulo) => (mod(num, modulo) & _1n) === _1n;
// An idea on modular arithmetic for bls12-381:
// const FIELD = {add, pow, sqrt, mul};
// Functions will take field elements, no need for an additional class
// Could be faster. 1 bigint field will just do operations and mod later:
// instead of 'r = mod(r * b, P)' we will write r = mul(r, b);
// Could be insecure without shape check, so it needs to be done.
// Functions could be inlined by JIT.
/*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
// Convert between types
// ---------------------
export function validateOpts(curve) {
for (const i of ['P', 'n', 'h', 'Gx', 'Gy']) {
if (typeof curve[i] !== 'bigint')
throw new Error(`Invalid curve param ${i}=${curve[i]} (${typeof curve[i]})`);
}
for (const i of ['nBitLength', 'nByteLength']) {
if (curve[i] === undefined)
continue; // Optional
if (!Number.isSafeInteger(curve[i]))
throw new Error(`Invalid curve param ${i}=${curve[i]} (${typeof curve[i]})`);
}
// Set defaults
return Object.freeze({ ...nLength(curve.n, curve.nBitLength), ...curve });
}
import * as mod from './modular.js';
const hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0'));

@@ -45,9 +58,19 @@ export function bytesToHex(uint8a) {

// Big Endian
export function bytesToNumber(bytes) {
export function bytesToNumberBE(bytes) {
return hexToNumber(bytesToHex(bytes));
}
export function ensureBytes(hex) {
export function bytesToNumberLE(uint8a) {
if (!(uint8a instanceof Uint8Array))
throw new Error('Expected Uint8Array');
return BigInt('0x' + bytesToHex(Uint8Array.from(uint8a).reverse()));
}
export const numberToBytesBE = (n, len) => hexToBytes(n.toString(16).padStart(len * 2, '0'));
export const numberToBytesLE = (n, len) => numberToBytesBE(n, len).reverse();
export function ensureBytes(hex, expectedLength) {
// Uint8Array.from() instead of hash.slice() because node.js Buffer
// is instance of Uint8Array, and its slice() creates **mutable** copy
return hex instanceof Uint8Array ? Uint8Array.from(hex) : hexToBytes(hex);
const bytes = hex instanceof Uint8Array ? Uint8Array.from(hex) : hexToBytes(hex);
if (typeof expectedLength === 'number' && bytes.length !== expectedLength)
throw new Error(`Expected ${expectedLength} bytes`);
return bytes;
}

@@ -69,1 +92,35 @@ // Copies several Uint8Arrays into one.

}
// CURVE.n lengths
export function nLength(n, nBitLength) {
// Bit size, byte size of CURVE.n
const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length;
const nByteLength = Math.ceil(_nBitLength / 8);
return { nBitLength: _nBitLength, nByteLength };
}
/**
* Can take (n+8) or more bytes of uniform input e.g. from CSPRNG or KDF
* and convert them into private scalar, with the modulo bias being neglible.
* As per FIPS 186 B.4.1.
* https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
* @param hash hash output from sha512, or a similar function
* @returns valid private scalar
*/
const _1n = BigInt(1);
export function hashToPrivateScalar(hash, CURVE_ORDER, isLE = false) {
hash = ensureBytes(hash);
const orderLen = nLength(CURVE_ORDER).nByteLength;
const minLen = orderLen + 8;
if (orderLen < 16 || hash.length < minLen || hash.length > 1024)
throw new Error('Expected valid bytes of private key as per FIPS 186');
const num = isLE ? bytesToNumberLE(hash) : bytesToNumberBE(hash);
return mod.mod(num, CURVE_ORDER - _1n) + _1n;
}
export function equalBytes(b1, b2) {
// We don't care about timing attacks here
if (b1.length !== b2.length)
return false;
for (let i = 0; i < b1.length; i++)
if (b1[i] !== b2[i])
return false;
return true;
}

3

lib/modular.d.ts

@@ -0,1 +1,2 @@

/*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
export declare function mod(a: bigint, b: bigint): bigint;

@@ -23,4 +24,4 @@ /**

* Calculates square root of a number in a finite field.
* Used to calculate y - the square root of y².
*/
export declare function sqrt(number: bigint, modulo: bigint): bigint;
export declare const isNegativeLE: (num: bigint, modulo: bigint) => boolean;
"use strict";
/*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
Object.defineProperty(exports, "__esModule", { value: true });
exports.sqrt = exports.legendre = exports.invertBatch = exports.invert = exports.pow2 = exports.pow = exports.mod = void 0;
/*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
exports.isNegativeLE = exports.sqrt = exports.legendre = exports.invertBatch = exports.invert = exports.pow2 = exports.pow = exports.mod = void 0;
// Utilities for modular arithmetics
const _0n = BigInt(0);

@@ -109,3 +110,2 @@ const _1n = BigInt(1);

* Calculates square root of a number in a finite field.
* Used to calculate y - the square root of y².
*/

@@ -160,1 +160,11 @@ function sqrt(number, modulo) {

exports.sqrt = sqrt;
// Little-endian check for first LE bit (last BE bit);
const isNegativeLE = (num, modulo) => (mod(num, modulo) & _1n) === _1n;
exports.isNegativeLE = isNegativeLE;
// An idea on modular arithmetic for bls12-381:
// const FIELD = {add, pow, sqrt, mul};
// Functions will take field elements, no need for an additional class
// Could be faster. 1 bigint field will just do operations and mod later:
// instead of 'r = mod(r * b, P)' we will write r = mul(r, b);
// Could be insecure without shape check, so it needs to be done.
// Functions could be inlined by JIT.
/*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
export declare type Hex = Uint8Array | string;
export declare type PrivKey = Hex | bigint | number;
export declare type BasicCurve = {
P: bigint;
n: bigint;
nBitLength?: number;
nByteLength?: number;
h: bigint;
Gx: bigint;
Gy: bigint;
};
export declare function validateOpts<T extends BasicCurve>(curve: T): Readonly<{
readonly nBitLength: number;
readonly nByteLength: number;
} & T>;
export declare function bytesToHex(uint8a: Uint8Array): string;

@@ -6,4 +21,13 @@ export declare function numberToHexUnpadded(num: number | bigint): string;

export declare function hexToBytes(hex: string): Uint8Array;
export declare function bytesToNumber(bytes: Uint8Array): bigint;
export declare function ensureBytes(hex: string | Uint8Array): Uint8Array;
export declare function bytesToNumberBE(bytes: Uint8Array): bigint;
export declare function bytesToNumberLE(uint8a: Uint8Array): bigint;
export declare const numberToBytesBE: (n: bigint, len: number) => Uint8Array;
export declare const numberToBytesLE: (n: bigint, len: number) => Uint8Array;
export declare function ensureBytes(hex: Hex, expectedLength?: number): Uint8Array;
export declare function concatBytes(...arrays: Uint8Array[]): Uint8Array;
export declare function nLength(n: bigint, nBitLength?: number): {
nBitLength: number;
nByteLength: number;
};
export declare function hashToPrivateScalar(hash: Hex, CURVE_ORDER: bigint, isLE?: boolean): bigint;
export declare function equalBytes(b1: Uint8Array, b2: Uint8Array): boolean;
"use strict";
/*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
// Convert between types
// ---------------------
Object.defineProperty(exports, "__esModule", { value: true });
exports.concatBytes = exports.ensureBytes = exports.bytesToNumber = exports.hexToBytes = exports.hexToNumber = exports.numberToHexUnpadded = exports.bytesToHex = void 0;
exports.equalBytes = exports.hashToPrivateScalar = exports.nLength = exports.concatBytes = exports.ensureBytes = exports.numberToBytesLE = exports.numberToBytesBE = exports.bytesToNumberLE = exports.bytesToNumberBE = exports.hexToBytes = exports.hexToNumber = exports.numberToHexUnpadded = exports.bytesToHex = exports.validateOpts = void 0;
function validateOpts(curve) {
for (const i of ['P', 'n', 'h', 'Gx', 'Gy']) {
if (typeof curve[i] !== 'bigint')
throw new Error(`Invalid curve param ${i}=${curve[i]} (${typeof curve[i]})`);
}
for (const i of ['nBitLength', 'nByteLength']) {
if (curve[i] === undefined)
continue; // Optional
if (!Number.isSafeInteger(curve[i]))
throw new Error(`Invalid curve param ${i}=${curve[i]} (${typeof curve[i]})`);
}
// Set defaults
return Object.freeze({ ...nLength(curve.n, curve.nBitLength), ...curve });
}
exports.validateOpts = validateOpts;
const mod = require("./modular.js");
const hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0'));

@@ -52,10 +66,23 @@ function bytesToHex(uint8a) {

// Big Endian
function bytesToNumber(bytes) {
function bytesToNumberBE(bytes) {
return hexToNumber(bytesToHex(bytes));
}
exports.bytesToNumber = bytesToNumber;
function ensureBytes(hex) {
exports.bytesToNumberBE = bytesToNumberBE;
function bytesToNumberLE(uint8a) {
if (!(uint8a instanceof Uint8Array))
throw new Error('Expected Uint8Array');
return BigInt('0x' + bytesToHex(Uint8Array.from(uint8a).reverse()));
}
exports.bytesToNumberLE = bytesToNumberLE;
const numberToBytesBE = (n, len) => hexToBytes(n.toString(16).padStart(len * 2, '0'));
exports.numberToBytesBE = numberToBytesBE;
const numberToBytesLE = (n, len) => (0, exports.numberToBytesBE)(n, len).reverse();
exports.numberToBytesLE = numberToBytesLE;
function ensureBytes(hex, expectedLength) {
// Uint8Array.from() instead of hash.slice() because node.js Buffer
// is instance of Uint8Array, and its slice() creates **mutable** copy
return hex instanceof Uint8Array ? Uint8Array.from(hex) : hexToBytes(hex);
const bytes = hex instanceof Uint8Array ? Uint8Array.from(hex) : hexToBytes(hex);
if (typeof expectedLength === 'number' && bytes.length !== expectedLength)
throw new Error(`Expected ${expectedLength} bytes`);
return bytes;
}

@@ -79,1 +106,38 @@ exports.ensureBytes = ensureBytes;

exports.concatBytes = concatBytes;
// CURVE.n lengths
function nLength(n, nBitLength) {
// Bit size, byte size of CURVE.n
const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length;
const nByteLength = Math.ceil(_nBitLength / 8);
return { nBitLength: _nBitLength, nByteLength };
}
exports.nLength = nLength;
/**
* Can take (n+8) or more bytes of uniform input e.g. from CSPRNG or KDF
* and convert them into private scalar, with the modulo bias being neglible.
* As per FIPS 186 B.4.1.
* https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
* @param hash hash output from sha512, or a similar function
* @returns valid private scalar
*/
const _1n = BigInt(1);
function hashToPrivateScalar(hash, CURVE_ORDER, isLE = false) {
hash = ensureBytes(hash);
const orderLen = nLength(CURVE_ORDER).nByteLength;
const minLen = orderLen + 8;
if (orderLen < 16 || hash.length < minLen || hash.length > 1024)
throw new Error('Expected valid bytes of private key as per FIPS 186');
const num = isLE ? bytesToNumberLE(hash) : bytesToNumberBE(hash);
return mod.mod(num, CURVE_ORDER - _1n) + _1n;
}
exports.hashToPrivateScalar = hashToPrivateScalar;
function equalBytes(b1, b2) {
// We don't care about timing attacks here
if (b1.length !== b2.length)
return false;
for (let i = 0; i < b1.length; i++)
if (b1[i] !== b2[i])
return false;
return true;
}
exports.equalBytes = equalBytes;
{
"name": "@noble/curves",
"version": "0.1.0",
"version": "0.2.0",
"description": "Minimal, zero-dependency JS implementation of elliptic curve cryptography",

@@ -11,3 +11,3 @@ "files": [

"scripts": {
"bench": "node test/benchmark/index.js",
"bench": "node curve-definitions/benchmark/index.js",
"build": "tsc && tsc -p tsconfig.esm.json",

@@ -36,2 +36,7 @@ "build:release": "rollup -c rollup.config.js",

"exports": {
"./edwards": {
"types": "./lib/edwards.d.ts",
"import": "./lib/esm/edwards.js",
"default": "./lib/edwards.js"
},
"./modular": {

@@ -42,7 +47,12 @@ "types": "./lib/modular.d.ts",

},
"./shortw": {
"types": "./lib/shortw.d.ts",
"import": "./lib/esm/shortw.js",
"default": "./lib/shortw.js"
"./montgomery": {
"types": "./lib/montgomery.d.ts",
"import": "./lib/esm/montgomery.js",
"default": "./lib/montgomery.js"
},
"./weierstrass": {
"types": "./lib/weierstrass.d.ts",
"import": "./lib/esm/weierstrass.js",
"default": "./lib/weierstrass.js"
},
"./utils": {

@@ -59,2 +69,8 @@ "types": "./lib/utils.d.ts",

"hyperelliptic",
"weierstrass",
"edwards",
"montgomery",
"secp256k1",
"ed25519",
"ed448",
"p256",

@@ -64,6 +80,2 @@ "p384",

"nist",
"weierstrass",
"edwards",
"montgomery",
"hashes",
"ecc",

@@ -80,2 +92,2 @@ "ecdsa",

]
}
}

@@ -5,11 +5,17 @@ # noble-curves

Implements Short Weierstrass curves with ECDSA signature scheme.
- Short Weierstrass curve with ECDSA signatures
- Twisted Edwards curve with EdDSA signatures
- Montgomery curve for ECDH key agreement
To keep the package minimal, no curve definitions are provided out-of-box.
Main reason for that is the fact hashing library is usually required for full functionality. Use separate package that defines popular curves: `micro-curve-definitions` for P192, P224, P256, P384, P521, secp256k1, stark curve, bn254, pasta (pallas/vesta) - it depends on `@noble/hashes`.
To keep the package minimal, no curve definitions are provided out-of-box. Use `micro-curve-definitions` module:
- It provides P192, P224, P256, P384, P521, secp256k1, stark curve, bn254, pasta (pallas/vesta) short weierstrass curves
- It also provides ed25519 and ed448 twisted edwards curves
- Main reason for separate package is the fact hashing library (like `@noble/hashes`) is required for full functionality
- We may reconsider merging packages in future, when a stable version would be ready
Future plans:
- Edwards, Twisted Edwards & Montgomery curves
- hash-to-curve standard
- hash to curve standard
- point indistinguishability
- pairings

@@ -44,4 +50,3 @@

```ts
// Short Weierstrass curve
import shortw from '@noble/curves/shortw';
import { weierstrass } from '@noble/curves/weierstrass'; // Short Weierstrass curve
import { sha256 } from '@noble/hashes/sha256';

@@ -51,10 +56,7 @@ import { hmac } from '@noble/hashes/hmac';

export const secp256k1 = shortw({
const secp256k1 = weierstrass({
a: 0n,
b: 7n,
// Field over which we'll do calculations
P: 2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n,
// Curve order, total count of valid points in the field
P: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fn,
n: 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n,
// Base point (x, y) aka generator point
Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,

@@ -64,12 +66,94 @@ Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,

hmac: (k: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, concatBytes(...msgs)),
randomBytes: randomBytes
randomBytes
});
// secp256k1.getPublicKey(priv)
// secp256k1.sign(msg, priv)
secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey());
secp256k1.sign(randomBytes(32), secp256k1.utils.randomPrivateKey());
// secp256k1.verify(sig, msg, pub)
import { twistedEdwards } from '@noble/curves/edwards'; // Twisted Edwards curve
import { sha512 } from '@noble/hashes/sha512';
const ed25519 = twistedEdwards({
a: -1n,
d: 37095705934669439343138083508754565189542113879843219016388785533085940283555n,
P: 57896044618658097711785492504343953926634992332820282019728792003956564819949n,
n: 7237005577332262213973186563042994240857116359379907606001950938285454250989n,
h: 8n,
Gx: 15112221349535400772501151409588531511454012693041857206046113283949847762202n,
Gy: 46316835694926478169428394003475163141307993866256225615783033603165251855960n,
hash: sha512,
randomBytes,
adjustScalarBytes(bytes) { // could be no-op
bytes[0] &= 248;
bytes[31] &= 127;
bytes[31] |= 64;
return bytes;
},
} as const);
ed25519.getPublicKey(ed25519.utils.randomPrivateKey());
```
## Performance
Benchmark results on Apple M2 with node v18.10:
```
==== secp256k1 ====
- getPublicKey1 (samples: 10000)
noble_old x 8,131 ops/sec @ 122μs/op
secp256k1 x 7,374 ops/sec @ 135μs/op
- getPublicKey255 (samples: 10000)
noble_old x 7,894 ops/sec @ 126μs/op
secp256k1 x 7,327 ops/sec @ 136μs/op
- sign (samples: 5000)
noble_old x 5,243 ops/sec @ 190μs/op
secp256k1 x 4,834 ops/sec @ 206μs/op
- getSharedSecret (samples: 1000)
noble_old x 653 ops/sec @ 1ms/op
secp256k1 x 634 ops/sec @ 1ms/op
- verify (samples: 1000)
secp256k1_old x 1,038 ops/sec @ 962μs/op
secp256k1 x 1,009 ops/sec @ 990μs/op
==== ed25519 ====
- getPublicKey (samples: 10000)
old x 8,632 ops/sec @ 115μs/op
noble x 8,390 ops/sec @ 119μs/op
- sign (samples: 5000)
old x 4,376 ops/sec @ 228μs/op
noble x 4,233 ops/sec @ 236μs/op
- verify (samples: 1000)
old x 865 ops/sec @ 1ms/op
noble x 860 ops/sec @ 1ms/op
==== ed448 ====
- getPublicKey (samples: 5000)
noble x 3,224 ops/sec @ 310μs/op
- sign (samples: 2500)
noble x 1,561 ops/sec @ 640μs/op
- verify (samples: 500)
noble x 313 ops/sec @ 3ms/op
==== nist ====
- getPublicKey (samples: 2500)
P256 x 7,993 ops/sec @ 125μs/op
P384 x 3,819 ops/sec @ 261μs/op
P521 x 2,074 ops/sec @ 481μs/op
- sign (samples: 1000)
P256 x 5,327 ops/sec @ 187μs/op
P384 x 2,728 ops/sec @ 366μs/op
P521 x 1,594 ops/sec @ 626μs/op
- verify (samples: 250)
P256 x 806 ops/sec @ 1ms/op
P384 x 353 ops/sec @ 2ms/op
P521 x 171 ops/sec @ 5ms/op
==== stark ====
- pedersen (samples: 500)
old x 85 ops/sec @ 11ms/op
noble x 1,216 ops/sec @ 822μs/op
- verify (samples: 500)
old x 302 ops/sec @ 3ms/op
noble x 698 ops/sec @ 1ms/op
```
## License
MIT (c) Paul Miller [(https://paulmillr.com)](https://paulmillr.com), see LICENSE file.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc