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.6.0 to 0.6.1

6

lib/_shortw_utils.d.ts

@@ -21,7 +21,7 @@ import { randomBytes } from '@noble/hashes/utils';

readonly Gy: bigint;
readonly wrapPrivateKey?: boolean | undefined;
readonly allowInfinityPoint?: boolean | undefined;
readonly a: bigint;
readonly b: bigint;
readonly normalizePrivateKey?: ((key: import("./abstract/utils.js").PrivKey) => import("./abstract/utils.js").PrivKey) | undefined;
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
readonly wrapPrivateKey?: boolean | undefined;
readonly endo?: {

@@ -38,6 +38,6 @@ beta: bigint;

readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => import("./abstract/weierstrass.js").ProjPointType<bigint>) | undefined;
lowS: boolean;
readonly hash: CHash;
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
lowS: boolean;
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;

@@ -44,0 +44,0 @@ readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;

@@ -49,3 +49,3 @@ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */

};
export declare type AbstractCurve<T> = {
export declare type BasicCurve<T> = {
Fp: Field<T>;

@@ -59,8 +59,7 @@ n: bigint;

Gy: T;
wrapPrivateKey?: boolean;
allowInfinityPoint?: boolean;
};
export declare function validateAbsOpts<FP, T>(curve: AbstractCurve<FP> & T): Readonly<{
export declare function validateBasic<FP, T>(curve: BasicCurve<FP> & T): Readonly<{
readonly nBitLength: number;
readonly nByteLength: number;
} & AbstractCurve<FP> & T>;
} & BasicCurve<FP> & T>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateAbsOpts = exports.wNAF = void 0;
exports.validateBasic = exports.wNAF = void 0;
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
// Abelian group utilities
const modular_js_1 = require("./modular.js");
const utils_js_1 = require("./utils.js");
const _0n = BigInt(0);

@@ -128,23 +129,16 @@ const _1n = BigInt(1);

exports.wNAF = wNAF;
function validateAbsOpts(curve) {
function validateBasic(curve) {
(0, modular_js_1.validateField)(curve.Fp);
for (const i of ['n', 'h']) {
const val = curve[i];
if (typeof val !== 'bigint')
throw new Error(`Invalid curve param ${i}=${val} (${typeof val})`);
}
if (!curve.Fp.isValid(curve.Gx))
throw new Error('Invalid generator X coordinate Fp element');
if (!curve.Fp.isValid(curve.Gy))
throw new Error('Invalid generator Y coordinate Fp element');
for (const i of ['nBitLength', 'nByteLength']) {
const val = curve[i];
if (val === undefined)
continue; // Optional
if (!Number.isSafeInteger(val))
throw new Error(`Invalid param ${i}=${val} (${typeof val})`);
}
(0, utils_js_1.validateObject)(curve, {
n: 'bigint',
h: 'bigint',
Gx: 'field',
Gy: 'field',
}, {
nBitLength: 'isSafeInteger',
nByteLength: 'isSafeInteger',
});
// Set defaults
return Object.freeze({ ...(0, modular_js_1.nLength)(curve.n, curve.nBitLength), ...curve });
}
exports.validateAbsOpts = validateAbsOpts;
exports.validateBasic = validateBasic;

@@ -0,4 +1,5 @@

import * as ut from './utils.js';
import { FHash, Hex } from './utils.js';
import { Group, GroupConstructor, AbstractCurve, AffinePoint } from './curve.js';
export declare type CurveType = AbstractCurve<bigint> & {
import { Group, GroupConstructor, BasicCurve, AffinePoint } from './curve.js';
export declare type CurveType = BasicCurve<bigint> & {
a: bigint;

@@ -26,7 +27,6 @@ d: bigint;

readonly Gy: bigint;
readonly wrapPrivateKey?: boolean | undefined;
readonly allowInfinityPoint?: boolean | undefined;
readonly a: bigint;
readonly d: bigint;
readonly hash: FHash;
readonly hash: ut.FHash;
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;

@@ -39,3 +39,3 @@ readonly adjustScalarBytes?: ((bytes: Uint8Array) => Uint8Array) | undefined;

}) | undefined;
readonly preHash?: FHash | undefined;
readonly preHash?: ut.FHash | undefined;
readonly mapToCurve?: ((scalar: bigint[]) => AffinePoint<bigint>) | undefined;

@@ -42,0 +42,0 @@ }>;

@@ -7,2 +7,3 @@ "use strict";

const modular_js_1 = require("./modular.js");
const ut = require("./utils.js");
const utils_js_1 = require("./utils.js");

@@ -16,20 +17,14 @@ const curve_js_1 = require("./curve.js");

function validateOpts(curve) {
const opts = (0, curve_js_1.validateAbsOpts)(curve);
if (typeof opts.hash !== 'function')
throw new Error('Invalid hash function');
for (const i of ['a', 'd']) {
const val = opts[i];
if (typeof val !== 'bigint')
throw new Error(`Invalid curve param ${i}=${val} (${typeof val})`);
}
for (const fn of ['randomBytes']) {
if (typeof opts[fn] !== 'function')
throw new Error(`Invalid ${fn} function`);
}
for (const fn of ['adjustScalarBytes', 'domain', 'uvRatio', 'mapToCurve']) {
if (opts[fn] === undefined)
continue; // Optional
if (typeof opts[fn] !== 'function')
throw new Error(`Invalid ${fn} function`);
}
const opts = (0, curve_js_1.validateBasic)(curve);
ut.validateObject(curve, {
hash: 'function',
a: 'bigint',
d: 'bigint',
randomBytes: 'function',
}, {
adjustScalarBytes: 'function',
domain: 'function',
uvRatio: 'function',
mapToCurve: 'function',
});
// Set defaults

@@ -269,3 +264,3 @@ return Object.freeze({ ...opts });

normed[len - 1] = lastByte & ~0x80; // clear last bit
const y = (0, utils_js_1.bytesToNumberLE)(normed);
const y = ut.bytesToNumberLE(normed);
if (y === _0n) {

@@ -300,3 +295,3 @@ // y=0 is allowed

const { x, y } = this.toAffine();
const bytes = (0, utils_js_1.numberToBytesLE)(y, Fp.BYTES); // each y has 2 x values (x, -y)
const bytes = ut.numberToBytesLE(y, Fp.BYTES); // each y has 2 x values (x, -y)
bytes[bytes.length - 1] |= x & _1n ? 0x80 : 0; // when compressing, it's enough to store y

@@ -306,3 +301,3 @@ return bytes; // and use the last byte to encode sign of x

toHex() {
return (0, utils_js_1.bytesToHex)(this.toRawBytes()); // Same as toRawBytes, but returns string.
return ut.bytesToHex(this.toRawBytes()); // Same as toRawBytes, but returns string.
}

@@ -319,3 +314,3 @@ }

function modN_LE(hash) {
return modN((0, utils_js_1.bytesToNumberLE)(hash));
return modN(ut.bytesToNumberLE(hash));
}

@@ -346,3 +341,3 @@ function isHex(item, err) {

function hashDomainToScalar(context = new Uint8Array(), ...msgs) {
const msg = (0, utils_js_1.concatBytes)(...msgs);
const msg = ut.concatBytes(...msgs);
return modN_LE(cHash(domain(msg, (0, utils_js_1.ensureBytes)(context), !!preHash)));

@@ -362,3 +357,3 @@ }

assertGE0(s); // 0 <= s < l
const res = (0, utils_js_1.concatBytes)(R, (0, utils_js_1.numberToBytesLE)(s, Fp.BYTES));
const res = ut.concatBytes(R, ut.numberToBytesLE(s, Fp.BYTES));
return (0, utils_js_1.ensureBytes)(res, nByteLength * 2); // 64-byte signature

@@ -376,3 +371,3 @@ }

const R = Point.fromHex(sig.slice(0, len), false); // 0 <= R < 2^256: ZIP215 R can be >= P
const s = (0, utils_js_1.bytesToNumberLE)(sig.slice(len, 2 * len)); // 0 <= s < l
const s = ut.bytesToNumberLE(sig.slice(len, 2 * len)); // 0 <= s < l
const SB = G.multiplyUnsafe(s);

@@ -379,0 +374,0 @@ const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg);

@@ -23,3 +23,3 @@ "use strict";

if (typeof str !== 'string') {
throw new TypeError(`utf8ToBytes expected string, got ${typeof str}`);
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
}

@@ -26,0 +26,0 @@ return new TextEncoder().encode(str);

@@ -45,3 +45,3 @@ export declare function mod(a: bigint, b: bigint): bigint;

}
export declare function validateField<T>(field: Field<T>): void;
export declare function validateField<T>(field: Field<T>): object;
export declare function FpPow<T>(f: Field<T>, num: T, power: bigint): T;

@@ -48,0 +48,0 @@ export declare function FpInvertBatch<T>(f: Field<T>, nums: T[]): T[];

@@ -42,3 +42,2 @@ "use strict";

// Does x ^ (2 ^ power) mod p. pow2(30, 4) == 30 ^ (2 ^ 4)
// TODO: Fp version?
function pow2(x, power, modulo) {

@@ -207,14 +206,13 @@ let res = x;

function validateField(field) {
for (const i of ['ORDER', 'MASK']) {
if (typeof field[i] !== 'bigint')
throw new Error(`Invalid field param ${i}=${field[i]} (${typeof field[i]})`);
}
for (const i of ['BYTES', 'BITS']) {
if (typeof field[i] !== 'number')
throw new Error(`Invalid field param ${i}=${field[i]} (${typeof field[i]})`);
}
for (const i of FIELD_FIELDS) {
if (typeof field[i] !== 'function')
throw new Error(`Invalid field param ${i}=${field[i]} (${typeof field[i]})`);
}
const initial = {
ORDER: 'bigint',
MASK: 'bigint',
BYTES: 'isSafeInteger',
BITS: 'isSafeInteger',
};
const opts = FIELD_FIELDS.reduce((map, val) => {
map[val] = 'function';
return map;
}, initial);
return (0, utils_js_1.validateObject)(field, opts);
}

@@ -221,0 +219,0 @@ exports.validateField = validateField;

@@ -10,24 +10,12 @@ "use strict";

function validateOpts(curve) {
for (const i of ['a24']) {
if (typeof curve[i] !== 'bigint')
throw new Error(`Invalid curve param ${i}=${curve[i]} (${typeof curve[i]})`);
}
for (const i of ['montgomeryBits', 'nByteLength']) {
if (curve[i] === undefined)
continue; // Optional
if (!Number.isSafeInteger(curve[i]))
throw new Error(`Invalid curve param ${i}=${curve[i]} (${typeof curve[i]})`);
}
for (const fn of ['adjustScalarBytes', 'domain', 'powPminus2']) {
if (curve[fn] === undefined)
continue; // Optional
if (typeof curve[fn] !== 'function')
throw new Error(`Invalid ${fn} function`);
}
for (const i of ['Gu']) {
if (curve[i] === undefined)
continue; // Optional
if (typeof curve[i] !== 'string')
throw new Error(`Invalid curve param ${i}=${curve[i]} (${typeof curve[i]})`);
}
(0, utils_js_1.validateObject)(curve, {
a24: 'bigint',
}, {
montgomeryBits: 'isSafeInteger',
nByteLength: 'isSafeInteger',
adjustScalarBytes: 'function',
domain: 'function',
powPminus2: 'function',
Gu: 'string',
});
// Set defaults

@@ -47,27 +35,3 @@ return Object.freeze({ ...curve });

const powPminus2 = CURVE.powPminus2 || ((x) => (0, modular_js_1.pow)(x, P - BigInt(2), P));
/**
* Checks for num to be in range:
* For strict == true: `0 < num < max`.
* For strict == false: `0 <= num < max`.
* Converts non-float safe numbers to bigints.
*/
function normalizeScalar(num, max, strict = true) {
if (!max)
throw new TypeError('Specify max value');
if (typeof num === 'number' && Number.isSafeInteger(num))
num = BigInt(num);
if (typeof num === 'bigint' && num < max) {
if (strict) {
if (_0n < num)
return num;
}
else {
if (_0n <= num)
return num;
}
}
throw new TypeError('Expected valid scalar: 0 < scalar < max');
}
// cswap from RFC7748
// NOTE: cswap is not from RFC7748!
// cswap from RFC7748. But it is not from RFC7748!
/*

@@ -88,2 +52,7 @@ cswap(swap, x_2, x_3):

}
function assertFieldElement(n) {
if (typeof n === 'bigint' && _0n <= n && n < P)
return n;
throw new Error('Expected valid scalar 0 < scalar < CURVE.P');
}
// x25519 from 4

@@ -97,7 +66,6 @@ /**

function montgomeryLadder(pointU, scalar) {
const { P } = CURVE;
const u = normalizeScalar(pointU, P);
const u = assertFieldElement(pointU);
// Section 5: Implementations MUST accept non-canonical values and process them as
// if they had been reduced modulo the field prime.
const k = normalizeScalar(scalar, P);
const k = assertFieldElement(scalar);
// The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519

@@ -155,3 +123,2 @@ const a24 = CURVE.a24;

function decodeUCoordinate(uEnc) {
const u = (0, utils_js_1.ensureBytes)(uEnc, montgomeryBytes);
// Section 5: When receiving such an array, implementations of X25519

@@ -161,2 +128,3 @@ // MUST mask the most significant bit in the final byte.

// fieldLen - scalaryBytes = 1 for X448 and = 0 for X25519
const u = (0, utils_js_1.ensureBytes)(uEnc, montgomeryBytes);
u[fieldLen - 1] &= 127; // 0b0111_1111

@@ -171,9 +139,2 @@ return (0, utils_js_1.bytesToNumberLE)(u);

}
/**
* Computes shared secret between private key "scalar" and public key's "u" (x) coordinate.
* We can get 'y' coordinate from 'u',
* but Point.fromHex also wants 'x' coordinate oddity flag,
* and we cannot get 'x' without knowing 'v'.
* Need to add generic conversion between twisted edwards and complimentary curve for JubJub.
*/
function scalarMult(scalar, u) {

@@ -189,8 +150,3 @@ const pointU = decodeUCoordinate(u);

}
/**
* Computes public key from private.
* Executes scalar multiplication of curve's base point by scalar.
* @param scalar private key
* @returns new public key
*/
// Computes public key from private. By doing scalar multiplication of base point.
function scalarMultBase(scalar) {

@@ -197,0 +153,0 @@ return scalarMult(scalar, CURVE.Gu);

@@ -22,3 +22,3 @@ export declare type Hex = Uint8Array | string;

export declare function ensureBytes(hex: Hex, expectedLength?: number): Uint8Array;
export declare function concatBytes(...arrays: Uint8Array[]): Uint8Array;
export declare function concatBytes(...arrs: Uint8Array[]): Uint8Array;
export declare function equalBytes(b1: Uint8Array, b2: Uint8Array): boolean;

@@ -29,1 +29,4 @@ export declare function bitLen(n: bigint): number;

export declare const bitMask: (n: number) => bigint;
declare type ValMap = Record<string, string>;
export declare function validateObject(object: object, validators: ValMap, optValidators?: ValMap): object;
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.bitMask = exports.bitSet = exports.bitGet = exports.bitLen = exports.equalBytes = exports.concatBytes = exports.ensureBytes = exports.numberToVarBytesBE = exports.numberToBytesLE = exports.numberToBytesBE = exports.bytesToNumberLE = exports.bytesToNumberBE = exports.hexToBytes = exports.hexToNumber = exports.numberToHexUnpadded = exports.bytesToHex = void 0;
exports.validateObject = exports.bitMask = exports.bitSet = exports.bitGet = exports.bitLen = exports.equalBytes = exports.concatBytes = exports.ensureBytes = exports.numberToVarBytesBE = exports.numberToBytesLE = exports.numberToBytesBE = exports.bytesToNumberLE = exports.bytesToNumberBE = exports.hexToBytes = exports.hexToNumber = exports.numberToHexUnpadded = exports.bytesToHex = void 0;
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */

@@ -12,3 +12,3 @@ const _0n = BigInt(0);

if (!u8a(bytes))
throw new Error('Expected Uint8Array');
throw new Error('Uint8Array expected');
// pre-caching improves the speed 6x

@@ -29,3 +29,3 @@ let hex = '';

if (typeof hex !== 'string')
throw new Error('hexToNumber: expected string, got ' + typeof hex);
throw new Error('string expected, got ' + typeof hex);
// Big Endian

@@ -38,5 +38,5 @@ return BigInt(`0x${hex}`);

if (typeof hex !== 'string')
throw new Error('hexToBytes: expected string, got ' + typeof hex);
throw new Error('string expected, got ' + typeof hex);
if (hex.length % 2)
throw new Error('hexToBytes: received invalid unpadded hex ' + hex.length);
throw new Error('hex string is invalid: unpadded ' + hex.length);
const array = new Uint8Array(hex.length / 2);

@@ -48,3 +48,3 @@ for (let i = 0; i < array.length; i++) {

if (Number.isNaN(byte) || byte < 0)
throw new Error('Invalid byte sequence');
throw new Error('invalid byte sequence');
array[i] = byte;

@@ -62,3 +62,3 @@ }

if (!u8a(bytes))
throw new Error('Expected Uint8Array');
throw new Error('Uint8Array expected');
return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));

@@ -72,8 +72,3 @@ }

// Returns variable number bytes (minimal bigint encoding?)
const numberToVarBytesBE = (n) => {
let hex = n.toString(16);
if (hex.length & 1)
hex = '0' + hex;
return hexToBytes(hex);
};
const numberToVarBytesBE = (n) => hexToBytes(numberToHexUnpadded(n));
exports.numberToVarBytesBE = numberToVarBytesBE;

@@ -90,15 +85,12 @@ function ensureBytes(hex, expectedLength) {

// Copies several Uint8Arrays into one.
function concatBytes(...arrays) {
if (!arrays.every((b) => u8a(b)))
throw new Error('Uint8Array list expected');
if (arrays.length === 1)
return arrays[0];
const length = arrays.reduce((a, arr) => a + arr.length, 0);
const result = new Uint8Array(length);
for (let i = 0, pad = 0; i < arrays.length; i++) {
const arr = arrays[i];
result.set(arr, pad);
pad += arr.length;
}
return result;
function concatBytes(...arrs) {
const r = new Uint8Array(arrs.reduce((sum, a) => sum + a.length, 0));
let pad = 0; // walk through each item, ensure they have proper type
arrs.forEach((a) => {
if (!u8a(a))
throw new Error('Uint8Array expected');
r.set(a, pad);
pad += a.length;
});
return r;
}

@@ -136,1 +128,31 @@ exports.concatBytes = concatBytes;

exports.bitMask = bitMask;
function validateObject(object, validators, optValidators = {}) {
const validatorFns = {
bigint: (val) => typeof val === 'bigint',
function: (val) => typeof val === 'function',
boolean: (val) => typeof val === 'boolean',
string: (val) => typeof val === 'string',
isSafeInteger: (val) => Number.isSafeInteger(val),
array: (val) => Array.isArray(val),
field: (val) => object.Fp.isValid(val),
hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen),
};
// type Key = keyof typeof validators;
const checkField = (fieldName, type, isOptional) => {
const checkVal = validatorFns[type];
if (typeof checkVal !== 'function')
throw new Error(`Invalid validator "${type}", expected function`);
const val = object[fieldName];
if (isOptional && val === undefined)
return;
if (!checkVal(val)) {
throw new Error(`Invalid param ${fieldName}=${val} (${typeof val}), expected ${type}`);
}
};
for (let [fieldName, type] of Object.entries(validators))
checkField(fieldName, type, false);
for (let [fieldName, type] of Object.entries(optValidators))
checkField(fieldName, type, true);
return object;
}
exports.validateObject = validateObject;
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
import * as mod from './modular.js';
import * as ut from './utils.js';
import { Hex, PrivKey, CHash } from './utils.js';
import { Group, GroupConstructor, AbstractCurve, AffinePoint } from './curve.js';
import { CHash, Hex, PrivKey } from './utils.js';
import { Group, GroupConstructor, BasicCurve, AffinePoint } from './curve.js';
export type { AffinePoint };

@@ -17,6 +17,6 @@ declare type HmacFnSync = (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;

};
export declare type BasicCurve<T> = AbstractCurve<T> & {
export declare type BasicWCurve<T> = BasicCurve<T> & {
a: T;
b: T;
normalizePrivateKey?: (key: PrivKey) => PrivKey;
allowedPrivateKeyLengths?: readonly number[];
wrapPrivateKey?: boolean;

@@ -81,3 +81,3 @@ endo?: EndomorphismOpts;

}
export declare type CurvePointsType<T> = BasicCurve<T> & {
export declare type CurvePointsType<T> = BasicWCurve<T> & {
fromBytes: (bytes: Uint8Array) => AffinePoint<T>;

@@ -122,7 +122,7 @@ toBytes: (c: ProjConstructor<T>, point: ProjPointType<T>, compressed: boolean) => Uint8Array;

export declare type PubKey = Hex | ProjPointType<bigint>;
export declare type CurveType = BasicCurve<bigint> & {
lowS?: boolean;
export declare type CurveType = BasicWCurve<bigint> & {
hash: CHash;
hmac: HmacFnSync;
randomBytes: (bytesLength?: number) => Uint8Array;
lowS?: boolean;
bits2int?: (bytes: Uint8Array) => bigint;

@@ -140,14 +140,14 @@ bits2int_modN?: (bytes: Uint8Array) => bigint;

readonly Gy: bigint;
readonly wrapPrivateKey?: boolean | undefined;
readonly allowInfinityPoint?: boolean | undefined;
readonly a: bigint;
readonly b: bigint;
readonly normalizePrivateKey?: ((key: ut.PrivKey) => ut.PrivKey) | undefined;
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
readonly wrapPrivateKey?: boolean | undefined;
readonly endo?: EndomorphismOpts | undefined;
readonly isTorsionFree?: ((c: ProjConstructor<bigint>, point: ProjPointType<bigint>) => boolean) | undefined;
readonly clearCofactor?: ((c: ProjConstructor<bigint>, point: ProjPointType<bigint>) => ProjPointType<bigint>) | undefined;
lowS: boolean;
readonly hash: ut.CHash;
readonly hmac: HmacFnSync;
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
lowS: boolean;
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;

@@ -154,0 +154,0 @@ readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;

@@ -11,17 +11,17 @@ "use strict";

function validatePointOpts(curve) {
const opts = (0, curve_js_1.validateAbsOpts)(curve);
const Fp = opts.Fp;
for (const i of ['a', 'b']) {
if (!Fp.isValid(curve[i]))
throw new Error(`Invalid curve param ${i}=${opts[i]} (${typeof opts[i]})`);
}
for (const i of ['isTorsionFree', 'clearCofactor']) {
if (curve[i] === undefined)
continue; // Optional
if (typeof curve[i] !== 'function')
throw new Error(`Invalid ${i} function`);
}
const endo = opts.endo;
const opts = (0, curve_js_1.validateBasic)(curve);
ut.validateObject(opts, {
a: 'field',
b: 'field',
fromBytes: 'function',
toBytes: 'function',
}, {
allowedPrivateKeyLengths: 'array',
wrapPrivateKey: 'boolean',
isTorsionFree: 'function',
clearCofactor: 'function',
});
const { endo, Fp, a } = opts;
if (endo) {
if (!Fp.eql(opts.a, Fp.ZERO)) {
if (!Fp.eql(a, Fp.ZERO)) {
throw new Error('Endomorphism can only be defined for Koblitz curves that have a=0');

@@ -35,7 +35,2 @@ }

}
if (typeof opts.fromBytes !== 'function')
throw new Error('Invalid fromBytes function');
if (typeof opts.toBytes !== 'function')
throw new Error('Invalid fromBytes function');
// Set defaults
return Object.freeze({ ...opts });

@@ -121,35 +116,24 @@ }

}
/**
* Validates if a private key is valid and converts it to bigint form.
* Supports two options, that are passed when CURVE is initialized:
* - `normalizePrivateKey()` executed before all checks
* - `wrapPrivateKey` when true, executed after most checks, but before `0 < key < n`
*/
// Validates if priv key is valid and converts it to bigint.
// Supports options CURVE.normalizePrivateKey and CURVE.wrapPrivateKey.
function normalizePrivateKey(key) {
const { normalizePrivateKey: custom, nByteLength: groupLen, wrapPrivateKey, n } = CURVE;
if (typeof custom === 'function')
key = custom(key);
const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n } = CURVE;
if (lengths && typeof key !== 'bigint') {
if (key instanceof Uint8Array)
key = ut.bytesToHex(key);
// Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes
if (typeof key !== 'string' || !lengths.includes(key.length))
throw new Error('Invalid key');
key = key.padStart(nByteLength * 2, '0');
}
let num;
if (typeof key === 'bigint') {
// Curve order check is done below
num = key;
try {
num = typeof key === 'bigint' ? key : ut.bytesToNumberBE((0, utils_js_1.ensureBytes)(key, nByteLength));
}
else if (typeof key === 'string') {
if (key.length !== 2 * groupLen)
throw new Error(`must be ${groupLen} bytes`);
// Validates individual octets
num = ut.bytesToNumberBE((0, utils_js_1.ensureBytes)(key));
catch (error) {
throw new Error(`private key must be ${nByteLength} bytes, hex or bigint, not ${typeof key}`);
}
else if (key instanceof Uint8Array) {
if (key.length !== groupLen)
throw new Error(`must be ${groupLen} bytes`);
num = ut.bytesToNumberBE(key);
}
else {
throw new Error('private key must be bytes, hex or bigint, not ' + typeof key);
}
// Useful for curves with cofactor != 1
if (wrapPrivateKey)
num = mod.mod(num, n);
assertGE(num);
num = mod.mod(num, n); // disabled by default, enabled for BLS
assertGE(num); // num in range [1..N-1]
return num;

@@ -509,10 +493,12 @@ }

function validateOpts(curve) {
const opts = (0, curve_js_1.validateAbsOpts)(curve);
if (typeof opts.hash !== 'function' || !Number.isSafeInteger(opts.hash.outputLen))
throw new Error('Invalid hash function');
if (typeof opts.hmac !== 'function')
throw new Error('Invalid hmac function');
if (typeof opts.randomBytes !== 'function')
throw new Error('Invalid randomBytes function');
// Set defaults
const opts = (0, curve_js_1.validateBasic)(curve);
ut.validateObject(opts, {
hash: 'hash',
hmac: 'function',
randomBytes: 'function',
}, {
bits2int: 'function',
bits2int_modN: 'function',
lowS: 'boolean',
});
return Object.freeze({ lowS: true, ...opts });

@@ -626,3 +612,3 @@ }

else {
throw new Error(`Point.fromHex: received invalid point. Expected ${compressedLen} compressed bytes or ${uncompressedLen} uncompressed bytes, not ${len}`);
throw new Error(`Point of length ${len} was invalid. Expected ${compressedLen} compressed bytes or ${uncompressedLen} uncompressed bytes`);
}

@@ -689,3 +675,3 @@ },

const u2 = modN(s * ir); // sr^-1
const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2); // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1)
const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2); // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1)
if (!Q)

@@ -813,5 +799,6 @@ throw new Error('point at infinify'); // unsafe is fine: no priv data leaked

if (typeof num !== 'bigint')
throw new Error('Expected bigint');
throw new Error('bigint expected');
if (!(_0n <= num && num < ORDER_MASK))
throw new Error(`Expected number < 2^${CURVE.nBitLength}`);
// n in [0..ORDER_MASK-1]
throw new Error(`bigint expected < 2^${CURVE.nBitLength}`);
// works with order, can have different size than numToField!

@@ -826,2 +813,3 @@ return ut.numberToBytesBE(num, CURVE.nByteLength);

function prepSig(msgHash, privateKey, opts = defaultSigOpts) {
const { hash, randomBytes } = CURVE;
if (msgHash == null)

@@ -834,24 +822,16 @@ throw new Error(`sign: expected valid message hash, not "${msgHash}"`);

if (prehash)
msgHash = CURVE.hash((0, utils_js_1.ensureBytes)(msgHash));
msgHash = hash((0, utils_js_1.ensureBytes)(msgHash));
if (lowS == null)
lowS = true; // RFC6979 3.2: we skip step A, because
// Step A is ignored, since we already provide hash instead of msg
// NOTE: instead of bits2int, we calling here truncateHash, since we need
// custom truncation for stark. For other curves it is essentially same as calling bits2int + mod
// However, we cannot later call bits2octets (which is truncateHash + int2octets), since nested bits2int is broken
// for curves where nBitLength % 8 !== 0, so we unwrap it here as int2octets call.
// const bits2octets = (bits)=>int2octets(bytesToNumberBE(truncateHash(bits)))
lowS = true; // RFC6979 3.2: we skip step A, because we already provide hash
// We can't later call bits2octets, since nested bits2int is broken for curves
// with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call.
// const bits2octets = (bits) => int2octets(bits2int_modN(bits))
const h1int = bits2int_modN((0, utils_js_1.ensureBytes)(msgHash));
const h1octets = int2octets(h1int);
const d = normalizePrivateKey(privateKey);
// K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
const seedArgs = [int2octets(d), h1octets];
const d = normalizePrivateKey(privateKey); // validate private key, convert to bigint
const seedArgs = [int2octets(d), int2octets(h1int)];
// extraEntropy. RFC6979 3.6: additional k' (optional).
if (ent != null) {
// RFC6979 3.6: additional k' (optional)
if (ent === true)
ent = CURVE.randomBytes(Fp.BYTES);
const e = (0, utils_js_1.ensureBytes)(ent);
if (e.length !== Fp.BYTES)
throw new Error(`sign: Expected ${Fp.BYTES} bytes of extra data`);
seedArgs.push(e);
// K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
// Either pass as-is, or generate random bytes. Then validate for being ui8a of size BYTES
seedArgs.push((0, utils_js_1.ensureBytes)(ent === true ? randomBytes(Fp.BYTES) : ent, Fp.BYTES));
}

@@ -966,3 +946,2 @@ const seed = ut.concatBytes(...seedArgs); // Step D of RFC6979 3.2

verify,
// Point,
ProjectivePoint: Point,

@@ -969,0 +948,0 @@ Signature,

/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
// Abelian group utilities
import { validateField, nLength } from './modular.js';
import { validateObject } from './utils.js';
const _0n = BigInt(0);

@@ -124,22 +125,15 @@ const _1n = BigInt(1);

}
export function validateAbsOpts(curve) {
export function validateBasic(curve) {
validateField(curve.Fp);
for (const i of ['n', 'h']) {
const val = curve[i];
if (typeof val !== 'bigint')
throw new Error(`Invalid curve param ${i}=${val} (${typeof val})`);
}
if (!curve.Fp.isValid(curve.Gx))
throw new Error('Invalid generator X coordinate Fp element');
if (!curve.Fp.isValid(curve.Gy))
throw new Error('Invalid generator Y coordinate Fp element');
for (const i of ['nBitLength', 'nByteLength']) {
const val = curve[i];
if (val === undefined)
continue; // Optional
if (!Number.isSafeInteger(val))
throw new Error(`Invalid param ${i}=${val} (${typeof val})`);
}
validateObject(curve, {
n: 'bigint',
h: 'bigint',
Gx: 'field',
Gy: 'field',
}, {
nBitLength: 'isSafeInteger',
nByteLength: 'isSafeInteger',
});
// Set defaults
return Object.freeze({ ...nLength(curve.n, curve.nBitLength), ...curve });
}
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
// Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y²
import { mod } from './modular.js';
import { bytesToHex, bytesToNumberLE, concatBytes, ensureBytes, numberToBytesLE, } from './utils.js';
import { wNAF, validateAbsOpts, } from './curve.js';
import * as ut from './utils.js';
import { ensureBytes } from './utils.js';
import { wNAF, validateBasic } from './curve.js';
// Be friendly to bad ECMAScript parsers by not using bigint literals like 123n

@@ -12,20 +13,14 @@ const _0n = BigInt(0);

function validateOpts(curve) {
const opts = validateAbsOpts(curve);
if (typeof opts.hash !== 'function')
throw new Error('Invalid hash function');
for (const i of ['a', 'd']) {
const val = opts[i];
if (typeof val !== 'bigint')
throw new Error(`Invalid curve param ${i}=${val} (${typeof val})`);
}
for (const fn of ['randomBytes']) {
if (typeof opts[fn] !== 'function')
throw new Error(`Invalid ${fn} function`);
}
for (const fn of ['adjustScalarBytes', 'domain', 'uvRatio', 'mapToCurve']) {
if (opts[fn] === undefined)
continue; // Optional
if (typeof opts[fn] !== 'function')
throw new Error(`Invalid ${fn} function`);
}
const opts = validateBasic(curve);
ut.validateObject(curve, {
hash: 'function',
a: 'bigint',
d: 'bigint',
randomBytes: 'function',
}, {
adjustScalarBytes: 'function',
domain: 'function',
uvRatio: 'function',
mapToCurve: 'function',
});
// Set defaults

@@ -265,3 +260,3 @@ return Object.freeze({ ...opts });

normed[len - 1] = lastByte & ~0x80; // clear last bit
const y = bytesToNumberLE(normed);
const y = ut.bytesToNumberLE(normed);
if (y === _0n) {

@@ -296,3 +291,3 @@ // y=0 is allowed

const { x, y } = this.toAffine();
const bytes = numberToBytesLE(y, Fp.BYTES); // each y has 2 x values (x, -y)
const bytes = ut.numberToBytesLE(y, Fp.BYTES); // each y has 2 x values (x, -y)
bytes[bytes.length - 1] |= x & _1n ? 0x80 : 0; // when compressing, it's enough to store y

@@ -302,3 +297,3 @@ return bytes; // and use the last byte to encode sign of x

toHex() {
return bytesToHex(this.toRawBytes()); // Same as toRawBytes, but returns string.
return ut.bytesToHex(this.toRawBytes()); // Same as toRawBytes, but returns string.
}

@@ -315,3 +310,3 @@ }

function modN_LE(hash) {
return modN(bytesToNumberLE(hash));
return modN(ut.bytesToNumberLE(hash));
}

@@ -342,3 +337,3 @@ function isHex(item, err) {

function hashDomainToScalar(context = new Uint8Array(), ...msgs) {
const msg = concatBytes(...msgs);
const msg = ut.concatBytes(...msgs);
return modN_LE(cHash(domain(msg, ensureBytes(context), !!preHash)));

@@ -358,3 +353,3 @@ }

assertGE0(s); // 0 <= s < l
const res = concatBytes(R, numberToBytesLE(s, Fp.BYTES));
const res = ut.concatBytes(R, ut.numberToBytesLE(s, Fp.BYTES));
return ensureBytes(res, nByteLength * 2); // 64-byte signature

@@ -372,3 +367,3 @@ }

const R = Point.fromHex(sig.slice(0, len), false); // 0 <= R < 2^256: ZIP215 R can be >= P
const s = bytesToNumberLE(sig.slice(len, 2 * len)); // 0 <= s < l
const s = ut.bytesToNumberLE(sig.slice(len, 2 * len)); // 0 <= s < l
const SB = G.multiplyUnsafe(s);

@@ -375,0 +370,0 @@ const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg);

@@ -19,3 +19,3 @@ import { mod } from './modular.js';

if (typeof str !== 'string') {
throw new TypeError(`utf8ToBytes expected string, got ${typeof str}`);
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
}

@@ -22,0 +22,0 @@ return new TextEncoder().encode(str);

/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
// Utilities for modular arithmetics and finite fields
import { bitMask, numberToBytesBE, numberToBytesLE, bytesToNumberBE, bytesToNumberLE, ensureBytes, } from './utils.js';
import { bitMask, numberToBytesBE, numberToBytesLE, bytesToNumberBE, bytesToNumberLE, ensureBytes, validateObject, } from './utils.js';
// prettier-ignore

@@ -37,3 +37,2 @@ const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);

// Does x ^ (2 ^ power) mod p. pow2(30, 4) == 30 ^ (2 ^ 4)
// TODO: Fp version?
export function pow2(x, power, modulo) {

@@ -197,14 +196,13 @@ let res = x;

export function validateField(field) {
for (const i of ['ORDER', 'MASK']) {
if (typeof field[i] !== 'bigint')
throw new Error(`Invalid field param ${i}=${field[i]} (${typeof field[i]})`);
}
for (const i of ['BYTES', 'BITS']) {
if (typeof field[i] !== 'number')
throw new Error(`Invalid field param ${i}=${field[i]} (${typeof field[i]})`);
}
for (const i of FIELD_FIELDS) {
if (typeof field[i] !== 'function')
throw new Error(`Invalid field param ${i}=${field[i]} (${typeof field[i]})`);
}
const initial = {
ORDER: 'bigint',
MASK: 'bigint',
BYTES: 'isSafeInteger',
BITS: 'isSafeInteger',
};
const opts = FIELD_FIELDS.reduce((map, val) => {
map[val] = 'function';
return map;
}, initial);
return validateObject(field, opts);
}

@@ -211,0 +209,0 @@ // Generic field functions

/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
import { mod, pow } from './modular.js';
import { ensureBytes, numberToBytesLE, bytesToNumberLE } from './utils.js';
import { bytesToNumberLE, ensureBytes, numberToBytesLE, validateObject } from './utils.js';
const _0n = BigInt(0);
const _1n = BigInt(1);
function validateOpts(curve) {
for (const i of ['a24']) {
if (typeof curve[i] !== 'bigint')
throw new Error(`Invalid curve param ${i}=${curve[i]} (${typeof curve[i]})`);
}
for (const i of ['montgomeryBits', 'nByteLength']) {
if (curve[i] === undefined)
continue; // Optional
if (!Number.isSafeInteger(curve[i]))
throw new Error(`Invalid curve param ${i}=${curve[i]} (${typeof curve[i]})`);
}
for (const fn of ['adjustScalarBytes', 'domain', 'powPminus2']) {
if (curve[fn] === undefined)
continue; // Optional
if (typeof curve[fn] !== 'function')
throw new Error(`Invalid ${fn} function`);
}
for (const i of ['Gu']) {
if (curve[i] === undefined)
continue; // Optional
if (typeof curve[i] !== 'string')
throw new Error(`Invalid curve param ${i}=${curve[i]} (${typeof curve[i]})`);
}
validateObject(curve, {
a24: 'bigint',
}, {
montgomeryBits: 'isSafeInteger',
nByteLength: 'isSafeInteger',
adjustScalarBytes: 'function',
domain: 'function',
powPminus2: 'function',
Gu: 'string',
});
// Set defaults

@@ -43,27 +31,3 @@ return Object.freeze({ ...curve });

const powPminus2 = CURVE.powPminus2 || ((x) => pow(x, P - BigInt(2), P));
/**
* Checks for num to be in range:
* For strict == true: `0 < num < max`.
* For strict == false: `0 <= num < max`.
* Converts non-float safe numbers to bigints.
*/
function normalizeScalar(num, max, strict = true) {
if (!max)
throw new TypeError('Specify max value');
if (typeof num === 'number' && Number.isSafeInteger(num))
num = BigInt(num);
if (typeof num === 'bigint' && num < max) {
if (strict) {
if (_0n < num)
return num;
}
else {
if (_0n <= num)
return num;
}
}
throw new TypeError('Expected valid scalar: 0 < scalar < max');
}
// cswap from RFC7748
// NOTE: cswap is not from RFC7748!
// cswap from RFC7748. But it is not from RFC7748!
/*

@@ -84,2 +48,7 @@ cswap(swap, x_2, x_3):

}
function assertFieldElement(n) {
if (typeof n === 'bigint' && _0n <= n && n < P)
return n;
throw new Error('Expected valid scalar 0 < scalar < CURVE.P');
}
// x25519 from 4

@@ -93,7 +62,6 @@ /**

function montgomeryLadder(pointU, scalar) {
const { P } = CURVE;
const u = normalizeScalar(pointU, P);
const u = assertFieldElement(pointU);
// Section 5: Implementations MUST accept non-canonical values and process them as
// if they had been reduced modulo the field prime.
const k = normalizeScalar(scalar, P);
const k = assertFieldElement(scalar);
// The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519

@@ -151,3 +119,2 @@ const a24 = CURVE.a24;

function decodeUCoordinate(uEnc) {
const u = ensureBytes(uEnc, montgomeryBytes);
// Section 5: When receiving such an array, implementations of X25519

@@ -157,2 +124,3 @@ // MUST mask the most significant bit in the final byte.

// fieldLen - scalaryBytes = 1 for X448 and = 0 for X25519
const u = ensureBytes(uEnc, montgomeryBytes);
u[fieldLen - 1] &= 127; // 0b0111_1111

@@ -167,9 +135,2 @@ return bytesToNumberLE(u);

}
/**
* Computes shared secret between private key "scalar" and public key's "u" (x) coordinate.
* We can get 'y' coordinate from 'u',
* but Point.fromHex also wants 'x' coordinate oddity flag,
* and we cannot get 'x' without knowing 'v'.
* Need to add generic conversion between twisted edwards and complimentary curve for JubJub.
*/
function scalarMult(scalar, u) {

@@ -185,8 +146,3 @@ const pointU = decodeUCoordinate(u);

}
/**
* Computes public key from private.
* Executes scalar multiplication of curve's base point by scalar.
* @param scalar private key
* @returns new public key
*/
// Computes public key from private. By doing scalar multiplication of base point.
function scalarMultBase(scalar) {

@@ -193,0 +149,0 @@ return scalarMult(scalar, CURVE.Gu);

/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
// Poseidon Hash: https://eprint.iacr.org/2019/458.pdf, https://www.poseidon-hash.info
import { validateField, FpPow } from './modular.js';
import { FpPow, validateField } from './modular.js';
export function validateOpts(opts) {

@@ -5,0 +5,0 @@ const { Fp } = opts;

@@ -9,3 +9,3 @@ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */

if (!u8a(bytes))
throw new Error('Expected Uint8Array');
throw new Error('Uint8Array expected');
// pre-caching improves the speed 6x

@@ -24,3 +24,3 @@ let hex = '';

if (typeof hex !== 'string')
throw new Error('hexToNumber: expected string, got ' + typeof hex);
throw new Error('string expected, got ' + typeof hex);
// Big Endian

@@ -32,5 +32,5 @@ return BigInt(`0x${hex}`);

if (typeof hex !== 'string')
throw new Error('hexToBytes: expected string, got ' + typeof hex);
throw new Error('string expected, got ' + typeof hex);
if (hex.length % 2)
throw new Error('hexToBytes: received invalid unpadded hex ' + hex.length);
throw new Error('hex string is invalid: unpadded ' + hex.length);
const array = new Uint8Array(hex.length / 2);

@@ -42,3 +42,3 @@ for (let i = 0; i < array.length; i++) {

if (Number.isNaN(byte) || byte < 0)
throw new Error('Invalid byte sequence');
throw new Error('invalid byte sequence');
array[i] = byte;

@@ -54,3 +54,3 @@ }

if (!u8a(bytes))
throw new Error('Expected Uint8Array');
throw new Error('Uint8Array expected');
return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));

@@ -61,8 +61,3 @@ }

// Returns variable number bytes (minimal bigint encoding?)
export const numberToVarBytesBE = (n) => {
let hex = n.toString(16);
if (hex.length & 1)
hex = '0' + hex;
return hexToBytes(hex);
};
export const numberToVarBytesBE = (n) => hexToBytes(numberToHexUnpadded(n));
export function ensureBytes(hex, expectedLength) {

@@ -77,15 +72,12 @@ // Uint8Array.from() instead of hash.slice() because node.js Buffer

// Copies several Uint8Arrays into one.
export function concatBytes(...arrays) {
if (!arrays.every((b) => u8a(b)))
throw new Error('Uint8Array list expected');
if (arrays.length === 1)
return arrays[0];
const length = arrays.reduce((a, arr) => a + arr.length, 0);
const result = new Uint8Array(length);
for (let i = 0, pad = 0; i < arrays.length; i++) {
const arr = arrays[i];
result.set(arr, pad);
pad += arr.length;
}
return result;
export function concatBytes(...arrs) {
const r = new Uint8Array(arrs.reduce((sum, a) => sum + a.length, 0));
let pad = 0; // walk through each item, ensure they have proper type
arrs.forEach((a) => {
if (!u8a(a))
throw new Error('Uint8Array expected');
r.set(a, pad);
pad += a.length;
});
return r;
}

@@ -117,1 +109,30 @@ export function equalBytes(b1, b2) {

export const bitMask = (n) => (_2n << BigInt(n - 1)) - _1n;
export function validateObject(object, validators, optValidators = {}) {
const validatorFns = {
bigint: (val) => typeof val === 'bigint',
function: (val) => typeof val === 'function',
boolean: (val) => typeof val === 'boolean',
string: (val) => typeof val === 'string',
isSafeInteger: (val) => Number.isSafeInteger(val),
array: (val) => Array.isArray(val),
field: (val) => object.Fp.isValid(val),
hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen),
};
// type Key = keyof typeof validators;
const checkField = (fieldName, type, isOptional) => {
const checkVal = validatorFns[type];
if (typeof checkVal !== 'function')
throw new Error(`Invalid validator "${type}", expected function`);
const val = object[fieldName];
if (isOptional && val === undefined)
return;
if (!checkVal(val)) {
throw new Error(`Invalid param ${fieldName}=${val} (${typeof val}), expected ${type}`);
}
};
for (let [fieldName, type] of Object.entries(validators))
checkField(fieldName, type, false);
for (let [fieldName, type] of Object.entries(optValidators))
checkField(fieldName, type, true);
return object;
}

@@ -6,19 +6,19 @@ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */

import { ensureBytes } from './utils.js';
import { wNAF, validateAbsOpts, } from './curve.js';
import { wNAF, validateBasic } from './curve.js';
function validatePointOpts(curve) {
const opts = validateAbsOpts(curve);
const Fp = opts.Fp;
for (const i of ['a', 'b']) {
if (!Fp.isValid(curve[i]))
throw new Error(`Invalid curve param ${i}=${opts[i]} (${typeof opts[i]})`);
}
for (const i of ['isTorsionFree', 'clearCofactor']) {
if (curve[i] === undefined)
continue; // Optional
if (typeof curve[i] !== 'function')
throw new Error(`Invalid ${i} function`);
}
const endo = opts.endo;
const opts = validateBasic(curve);
ut.validateObject(opts, {
a: 'field',
b: 'field',
fromBytes: 'function',
toBytes: 'function',
}, {
allowedPrivateKeyLengths: 'array',
wrapPrivateKey: 'boolean',
isTorsionFree: 'function',
clearCofactor: 'function',
});
const { endo, Fp, a } = opts;
if (endo) {
if (!Fp.eql(opts.a, Fp.ZERO)) {
if (!Fp.eql(a, Fp.ZERO)) {
throw new Error('Endomorphism can only be defined for Koblitz curves that have a=0');

@@ -32,7 +32,2 @@ }

}
if (typeof opts.fromBytes !== 'function')
throw new Error('Invalid fromBytes function');
if (typeof opts.toBytes !== 'function')
throw new Error('Invalid fromBytes function');
// Set defaults
return Object.freeze({ ...opts });

@@ -118,35 +113,24 @@ }

}
/**
* Validates if a private key is valid and converts it to bigint form.
* Supports two options, that are passed when CURVE is initialized:
* - `normalizePrivateKey()` executed before all checks
* - `wrapPrivateKey` when true, executed after most checks, but before `0 < key < n`
*/
// Validates if priv key is valid and converts it to bigint.
// Supports options CURVE.normalizePrivateKey and CURVE.wrapPrivateKey.
function normalizePrivateKey(key) {
const { normalizePrivateKey: custom, nByteLength: groupLen, wrapPrivateKey, n } = CURVE;
if (typeof custom === 'function')
key = custom(key);
const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n } = CURVE;
if (lengths && typeof key !== 'bigint') {
if (key instanceof Uint8Array)
key = ut.bytesToHex(key);
// Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes
if (typeof key !== 'string' || !lengths.includes(key.length))
throw new Error('Invalid key');
key = key.padStart(nByteLength * 2, '0');
}
let num;
if (typeof key === 'bigint') {
// Curve order check is done below
num = key;
try {
num = typeof key === 'bigint' ? key : ut.bytesToNumberBE(ensureBytes(key, nByteLength));
}
else if (typeof key === 'string') {
if (key.length !== 2 * groupLen)
throw new Error(`must be ${groupLen} bytes`);
// Validates individual octets
num = ut.bytesToNumberBE(ensureBytes(key));
catch (error) {
throw new Error(`private key must be ${nByteLength} bytes, hex or bigint, not ${typeof key}`);
}
else if (key instanceof Uint8Array) {
if (key.length !== groupLen)
throw new Error(`must be ${groupLen} bytes`);
num = ut.bytesToNumberBE(key);
}
else {
throw new Error('private key must be bytes, hex or bigint, not ' + typeof key);
}
// Useful for curves with cofactor != 1
if (wrapPrivateKey)
num = mod.mod(num, n);
assertGE(num);
num = mod.mod(num, n); // disabled by default, enabled for BLS
assertGE(num); // num in range [1..N-1]
return num;

@@ -505,10 +489,12 @@ }

function validateOpts(curve) {
const opts = validateAbsOpts(curve);
if (typeof opts.hash !== 'function' || !Number.isSafeInteger(opts.hash.outputLen))
throw new Error('Invalid hash function');
if (typeof opts.hmac !== 'function')
throw new Error('Invalid hmac function');
if (typeof opts.randomBytes !== 'function')
throw new Error('Invalid randomBytes function');
// Set defaults
const opts = validateBasic(curve);
ut.validateObject(opts, {
hash: 'hash',
hmac: 'function',
randomBytes: 'function',
}, {
bits2int: 'function',
bits2int_modN: 'function',
lowS: 'boolean',
});
return Object.freeze({ lowS: true, ...opts });

@@ -622,3 +608,3 @@ }

else {
throw new Error(`Point.fromHex: received invalid point. Expected ${compressedLen} compressed bytes or ${uncompressedLen} uncompressed bytes, not ${len}`);
throw new Error(`Point of length ${len} was invalid. Expected ${compressedLen} compressed bytes or ${uncompressedLen} uncompressed bytes`);
}

@@ -685,3 +671,3 @@ },

const u2 = modN(s * ir); // sr^-1
const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2); // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1)
const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2); // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1)
if (!Q)

@@ -809,5 +795,6 @@ throw new Error('point at infinify'); // unsafe is fine: no priv data leaked

if (typeof num !== 'bigint')
throw new Error('Expected bigint');
throw new Error('bigint expected');
if (!(_0n <= num && num < ORDER_MASK))
throw new Error(`Expected number < 2^${CURVE.nBitLength}`);
// n in [0..ORDER_MASK-1]
throw new Error(`bigint expected < 2^${CURVE.nBitLength}`);
// works with order, can have different size than numToField!

@@ -822,2 +809,3 @@ return ut.numberToBytesBE(num, CURVE.nByteLength);

function prepSig(msgHash, privateKey, opts = defaultSigOpts) {
const { hash, randomBytes } = CURVE;
if (msgHash == null)

@@ -830,24 +818,16 @@ throw new Error(`sign: expected valid message hash, not "${msgHash}"`);

if (prehash)
msgHash = CURVE.hash(ensureBytes(msgHash));
msgHash = hash(ensureBytes(msgHash));
if (lowS == null)
lowS = true; // RFC6979 3.2: we skip step A, because
// Step A is ignored, since we already provide hash instead of msg
// NOTE: instead of bits2int, we calling here truncateHash, since we need
// custom truncation for stark. For other curves it is essentially same as calling bits2int + mod
// However, we cannot later call bits2octets (which is truncateHash + int2octets), since nested bits2int is broken
// for curves where nBitLength % 8 !== 0, so we unwrap it here as int2octets call.
// const bits2octets = (bits)=>int2octets(bytesToNumberBE(truncateHash(bits)))
lowS = true; // RFC6979 3.2: we skip step A, because we already provide hash
// We can't later call bits2octets, since nested bits2int is broken for curves
// with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call.
// const bits2octets = (bits) => int2octets(bits2int_modN(bits))
const h1int = bits2int_modN(ensureBytes(msgHash));
const h1octets = int2octets(h1int);
const d = normalizePrivateKey(privateKey);
// K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
const seedArgs = [int2octets(d), h1octets];
const d = normalizePrivateKey(privateKey); // validate private key, convert to bigint
const seedArgs = [int2octets(d), int2octets(h1int)];
// extraEntropy. RFC6979 3.6: additional k' (optional).
if (ent != null) {
// RFC6979 3.6: additional k' (optional)
if (ent === true)
ent = CURVE.randomBytes(Fp.BYTES);
const e = ensureBytes(ent);
if (e.length !== Fp.BYTES)
throw new Error(`sign: Expected ${Fp.BYTES} bytes of extra data`);
seedArgs.push(e);
// K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
// Either pass as-is, or generate random bytes. Then validate for being ui8a of size BYTES
seedArgs.push(ensureBytes(ent === true ? randomBytes(Fp.BYTES) : ent, Fp.BYTES));
}

@@ -962,3 +942,2 @@ const seed = ut.concatBytes(...seedArgs); // Step D of RFC6979 3.2

verify,
// Point,
ProjectivePoint: Point,

@@ -965,0 +944,0 @@ Signature,

@@ -11,3 +11,3 @@ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */

b: BigInt('0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4'),
// Field over which we'll do calculations; 2n**224n - 2n**96n + 1n
// Field over which we'll do calculations;
Fp: Fp(BigInt('0xffffffffffffffffffffffffffffffff000000000000000000000001')),

@@ -14,0 +14,0 @@ // Curve order, total count of valid points in the field

/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
import { createCurve } from './_shortw_utils.js';
import { sha512 } from '@noble/hashes/sha512';
import { bytesToHex } from './abstract/utils.js';
import { Fp as Field } from './abstract/modular.js';

@@ -36,14 +35,3 @@ import { mapToCurveSimpleSWU } from './abstract/weierstrass.js';

lowS: false,
// P521 keys could be 130, 131, 132 bytes. We normalize to 132 bytes.
// Does not replace validation; invalid keys would still be rejected.
normalizePrivateKey(key) {
if (typeof key === 'bigint')
return key;
if (key instanceof Uint8Array)
key = bytesToHex(key);
if (typeof key !== 'string' || !([130, 131, 132].includes(key.length))) {
throw new Error('Invalid key');
}
return key.padStart(66 * 2, '0'); // ensure it's always 132 bytes
},
allowedPrivateKeyLengths: [130, 131, 132] // P521 keys are variable-length. Normalize to 132b
}, sha512);

@@ -50,0 +38,0 @@ export const secp521r1 = P521;

@@ -6,3 +6,3 @@ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */

import { mapToCurveSimpleSWU } from './abstract/weierstrass.js';
import { ensureBytes, concatBytes, bytesToNumberBE as bytesToNum, numberToBytesBE, } from './abstract/utils.js';
import { ensureBytes, concatBytes, bytesToNumberBE as bytesToInt, numberToBytesBE, } from './abstract/utils.js';
import { randomBytes } from '@noble/hashes/utils';

@@ -116,16 +116,13 @@ import * as htf from './abstract/hash-to-curve.js';

}
const toRawX = (point) => point.toRawBytes(true).slice(1);
const pointToBytes = (point) => point.toRawBytes(true).slice(1);
const numTo32b = (n) => numberToBytesBE(n, 32);
const modN = (x) => mod(x, secp256k1N);
const _Point = secp256k1.ProjectivePoint;
const Gmul = (priv) => _Point.fromPrivateKey(priv);
const GmulAdd = (Q, a, b) => _Point.BASE.multiplyAndAddUnsafe(Q, a, b);
function schnorrGetScalar(priv) {
// Let d' = int(sk)
// Fail if d' = 0 or d' ≥ n
// Let P = d'⋅G
// Let d = d' if has_even_y(P), otherwise let d = n - d' .
const point = Gmul(priv);
const scalar = point.hasEvenY() ? priv : modN(-priv);
return { point, scalar, x: toRawX(point) };
const Point = secp256k1.ProjectivePoint;
const GmulAdd = (Q, a, b) => Point.BASE.multiplyAndAddUnsafe(Q, a, b);
const hex32ToInt = (key) => bytesToInt(ensureBytes(key, 32));
function schnorrGetExtPubKey(priv) {
let d = typeof priv === 'bigint' ? priv : hex32ToInt(priv);
const point = Point.fromPrivateKey(d); // P = d'⋅G; 0 < d' < n check is done inside
const scalar = point.hasEvenY() ? d : modN(-d); // d = d' if has_even_y(P), otherwise d = n-d'
return { point, scalar, bytes: pointToBytes(point) };
}

@@ -139,3 +136,3 @@ function lift_x(x) {

y = mod(-y, secp256k1P); // Return the unique point P such that x(P) = x and
const p = new _Point(x, y, _1n); // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise.
const p = new Point(x, y, _1n); // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise.
p.assertValidity();

@@ -145,28 +142,22 @@ return p;

function challenge(...args) {
return modN(bytesToNum(taggedHash(TAGS.challenge, ...args)));
return modN(bytesToInt(taggedHash(TAGS.challenge, ...args)));
}
// Schnorr's pubkey is just `x` of Point (BIP340)
function schnorrGetPublicKey(privateKey) {
return toRawX(Gmul(privateKey)); // Let d' = int(sk). Fail if d' = 0 or d' ≥ n. Return bytes(d'⋅G)
return schnorrGetExtPubKey(privateKey).bytes; // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G)
}
/**
* Synchronously creates Schnorr signature. Improved security: verifies itself before
* producing an output.
* @param msg message (not message hash)
* @param privateKey private key
* @param auxRand random bytes that would be added to k. Bad RNG won't break it.
*/
// Creates Schnorr signature as per BIP340. Verifies itself before returning anything.
// auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous
function schnorrSign(message, privateKey, auxRand = randomBytes(32)) {
if (message == null)
throw new Error(`sign: Expected valid message, not "${message}"`);
const m = ensureBytes(message);
// checks for isWithinCurveOrder
const { x: px, scalar: d } = schnorrGetScalar(bytesToNum(ensureBytes(privateKey, 32)));
const m = ensureBytes(message); // checks for isWithinCurveOrder
const { bytes: px, scalar: d } = schnorrGetExtPubKey(privateKey);
const a = ensureBytes(auxRand, 32); // Auxiliary random data a: a 32-byte array
// TODO: replace with proper xor?
const t = numTo32b(d ^ bytesToNum(taggedHash(TAGS.aux, a))); // Let t be the byte-wise xor of bytes(d) and hash/aux(a)
const t = numTo32b(d ^ bytesToInt(taggedHash(TAGS.aux, a))); // Let t be the byte-wise xor of bytes(d) and hash/aux(a)
const rand = taggedHash(TAGS.nonce, t, px, m); // Let rand = hash/nonce(t || bytes(P) || m)
const k_ = modN(bytesToNum(rand)); // Let k' = int(rand) mod n
const k_ = modN(bytesToInt(rand)); // Let k' = int(rand) mod n
if (k_ === _0n)
throw new Error('sign failed: k is zero'); // Fail if k' = 0.
const { point: R, x: rx, scalar: k } = schnorrGetScalar(k_); // Let R = k'⋅G.
const { point: R, bytes: rx, scalar: k } = schnorrGetExtPubKey(k_); // Let R = k'⋅G.
const e = challenge(rx, px, m); // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n.

@@ -186,12 +177,12 @@ const sig = new Uint8Array(64); // Let sig = bytes(R) || bytes((k + ed) mod n).

try {
const P = lift_x(bytesToNum(ensureBytes(publicKey, 32))); // P = lift_x(int(pk)); fail if that fails
const P = lift_x(hex32ToInt(publicKey)); // P = lift_x(int(pk)); fail if that fails
const sig = ensureBytes(signature, 64);
const r = bytesToNum(sig.subarray(0, 32)); // Let r = int(sig[0:32]); fail if r ≥ p.
const r = bytesToInt(sig.subarray(0, 32)); // Let r = int(sig[0:32]); fail if r ≥ p.
if (!fe(r))
return false;
const s = bytesToNum(sig.subarray(32, 64)); // Let s = int(sig[32:64]); fail if s ≥ n.
const s = bytesToInt(sig.subarray(32, 64)); // Let s = int(sig[32:64]); fail if s ≥ n.
if (!ge(s))
return false;
const m = ensureBytes(message);
const e = challenge(numTo32b(r), toRawX(P), m); // int(challenge(bytes(r)||bytes(P)||m)) mod n
const e = challenge(numTo32b(r), pointToBytes(P), m); // int(challenge(bytes(r)||bytes(P)||m)) mod n
const R = GmulAdd(P, s, modN(-e)); // R = s⋅G - e⋅P

@@ -207,7 +198,14 @@ if (!R || !R.hasEvenY() || R.toAffine().x !== r)

export const schnorr = {
// Schnorr's pubkey is just `x` of Point (BIP340)
getPublicKey: schnorrGetPublicKey,
sign: schnorrSign,
verify: schnorrVerify,
utils: { lift_x, int: bytesToNum, taggedHash },
utils: {
getExtendedPublicKey: schnorrGetExtPubKey,
lift_x,
pointToBytes,
numberToBytesBE,
bytesToNumberBE: bytesToInt,
taggedHash,
mod,
},
};

@@ -214,0 +212,0 @@ const isoMap = htf.isogenyMap(Fp, [

@@ -98,3 +98,3 @@ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */

}
function getPublicKey0x(privKey, isCompressed) {
function getPublicKey0x(privKey, isCompressed = false) {
return starkCurve.getPublicKey(normalizePrivateKey(privKey), isCompressed);

@@ -101,0 +101,0 @@ }

@@ -12,7 +12,7 @@ export declare const P192: Readonly<{

readonly Gy: bigint;
readonly wrapPrivateKey?: boolean | undefined;
readonly allowInfinityPoint?: boolean | undefined;
readonly a: bigint;
readonly b: bigint;
readonly normalizePrivateKey?: ((key: import("./abstract/utils.js").PrivKey) => import("./abstract/utils.js").PrivKey) | undefined;
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
readonly wrapPrivateKey?: boolean | undefined;
readonly endo?: {

@@ -29,6 +29,6 @@ beta: bigint;

readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => import("./abstract/weierstrass.js").ProjPointType<bigint>) | undefined;
lowS: boolean;
readonly hash: import("./abstract/utils.js").CHash;
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
lowS: boolean;
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;

@@ -64,7 +64,7 @@ readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;

readonly Gy: bigint;
readonly wrapPrivateKey?: boolean | undefined;
readonly allowInfinityPoint?: boolean | undefined;
readonly a: bigint;
readonly b: bigint;
readonly normalizePrivateKey?: ((key: import("./abstract/utils.js").PrivKey) => import("./abstract/utils.js").PrivKey) | undefined;
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
readonly wrapPrivateKey?: boolean | undefined;
readonly endo?: {

@@ -81,6 +81,6 @@ beta: bigint;

readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => import("./abstract/weierstrass.js").ProjPointType<bigint>) | undefined;
lowS: boolean;
readonly hash: import("./abstract/utils.js").CHash;
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
lowS: boolean;
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;

@@ -87,0 +87,0 @@ readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;

@@ -12,7 +12,7 @@ export declare const P224: Readonly<{

readonly Gy: bigint;
readonly wrapPrivateKey?: boolean | undefined;
readonly allowInfinityPoint?: boolean | undefined;
readonly a: bigint;
readonly b: bigint;
readonly normalizePrivateKey?: ((key: import("./abstract/utils.js").PrivKey) => import("./abstract/utils.js").PrivKey) | undefined;
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
readonly wrapPrivateKey?: boolean | undefined;
readonly endo?: {

@@ -29,6 +29,6 @@ beta: bigint;

readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => import("./abstract/weierstrass.js").ProjPointType<bigint>) | undefined;
lowS: boolean;
readonly hash: import("./abstract/utils.js").CHash;
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
lowS: boolean;
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;

@@ -64,7 +64,7 @@ readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;

readonly Gy: bigint;
readonly wrapPrivateKey?: boolean | undefined;
readonly allowInfinityPoint?: boolean | undefined;
readonly a: bigint;
readonly b: bigint;
readonly normalizePrivateKey?: ((key: import("./abstract/utils.js").PrivKey) => import("./abstract/utils.js").PrivKey) | undefined;
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
readonly wrapPrivateKey?: boolean | undefined;
readonly endo?: {

@@ -81,6 +81,6 @@ beta: bigint;

readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => import("./abstract/weierstrass.js").ProjPointType<bigint>) | undefined;
lowS: boolean;
readonly hash: import("./abstract/utils.js").CHash;
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
lowS: boolean;
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;

@@ -87,0 +87,0 @@ readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;

@@ -14,3 +14,3 @@ "use strict";

b: BigInt('0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4'),
// Field over which we'll do calculations; 2n**224n - 2n**96n + 1n
// Field over which we'll do calculations;
Fp: (0, modular_js_1.Fp)(BigInt('0xffffffffffffffffffffffffffffffff000000000000000000000001')),

@@ -17,0 +17,0 @@ // Curve order, total count of valid points in the field

@@ -13,7 +13,7 @@ import * as htf from './abstract/hash-to-curve.js';

readonly Gy: bigint;
readonly wrapPrivateKey?: boolean | undefined;
readonly allowInfinityPoint?: boolean | undefined;
readonly a: bigint;
readonly b: bigint;
readonly normalizePrivateKey?: ((key: import("./abstract/utils.js").PrivKey) => import("./abstract/utils.js").PrivKey) | undefined;
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
readonly wrapPrivateKey?: boolean | undefined;
readonly endo?: {

@@ -30,6 +30,6 @@ beta: bigint;

readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => import("./abstract/weierstrass.js").ProjPointType<bigint>) | undefined;
lowS: boolean;
readonly hash: import("./abstract/utils.js").CHash;
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
lowS: boolean;
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;

@@ -65,7 +65,7 @@ readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;

readonly Gy: bigint;
readonly wrapPrivateKey?: boolean | undefined;
readonly allowInfinityPoint?: boolean | undefined;
readonly a: bigint;
readonly b: bigint;
readonly normalizePrivateKey?: ((key: import("./abstract/utils.js").PrivKey) => import("./abstract/utils.js").PrivKey) | undefined;
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
readonly wrapPrivateKey?: boolean | undefined;
readonly endo?: {

@@ -82,6 +82,6 @@ beta: bigint;

readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => import("./abstract/weierstrass.js").ProjPointType<bigint>) | undefined;
lowS: boolean;
readonly hash: import("./abstract/utils.js").CHash;
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
lowS: boolean;
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;

@@ -88,0 +88,0 @@ readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;

@@ -13,7 +13,7 @@ import * as htf from './abstract/hash-to-curve.js';

readonly Gy: bigint;
readonly wrapPrivateKey?: boolean | undefined;
readonly allowInfinityPoint?: boolean | undefined;
readonly a: bigint;
readonly b: bigint;
readonly normalizePrivateKey?: ((key: import("./abstract/utils.js").PrivKey) => import("./abstract/utils.js").PrivKey) | undefined;
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
readonly wrapPrivateKey?: boolean | undefined;
readonly endo?: {

@@ -30,6 +30,6 @@ beta: bigint;

readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => import("./abstract/weierstrass.js").ProjPointType<bigint>) | undefined;
lowS: boolean;
readonly hash: import("./abstract/utils.js").CHash;
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
lowS: boolean;
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;

@@ -65,7 +65,7 @@ readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;

readonly Gy: bigint;
readonly wrapPrivateKey?: boolean | undefined;
readonly allowInfinityPoint?: boolean | undefined;
readonly a: bigint;
readonly b: bigint;
readonly normalizePrivateKey?: ((key: import("./abstract/utils.js").PrivKey) => import("./abstract/utils.js").PrivKey) | undefined;
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
readonly wrapPrivateKey?: boolean | undefined;
readonly endo?: {

@@ -82,6 +82,6 @@ beta: bigint;

readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => import("./abstract/weierstrass.js").ProjPointType<bigint>) | undefined;
lowS: boolean;
readonly hash: import("./abstract/utils.js").CHash;
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
lowS: boolean;
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;

@@ -88,0 +88,0 @@ readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;

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

import { PrivKey } from './abstract/utils.js';
import * as htf from './abstract/hash-to-curve.js';

@@ -14,7 +13,7 @@ export declare const P521: Readonly<{

readonly Gy: bigint;
readonly wrapPrivateKey?: boolean | undefined;
readonly allowInfinityPoint?: boolean | undefined;
readonly a: bigint;
readonly b: bigint;
readonly normalizePrivateKey?: ((key: PrivKey) => PrivKey) | undefined;
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
readonly wrapPrivateKey?: boolean | undefined;
readonly endo?: {

@@ -31,12 +30,12 @@ beta: bigint;

readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => import("./abstract/weierstrass.js").ProjPointType<bigint>) | undefined;
lowS: boolean;
readonly hash: import("./abstract/utils.js").CHash;
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
lowS: boolean;
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;
readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;
}>;
getPublicKey: (privateKey: PrivKey, isCompressed?: boolean | undefined) => Uint8Array;
getSharedSecret: (privateA: PrivKey, publicB: import("./abstract/utils.js").Hex, isCompressed?: boolean | undefined) => Uint8Array;
sign: (msgHash: import("./abstract/utils.js").Hex, privKey: PrivKey, opts?: import("./abstract/weierstrass.js").SignOpts | undefined) => import("./abstract/weierstrass.js").SignatureType;
getPublicKey: (privateKey: import("./abstract/utils.js").PrivKey, isCompressed?: boolean | undefined) => Uint8Array;
getSharedSecret: (privateA: import("./abstract/utils.js").PrivKey, publicB: import("./abstract/utils.js").Hex, isCompressed?: boolean | undefined) => Uint8Array;
sign: (msgHash: import("./abstract/utils.js").Hex, privKey: import("./abstract/utils.js").PrivKey, opts?: import("./abstract/weierstrass.js").SignOpts | undefined) => import("./abstract/weierstrass.js").SignatureType;
verify: (signature: import("./abstract/utils.js").Hex | {

@@ -49,4 +48,4 @@ r: bigint;

utils: {
_normalizePrivateKey: (key: PrivKey) => bigint;
isValidPrivateKey(privateKey: PrivKey): boolean;
_normalizePrivateKey: (key: import("./abstract/utils.js").PrivKey) => bigint;
isValidPrivateKey(privateKey: import("./abstract/utils.js").PrivKey): boolean;
hashToPrivateKey: (hash: import("./abstract/utils.js").Hex) => Uint8Array;

@@ -67,7 +66,7 @@ randomPrivateKey: () => Uint8Array;

readonly Gy: bigint;
readonly wrapPrivateKey?: boolean | undefined;
readonly allowInfinityPoint?: boolean | undefined;
readonly a: bigint;
readonly b: bigint;
readonly normalizePrivateKey?: ((key: PrivKey) => PrivKey) | undefined;
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
readonly wrapPrivateKey?: boolean | undefined;
readonly endo?: {

@@ -84,12 +83,12 @@ beta: bigint;

readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => import("./abstract/weierstrass.js").ProjPointType<bigint>) | undefined;
lowS: boolean;
readonly hash: import("./abstract/utils.js").CHash;
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
lowS: boolean;
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;
readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;
}>;
getPublicKey: (privateKey: PrivKey, isCompressed?: boolean | undefined) => Uint8Array;
getSharedSecret: (privateA: PrivKey, publicB: import("./abstract/utils.js").Hex, isCompressed?: boolean | undefined) => Uint8Array;
sign: (msgHash: import("./abstract/utils.js").Hex, privKey: PrivKey, opts?: import("./abstract/weierstrass.js").SignOpts | undefined) => import("./abstract/weierstrass.js").SignatureType;
getPublicKey: (privateKey: import("./abstract/utils.js").PrivKey, isCompressed?: boolean | undefined) => Uint8Array;
getSharedSecret: (privateA: import("./abstract/utils.js").PrivKey, publicB: import("./abstract/utils.js").Hex, isCompressed?: boolean | undefined) => Uint8Array;
sign: (msgHash: import("./abstract/utils.js").Hex, privKey: import("./abstract/utils.js").PrivKey, opts?: import("./abstract/weierstrass.js").SignOpts | undefined) => import("./abstract/weierstrass.js").SignatureType;
verify: (signature: import("./abstract/utils.js").Hex | {

@@ -102,4 +101,4 @@ r: bigint;

utils: {
_normalizePrivateKey: (key: PrivKey) => bigint;
isValidPrivateKey(privateKey: PrivKey): boolean;
_normalizePrivateKey: (key: import("./abstract/utils.js").PrivKey) => bigint;
isValidPrivateKey(privateKey: import("./abstract/utils.js").PrivKey): boolean;
hashToPrivateKey: (hash: import("./abstract/utils.js").Hex) => Uint8Array;

@@ -106,0 +105,0 @@ randomPrivateKey: () => Uint8Array;

@@ -7,3 +7,2 @@ "use strict";

const sha512_1 = require("@noble/hashes/sha512");
const utils_js_1 = require("./abstract/utils.js");
const modular_js_1 = require("./abstract/modular.js");

@@ -40,14 +39,3 @@ const weierstrass_js_1 = require("./abstract/weierstrass.js");

lowS: false,
// P521 keys could be 130, 131, 132 bytes. We normalize to 132 bytes.
// Does not replace validation; invalid keys would still be rejected.
normalizePrivateKey(key) {
if (typeof key === 'bigint')
return key;
if (key instanceof Uint8Array)
key = (0, utils_js_1.bytesToHex)(key);
if (typeof key !== 'string' || !([130, 131, 132].includes(key.length))) {
throw new Error('Invalid key');
}
return key.padStart(66 * 2, '0'); // ensure it's always 132 bytes
},
allowedPrivateKeyLengths: [130, 131, 132] // P521 keys are variable-length. Normalize to 132b
}, sha512_1.sha512);

@@ -54,0 +42,0 @@ exports.secp521r1 = exports.P521;

@@ -0,3 +1,4 @@

import { mod } from './abstract/modular.js';
import { ProjPointType as PointType } from './abstract/weierstrass.js';
import { Hex, bytesToNumberBE as bytesToNum, PrivKey } from './abstract/utils.js';
import { Hex, bytesToNumberBE as bytesToInt, PrivKey } from './abstract/utils.js';
import * as htf from './abstract/hash-to-curve.js';

@@ -15,7 +16,7 @@ export declare const secp256k1: Readonly<{

readonly Gy: bigint;
readonly wrapPrivateKey?: boolean | undefined;
readonly allowInfinityPoint?: boolean | undefined;
readonly a: bigint;
readonly b: bigint;
readonly normalizePrivateKey?: ((key: PrivKey) => PrivKey) | undefined;
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
readonly wrapPrivateKey?: boolean | undefined;
readonly endo?: {

@@ -32,6 +33,6 @@ beta: bigint;

readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: PointType<bigint>) => PointType<bigint>) | undefined;
lowS: boolean;
readonly hash: import("./abstract/utils.js").CHash;
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
lowS: boolean;
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;

@@ -57,13 +58,11 @@ readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;

declare function taggedHash(tag: string, ...messages: Uint8Array[]): Uint8Array;
declare function schnorrGetExtPubKey(priv: PrivKey): {
point: PointType<bigint>;
scalar: bigint;
bytes: Uint8Array;
};
declare function lift_x(x: bigint): PointType<bigint>;
declare function schnorrGetPublicKey(privateKey: PrivKey): Uint8Array;
declare function schnorrGetPublicKey(privateKey: Hex): Uint8Array;
declare function schnorrSign(message: Hex, privateKey: PrivKey, auxRand?: Hex): Uint8Array;
/**
* Synchronously creates Schnorr signature. Improved security: verifies itself before
* producing an output.
* @param msg message (not message hash)
* @param privateKey private key
* @param auxRand random bytes that would be added to k. Bad RNG won't break it.
*/
declare function schnorrSign(message: Hex, privateKey: Hex, auxRand?: Hex): Uint8Array;
/**
* Verifies Schnorr signature synchronously.

@@ -77,5 +76,9 @@ */

utils: {
getExtendedPublicKey: typeof schnorrGetExtPubKey;
lift_x: typeof lift_x;
int: typeof bytesToNum;
pointToBytes: (point: PointType<bigint>) => Uint8Array;
numberToBytesBE: (n: bigint, len: number) => Uint8Array;
bytesToNumberBE: typeof bytesToInt;
taggedHash: typeof taggedHash;
mod: typeof mod;
};

@@ -82,0 +85,0 @@ };

@@ -118,16 +118,13 @@ "use strict";

}
const toRawX = (point) => point.toRawBytes(true).slice(1);
const pointToBytes = (point) => point.toRawBytes(true).slice(1);
const numTo32b = (n) => (0, utils_js_1.numberToBytesBE)(n, 32);
const modN = (x) => (0, modular_js_1.mod)(x, secp256k1N);
const _Point = exports.secp256k1.ProjectivePoint;
const Gmul = (priv) => _Point.fromPrivateKey(priv);
const GmulAdd = (Q, a, b) => _Point.BASE.multiplyAndAddUnsafe(Q, a, b);
function schnorrGetScalar(priv) {
// Let d' = int(sk)
// Fail if d' = 0 or d' ≥ n
// Let P = d'⋅G
// Let d = d' if has_even_y(P), otherwise let d = n - d' .
const point = Gmul(priv);
const scalar = point.hasEvenY() ? priv : modN(-priv);
return { point, scalar, x: toRawX(point) };
const Point = exports.secp256k1.ProjectivePoint;
const GmulAdd = (Q, a, b) => Point.BASE.multiplyAndAddUnsafe(Q, a, b);
const hex32ToInt = (key) => (0, utils_js_1.bytesToNumberBE)((0, utils_js_1.ensureBytes)(key, 32));
function schnorrGetExtPubKey(priv) {
let d = typeof priv === 'bigint' ? priv : hex32ToInt(priv);
const point = Point.fromPrivateKey(d); // P = d'⋅G; 0 < d' < n check is done inside
const scalar = point.hasEvenY() ? d : modN(-d); // d = d' if has_even_y(P), otherwise d = n-d'
return { point, scalar, bytes: pointToBytes(point) };
}

@@ -141,3 +138,3 @@ function lift_x(x) {

y = (0, modular_js_1.mod)(-y, secp256k1P); // Return the unique point P such that x(P) = x and
const p = new _Point(x, y, _1n); // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise.
const p = new Point(x, y, _1n); // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise.
p.assertValidity();

@@ -149,20 +146,14 @@ return p;

}
// Schnorr's pubkey is just `x` of Point (BIP340)
function schnorrGetPublicKey(privateKey) {
return toRawX(Gmul(privateKey)); // Let d' = int(sk). Fail if d' = 0 or d' ≥ n. Return bytes(d'⋅G)
return schnorrGetExtPubKey(privateKey).bytes; // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G)
}
/**
* Synchronously creates Schnorr signature. Improved security: verifies itself before
* producing an output.
* @param msg message (not message hash)
* @param privateKey private key
* @param auxRand random bytes that would be added to k. Bad RNG won't break it.
*/
// Creates Schnorr signature as per BIP340. Verifies itself before returning anything.
// auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous
function schnorrSign(message, privateKey, auxRand = (0, utils_1.randomBytes)(32)) {
if (message == null)
throw new Error(`sign: Expected valid message, not "${message}"`);
const m = (0, utils_js_1.ensureBytes)(message);
// checks for isWithinCurveOrder
const { x: px, scalar: d } = schnorrGetScalar((0, utils_js_1.bytesToNumberBE)((0, utils_js_1.ensureBytes)(privateKey, 32)));
const m = (0, utils_js_1.ensureBytes)(message); // checks for isWithinCurveOrder
const { bytes: px, scalar: d } = schnorrGetExtPubKey(privateKey);
const a = (0, utils_js_1.ensureBytes)(auxRand, 32); // Auxiliary random data a: a 32-byte array
// TODO: replace with proper xor?
const t = numTo32b(d ^ (0, utils_js_1.bytesToNumberBE)(taggedHash(TAGS.aux, a))); // Let t be the byte-wise xor of bytes(d) and hash/aux(a)

@@ -173,3 +164,3 @@ const rand = taggedHash(TAGS.nonce, t, px, m); // Let rand = hash/nonce(t || bytes(P) || m)

throw new Error('sign failed: k is zero'); // Fail if k' = 0.
const { point: R, x: rx, scalar: k } = schnorrGetScalar(k_); // Let R = k'⋅G.
const { point: R, bytes: rx, scalar: k } = schnorrGetExtPubKey(k_); // Let R = k'⋅G.
const e = challenge(rx, px, m); // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n.

@@ -189,3 +180,3 @@ const sig = new Uint8Array(64); // Let sig = bytes(R) || bytes((k + ed) mod n).

try {
const P = lift_x((0, utils_js_1.bytesToNumberBE)((0, utils_js_1.ensureBytes)(publicKey, 32))); // P = lift_x(int(pk)); fail if that fails
const P = lift_x(hex32ToInt(publicKey)); // P = lift_x(int(pk)); fail if that fails
const sig = (0, utils_js_1.ensureBytes)(signature, 64);

@@ -199,3 +190,3 @@ const r = (0, utils_js_1.bytesToNumberBE)(sig.subarray(0, 32)); // Let r = int(sig[0:32]); fail if r ≥ p.

const m = (0, utils_js_1.ensureBytes)(message);
const e = challenge(numTo32b(r), toRawX(P), m); // int(challenge(bytes(r)||bytes(P)||m)) mod n
const e = challenge(numTo32b(r), pointToBytes(P), m); // int(challenge(bytes(r)||bytes(P)||m)) mod n
const R = GmulAdd(P, s, modN(-e)); // R = s⋅G - e⋅P

@@ -211,7 +202,14 @@ if (!R || !R.hasEvenY() || R.toAffine().x !== r)

exports.schnorr = {
// Schnorr's pubkey is just `x` of Point (BIP340)
getPublicKey: schnorrGetPublicKey,
sign: schnorrSign,
verify: schnorrVerify,
utils: { lift_x, int: utils_js_1.bytesToNumberBE, taggedHash },
utils: {
getExtendedPublicKey: schnorrGetExtPubKey,
lift_x,
pointToBytes,
numberToBytesBE: utils_js_1.numberToBytesBE,
bytesToNumberBE: utils_js_1.bytesToNumberBE,
taggedHash,
mod: modular_js_1.mod,
},
};

@@ -218,0 +216,0 @@ const isoMap = htf.isogenyMap(Fp, [

@@ -19,7 +19,7 @@ import { ProjPointType } from './abstract/weierstrass.js';

readonly Gy: bigint;
readonly wrapPrivateKey?: boolean | undefined;
readonly allowInfinityPoint?: boolean | undefined;
readonly a: bigint;
readonly b: bigint;
readonly normalizePrivateKey?: ((key: cutils.PrivKey) => cutils.PrivKey) | undefined;
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
readonly wrapPrivateKey?: boolean | undefined;
readonly endo?: {

@@ -36,6 +36,6 @@ beta: bigint;

readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: ProjPointType<bigint>) => ProjPointType<bigint>) | undefined;
lowS: boolean;
readonly hash: cutils.CHash;
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
lowS: boolean;
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;

@@ -42,0 +42,0 @@ readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;

@@ -101,3 +101,3 @@ "use strict";

}
function getPublicKey0x(privKey, isCompressed) {
function getPublicKey0x(privKey, isCompressed = false) {
return exports.starkCurve.getPublicKey(normalizePrivateKey(privKey), isCompressed);

@@ -104,0 +104,0 @@ }

{
"name": "@noble/curves",
"version": "0.6.0",
"version": "0.6.1",
"description": "Minimal, auditable JS implementation of elliptic curve cryptography",

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

"scripts": {
"bench": "cd benchmark; node index.js",
"bench": "cd benchmark; node secp256k1.js; node curves.js; node stark.js; node bls.js",
"build": "tsc && tsc -p tsconfig.esm.json",

@@ -34,4 +34,4 @@ "build:release": "rollup -c rollup.config.js",

"fast-check": "3.0.0",
"micro-bmark": "0.2.0",
"micro-should": "0.3.0",
"micro-bmark": "0.3.0",
"micro-should": "0.4.0",
"prettier": "2.8.3",

@@ -38,0 +38,0 @@ "rollup": "2.75.5",

@@ -10,3 +10,2 @@ # noble-curves

- [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash
- Auditable
- 🏎 [Ultra-fast](#speed), hand-optimized for caveats of JS engines

@@ -16,3 +15,3 @@ - 🔍 Unique tests ensure correctness. Wycheproof vectors included

There are two parts of the package:
Package consists of two parts:

@@ -31,2 +30,3 @@ 1. `abstract/` directory specifies zero-dependency EC algorithms

which had security audits and were developed from 2019 to 2022.
Check out [Upgrading](#upgrading) section if you've used them before.

@@ -451,39 +451,58 @@ ### This library belongs to _noble_ crypto

```
getPublicKey
secp256k1 x 5,241 ops/sec @ 190μs/op
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
ed25519 x 8,390 ops/sec @ 119μs/op
ed448 x 3,224 ops/sec @ 310μs/op
sign
secp256k1 x 3,934 ops/sec @ 254μs/op
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
ed25519 x 4,233 ops/sec @ 236μs/op
ed448 x 1,561 ops/sec @ 640μs/op
verify
secp256k1 x 731 ops/sec @ 1ms/op
P256 x 806 ops/sec @ 1ms/op
P384 x 353 ops/sec @ 2ms/op
P521 x 171 ops/sec @ 5ms/op
ed25519 x 860 ops/sec @ 1ms/op
ed448 x 313 ops/sec @ 3ms/op
getSharedSecret
secp256k1 x 445 ops/sec @ 2ms/op
recoverPublicKey
secp256k1 x 732 ops/sec @ 1ms/op
==== bls12-381 ====
getPublicKey x 817 ops/sec @ 1ms/op
sign x 50 ops/sec @ 19ms/op
verify x 34 ops/sec @ 28ms/op
pairing x 89 ops/sec @ 11ms/op
==== stark ====
secp256k1
init x 57 ops/sec @ 17ms/op
getPublicKey x 4,946 ops/sec @ 202μs/op
sign x 3,914 ops/sec @ 255μs/op
verify x 682 ops/sec @ 1ms/op
getSharedSecret x 427 ops/sec @ 2ms/op
recoverPublicKey x 683 ops/sec @ 1ms/op
schnorr.sign x 539 ops/sec @ 1ms/op
schnorr.verify x 716 ops/sec @ 1ms/op
P256
init x 30 ops/sec @ 32ms/op
getPublicKey x 5,008 ops/sec @ 199μs/op
sign x 3,970 ops/sec @ 251μs/op
verify x 515 ops/sec @ 1ms/op
P384
init x 14 ops/sec @ 66ms/op
getPublicKey x 2,434 ops/sec @ 410μs/op
sign x 1,942 ops/sec @ 514μs/op
verify x 206 ops/sec @ 4ms/op
P521
init x 7 ops/sec @ 126ms/op
getPublicKey x 1,282 ops/sec @ 779μs/op
sign x 1,077 ops/sec @ 928μs/op
verify x 110 ops/sec @ 9ms/op
ed25519
init x 37 ops/sec @ 26ms/op
getPublicKey x 8,147 ops/sec @ 122μs/op
sign x 3,979 ops/sec @ 251μs/op
verify x 848 ops/sec @ 1ms/op
ed448
init x 17 ops/sec @ 58ms/op
getPublicKey x 3,083 ops/sec @ 324μs/op
sign x 1,473 ops/sec @ 678μs/op
verify x 323 ops/sec @ 3ms/op
bls12-381
init x 30 ops/sec @ 33ms/op
getPublicKey x 788 ops/sec @ 1ms/op
sign x 45 ops/sec @ 21ms/op
verify x 32 ops/sec @ 30ms/op
pairing x 88 ops/sec @ 11ms/op
stark
init x 31 ops/sec @ 31ms/op
pedersen
old x 85 ops/sec @ 11ms/op
noble x 1,216 ops/sec @ 822μs/op
├─old x 84 ops/sec @ 11ms/op
└─noble x 802 ops/sec @ 1ms/op
poseidon x 7,466 ops/sec @ 133μs/op
verify
old x 302 ops/sec @ 3ms/op
noble x 698 ops/sec @ 1ms/op
├─old x 300 ops/sec @ 3ms/op
└─noble x 474 ops/sec @ 2ms/op
```

@@ -493,19 +512,30 @@

Differences from @noble/secp256k1 1.7:
If you're coming from single-curve noble packages, the following changes need to be kept in mind:
1. Different double() formula (but same addition)
2. Different sqrt() function
3. DRBG supports outputLen bigger than outputLen of hmac
4. Support for different hash functions
- 2d affine (x, y) points have been removed to reduce complexity and improve speed
- Removed `number` support as a type for private keys. `bigint` is still supported
- `mod`, `invert` are no longer present in `utils`. Use `@noble/curves/abstract/modular.js` now.
Differences from @noble/ed25519 1.7:
Upgrading from @noble/secp256k1 1.7:
1. Variable field element lengths between EDDSA/ECDH:
EDDSA (RFC8032) is 456 bits / 57 bytes, ECDH (RFC7748) is 448 bits / 56 bytes
2. Different addition formula (doubling is same)
3. uvRatio differs between curves (half-expected, not only pow fn changes)
4. Point decompression code is different (unexpected), now using generalized formula
5. Domain function was no-op for ed25519, but adds some data even with empty context for ed448
- Compressed (33-byte) public keys are now returned by default, instead of uncompressed
- Methods are now synchronous. Setting `secp.utils.hmacSha256` is no longer required
- `sign()`
- `der`, `recovered` options were removed
- `canonical` was renamed to `lowS`
- Return type is now `{ r: bigint, s: bigint, recovery: number }` instance of `Signature`
- `verify()`
- `strict` was renamed to `lowS`
- `recoverPublicKey()`: moved to sig instance `Signature#recoverPublicKey(msgHash)`
- `Point` was removed: use `ProjectivePoint` in xyz coordinates
- `utils`: Many methods were removed, others were moved to `schnorr` namespace
Upgrading from @noble/ed25519 1.7:
- Methods are now synchronous. Setting `secp.utils.hmacSha256` is no longer required
- ed25519ph, ed25519ctx
- `Point` was removed: use `ExtendedPoint` in xyzt coordinates
- `Signature` was removed
- `getSharedSecret` was removed: use separate x25519 sub-module
## Contributing & testing

@@ -512,0 +542,0 @@

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