Socket
Socket
Sign inDemoInstall

@noble/secp256k1

Package Overview
Dependencies
Maintainers
1
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@noble/secp256k1 - npm Package Compare versions

Comparing version 1.7.0 to 1.7.1

294

lib/esm/index.js

@@ -18,4 +18,35 @@ /*! noble-secp256k1 - MIT License (c) 2019 Paul Miller (paulmillr.com) */

});
const divNearest = (a, b) => (a + b / _2n) / b;
const endo = {
beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),
splitScalar(k) {
const { n } = CURVE;
const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15');
const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3');
const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8');
const b2 = a1;
const POW_2_128 = BigInt('0x100000000000000000000000000000000');
const c1 = divNearest(b2 * k, n);
const c2 = divNearest(-b1 * k, n);
let k1 = mod(k - c1 * a1 - c2 * a2, n);
let k2 = mod(-c1 * b1 - c2 * b2, n);
const k1neg = k1 > POW_2_128;
const k2neg = k2 > POW_2_128;
if (k1neg)
k1 = n - k1;
if (k2neg)
k2 = n - k2;
if (k1 > POW_2_128 || k2 > POW_2_128) {
throw new Error('splitScalarEndo: Endomorphism failed, k=' + k);
}
return { k1neg, k1, k2neg, k2 };
},
};
const fieldLen = 32;
const groupLen = 32;
const hashLen = 32;
const compressedLen = fieldLen + 1;
const uncompressedLen = 2 * fieldLen + 1;
export { CURVE };
function weistrass(x) {
function weierstrass(x) {
const { a, b } = CURVE;

@@ -32,2 +63,6 @@ const x2 = mod(x * x);

}
function assertJacPoint(other) {
if (!(other instanceof JacobianPoint))
throw new TypeError('JacobianPoint expected');
}
class JacobianPoint {

@@ -43,2 +78,4 @@ constructor(x, y, z) {

}
if (p.equals(Point.ZERO))
return JacobianPoint.ZERO;
return new JacobianPoint(p.x, p.y, _1n);

@@ -54,4 +91,3 @@ }

equals(other) {
if (!(other instanceof JacobianPoint))
throw new TypeError('JacobianPoint expected');
assertJacPoint(other);
const { x: X1, y: Y1, z: Z1 } = this;

@@ -85,4 +121,3 @@ const { x: X2, y: Y2, z: Z2 } = other;

add(other) {
if (!(other instanceof JacobianPoint))
throw new TypeError('JacobianPoint expected');
assertJacPoint(other);
const { x: X1, y: Y1, z: Z1 } = this;

@@ -139,3 +174,3 @@ const { x: X2, y: Y2, z: Z2 } = other;

}
let { k1neg, k1, k2neg, k2 } = splitScalarEndo(n);
let { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);
let k1p = P0;

@@ -157,3 +192,3 @@ let k2p = P0;

k2p = k2p.negate();
k2p = new JacobianPoint(mod(k2p.x * CURVE.beta), k2p.y, k2p.z);
k2p = new JacobianPoint(mod(k2p.x * endo.beta), k2p.y, k2p.z);
return k1p.add(k2p);

@@ -193,3 +228,3 @@ }

let p = JacobianPoint.ZERO;
let f = JacobianPoint.ZERO;
let f = JacobianPoint.BASE;
const windows = 1 + (USE_ENDOMORPHISM ? 128 / W : 256 / W);

@@ -208,13 +243,11 @@ const windowSize = 2 ** (W - 1);

}
const offset1 = offset;
const offset2 = offset + Math.abs(wbits) - 1;
const cond1 = window % 2 !== 0;
const cond2 = wbits < 0;
if (wbits === 0) {
let pr = precomputes[offset];
if (window % 2)
pr = pr.negate();
f = f.add(pr);
f = f.add(constTimeNegate(cond1, precomputes[offset1]));
}
else {
let cached = precomputes[offset + Math.abs(wbits) - 1];
if (wbits < 0)
cached = cached.negate();
p = p.add(cached);
p = p.add(constTimeNegate(cond2, precomputes[offset2]));
}

@@ -229,10 +262,8 @@ }

if (USE_ENDOMORPHISM) {
const { k1neg, k1, k2neg, k2 } = splitScalarEndo(n);
const { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);
let { p: k1p, f: f1p } = this.wNAF(k1, affinePoint);
let { p: k2p, f: f2p } = this.wNAF(k2, affinePoint);
if (k1neg)
k1p = k1p.negate();
if (k2neg)
k2p = k2p.negate();
k2p = new JacobianPoint(mod(k2p.x * CURVE.beta), k2p.y, k2p.z);
k1p = constTimeNegate(k1neg, k1p);
k2p = constTimeNegate(k2neg, k2p);
k2p = new JacobianPoint(mod(k2p.x * endo.beta), k2p.y, k2p.z);
point = k1p.add(k2p);

@@ -248,4 +279,7 @@ fake = f1p.add(f2p);

}
toAffine(invZ = invert(this.z)) {
toAffine(invZ) {
const { x, y, z } = this;
const is0 = this.equals(JacobianPoint.ZERO);
if (invZ == null)
invZ = is0 ? _8n : invert(z);
const iz1 = invZ;

@@ -257,2 +291,4 @@ const iz2 = mod(iz1 * iz1);

const zz = mod(z * iz1);
if (is0)
return Point.ZERO;
if (zz !== _1n)

@@ -265,2 +301,6 @@ throw new Error('invZ was invalid');

JacobianPoint.ZERO = new JacobianPoint(_0n, _1n, _0n);
function constTimeNegate(condition, item) {
const neg = item.negate();
return condition ? neg : item;
}
const pointPrecomputes = new WeakMap();

@@ -284,3 +324,3 @@ export class Point {

throw new Error('Point is not on curve');
const y2 = weistrass(x);
const y2 = weierstrass(x);
let y = sqrtMod(y2);

@@ -302,4 +342,4 @@ const isYOdd = (y & _1n) === _1n;

static fromUncompressedHex(bytes) {
const x = bytesToNumber(bytes.subarray(1, 33));
const y = bytesToNumber(bytes.subarray(33, 65));
const x = bytesToNumber(bytes.subarray(1, fieldLen + 1));
const y = bytesToNumber(bytes.subarray(fieldLen + 1, fieldLen * 2 + 1));
const point = new Point(x, y);

@@ -313,8 +353,10 @@ point.assertValidity();

const header = bytes[0];
if (len === 32 || (len === 33 && (header === 0x02 || header === 0x03))) {
if (len === fieldLen)
return this.fromCompressedHex(bytes);
if (len === compressedLen && (header === 0x02 || header === 0x03)) {
return this.fromCompressedHex(bytes);
}
if (len === 65 && header === 0x04)
if (len === uncompressedLen && header === 0x04)
return this.fromUncompressedHex(bytes);
throw new Error(`Point.fromHex: received invalid point. Expected 32-33 compressed bytes or 65 uncompressed bytes, not ${len}`);
throw new Error(`Point.fromHex: received invalid point. Expected 32-${compressedLen} compressed bytes or ${uncompressedLen} uncompressed bytes, not ${len}`);
}

@@ -325,14 +367,13 @@ static fromPrivateKey(privateKey) {

static fromSignature(msgHash, signature, recovery) {
msgHash = ensureBytes(msgHash);
const h = truncateHash(msgHash);
const { r, s } = normalizeSignature(signature);
if (recovery !== 0 && recovery !== 1) {
throw new Error('Cannot recover signature: invalid recovery bit');
}
const prefix = recovery & 1 ? '03' : '02';
const R = Point.fromHex(prefix + numTo32bStr(r));
if (![0, 1, 2, 3].includes(recovery))
throw new Error('Cannot recover: invalid recovery bit');
const h = truncateHash(ensureBytes(msgHash));
const { n } = CURVE;
const rinv = invert(r, n);
const radj = recovery === 2 || recovery === 3 ? r + n : r;
const rinv = invert(radj, n);
const u1 = mod(-h * rinv, n);
const u2 = mod(s * rinv, n);
const prefix = recovery & 1 ? '03' : '02';
const R = Point.fromHex(prefix + numTo32bStr(radj));
const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2);

@@ -369,3 +410,3 @@ if (!Q)

const left = mod(y * y);
const right = weistrass(x);
const right = weierstrass(x);
if (mod(left - right) !== _0n)

@@ -471,15 +512,15 @@ throw new Error(msg);

normalizeS() {
return this.hasHighS() ? new Signature(this.r, CURVE.n - this.s) : this;
return this.hasHighS() ? new Signature(this.r, mod(-this.s, CURVE.n)) : this;
}
toDERRawBytes(isCompressed = false) {
return hexToBytes(this.toDERHex(isCompressed));
toDERRawBytes() {
return hexToBytes(this.toDERHex());
}
toDERHex(isCompressed = false) {
toDERHex() {
const sHex = sliceDER(numberToHexUnpadded(this.s));
if (isCompressed)
return sHex;
const rHex = sliceDER(numberToHexUnpadded(this.r));
const rLen = numberToHexUnpadded(rHex.length / 2);
const sLen = numberToHexUnpadded(sHex.length / 2);
const length = numberToHexUnpadded(rHex.length / 2 + sHex.length / 2 + 4);
const sHexL = sHex.length / 2;
const rHexL = rHex.length / 2;
const sLen = numberToHexUnpadded(sHexL);
const rLen = numberToHexUnpadded(rHexL);
const length = numberToHexUnpadded(rHexL + sHexL + 4);
return `30${length}02${rLen}${rHex}02${sLen}${sHex}`;

@@ -529,3 +570,3 @@ }

if (!(_0n <= num && num < POW_2_256))
throw new Error('Expected number < 2^256');
throw new Error('Expected number 0 <= n < 2^256');
return num.toString(16).padStart(64, '0');

@@ -613,3 +654,7 @@ }

const t2 = (pow2(t1, _6n) * b2) % P;
return pow2(t2, _2n);
const rt = pow2(t2, _2n);
const xc = (rt * rt) % P;
if (xc !== x)
throw new Error('Cannot find square root');
return rt;
}

@@ -652,38 +697,13 @@ function invert(number, modulo = CURVE.P) {

}
const divNearest = (a, b) => (a + b / _2n) / b;
const ENDO = {
a1: BigInt('0x3086d221a7d46bcde86c90e49284eb15'),
b1: -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3'),
a2: BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8'),
b2: BigInt('0x3086d221a7d46bcde86c90e49284eb15'),
POW_2_128: BigInt('0x100000000000000000000000000000000'),
};
function splitScalarEndo(k) {
const { n } = CURVE;
const { a1, b1, a2, b2, POW_2_128 } = ENDO;
const c1 = divNearest(b2 * k, n);
const c2 = divNearest(-b1 * k, n);
let k1 = mod(k - c1 * a1 - c2 * a2, n);
let k2 = mod(-c1 * b1 - c2 * b2, n);
const k1neg = k1 > POW_2_128;
const k2neg = k2 > POW_2_128;
if (k1neg)
k1 = n - k1;
if (k2neg)
k2 = n - k2;
if (k1 > POW_2_128 || k2 > POW_2_128) {
throw new Error('splitScalarEndo: Endomorphism failed, k=' + k);
}
return { k1neg, k1, k2neg, k2 };
function bits2int_2(bytes) {
const delta = bytes.length * 8 - groupLen * 8;
const num = bytesToNumber(bytes);
return delta > 0 ? num >> BigInt(delta) : num;
}
function truncateHash(hash) {
function truncateHash(hash, truncateOnly = false) {
const h = bits2int_2(hash);
if (truncateOnly)
return h;
const { n } = CURVE;
const byteLength = hash.length;
const delta = byteLength * 8 - 256;
let h = bytesToNumber(hash);
if (delta > 0)
h = h >> BigInt(delta);
if (h >= n)
h -= n;
return h;
return h >= n ? h - n : h;
}

@@ -693,5 +713,11 @@ let _sha256Sync;

class HmacDrbg {
constructor() {
this.v = new Uint8Array(32).fill(1);
this.k = new Uint8Array(32).fill(0);
constructor(hashLen, qByteLen) {
this.hashLen = hashLen;
this.qByteLen = qByteLen;
if (typeof hashLen !== 'number' || hashLen < 2)
throw new Error('hashLen must be a number');
if (typeof qByteLen !== 'number' || qByteLen < 2)
throw new Error('qByteLen must be a number');
this.v = new Uint8Array(hashLen).fill(1);
this.k = new Uint8Array(hashLen).fill(0);
this.counter = 0;

@@ -733,4 +759,11 @@ }

this.incr();
this.v = await this.hmac(this.v);
return this.v;
let len = 0;
const out = [];
while (len < this.qByteLen) {
this.v = await this.hmac(this.v);
const sl = this.v.slice();
out.push(sl);
len += this.v.length;
}
return concatBytes(...out);
}

@@ -740,4 +773,11 @@ generateSync() {

this.incr();
this.v = this.hmacSync(this.v);
return this.v;
let len = 0;
const out = [];
while (len < this.qByteLen) {
this.v = this.hmacSync(this.v);
const sl = this.v.slice();
out.push(sl);
len += this.v.length;
}
return concatBytes(...out);
}

@@ -751,7 +791,8 @@ }

}
function kmdToSig(kBytes, m, d) {
const k = bytesToNumber(kBytes);
function kmdToSig(kBytes, m, d, lowS = true) {
const { n } = CURVE;
const k = truncateHash(kBytes, true);
if (!isWithinCurveOrder(k))
return;
const { n } = CURVE;
const kinv = invert(k, n);
const q = Point.BASE.multiply(k);

@@ -761,7 +802,11 @@ const r = mod(q.x, n);

return;
const s = mod(invert(k, n) * mod(m + d * r, n), n);
const s = mod(kinv * mod(m + d * r, n), n);
if (s === _0n)
return;
const sig = new Signature(r, s);
const recovery = (q.x === sig.r ? 0 : 2) | Number(q.y & _1n);
let sig = new Signature(r, s);
let recovery = (q.x === sig.r ? 0 : 2) | Number(q.y & _1n);
if (lowS && sig.hasHighS()) {
sig = sig.normalizeS();
recovery ^= 1;
}
return { sig, recovery };

@@ -778,3 +823,3 @@ }

else if (typeof key === 'string') {
if (key.length !== 64)
if (key.length !== 2 * groupLen)
throw new Error('Expected 32 bytes of private key');

@@ -784,3 +829,3 @@ num = hexToNumber(key);

else if (key instanceof Uint8Array) {
if (key.length !== 32)
if (key.length !== groupLen)
throw new Error('Expected 32 bytes of private key');

@@ -828,5 +873,5 @@ num = bytesToNumber(key);

if (arr)
return len === 33 || len === 65;
return len === compressedLen || len === uncompressedLen;
if (str)
return len === 66 || len === 130;
return len === compressedLen * 2 || len === uncompressedLen * 2;
if (item instanceof Point)

@@ -846,3 +891,3 @@ return true;

function bits2int(bytes) {
const slice = bytes.length > 32 ? bytes.slice(0, 32) : bytes;
const slice = bytes.length > fieldLen ? bytes.slice(0, fieldLen) : bytes;
return bytesToNumber(slice);

@@ -866,6 +911,6 @@ }

if (extraEntropy === true)
extraEntropy = utils.randomBytes(32);
extraEntropy = utils.randomBytes(fieldLen);
const e = ensureBytes(extraEntropy);
if (e.length !== 32)
throw new Error('sign: Expected 32 bytes of extra data');
if (e.length !== fieldLen)
throw new Error(`sign: Expected ${fieldLen} bytes of extra data`);
seedArgs.push(e);

@@ -878,8 +923,4 @@ }

function finalizeSig(recSig, opts) {
let { sig, recovery } = recSig;
const { canonical, der, recovered } = Object.assign({ canonical: true, der: true }, opts);
if (canonical && sig.hasHighS()) {
sig = sig.normalizeS();
recovery ^= 1;
}
const { sig, recovery } = recSig;
const { der, recovered } = Object.assign({ canonical: true, der: true }, opts);
const hashed = der ? sig.toDERRawBytes() : sig.toCompactRawBytes();

@@ -890,6 +931,6 @@ return recovered ? [hashed, recovery] : hashed;

const { seed, m, d } = initSigArgs(msgHash, privKey, opts.extraEntropy);
const drbg = new HmacDrbg(hashLen, groupLen);
await drbg.reseed(seed);
let sig;
const drbg = new HmacDrbg();
await drbg.reseed(seed);
while (!(sig = kmdToSig(await drbg.generate(), m, d)))
while (!(sig = kmdToSig(await drbg.generate(), m, d, opts.canonical)))
await drbg.reseed();

@@ -900,6 +941,6 @@ return finalizeSig(sig, opts);

const { seed, m, d } = initSigArgs(msgHash, privKey, opts.extraEntropy);
const drbg = new HmacDrbg(hashLen, groupLen);
drbg.reseedSync(seed);
let sig;
const drbg = new HmacDrbg();
drbg.reseedSync(seed);
while (!(sig = kmdToSig(drbg.generateSync(), m, d)))
while (!(sig = kmdToSig(drbg.generateSync(), m, d, opts.canonical)))
drbg.reseedSync();

@@ -1111,4 +1152,6 @@ return finalizeSig(sig, opts);

hash = ensureBytes(hash);
if (hash.length < 40 || hash.length > 1024)
throw new Error('Expected 40-1024 bytes of private key as per FIPS 186');
const minLen = groupLen + 8;
if (hash.length < minLen || hash.length > 1024) {
throw new Error(`Expected valid bytes of private key as per FIPS 186`);
}
const num = mod(bytesToNumber(hash), CURVE.n - _1n) + _1n;

@@ -1129,4 +1172,8 @@ return numTo32b(num);

},
randomPrivateKey: () => {
return utils.hashToPrivateKey(utils.randomBytes(40));
randomPrivateKey: () => utils.hashToPrivateKey(utils.randomBytes(groupLen + 8)),
precompute(windowSize = 8, point = Point.BASE) {
const cached = point === Point.BASE ? point : new Point(point.x, point.y);
cached._setWindowSize(windowSize);
cached.multiply(_3n);
return cached;
},

@@ -1187,8 +1234,3 @@ sha256: async (...messages) => {

},
precompute(windowSize = 8, point = Point.BASE) {
const cached = point === Point.BASE ? point : new Point(point.x, point.y);
cached._setWindowSize(windowSize);
cached.multiply(_3n);
return cached;
},
_JacobianPoint: JacobianPoint,
};

@@ -1195,0 +1237,0 @@ Object.defineProperties(utils, {

@@ -17,2 +17,23 @@ /*! noble-secp256k1 - MIT License (c) 2019 Paul Miller (paulmillr.com) */

declare type Sig = Hex | Signature;
declare class JacobianPoint {
readonly x: bigint;
readonly y: bigint;
readonly z: bigint;
constructor(x: bigint, y: bigint, z: bigint);
static readonly BASE: JacobianPoint;
static readonly ZERO: JacobianPoint;
static fromAffine(p: Point): JacobianPoint;
static toAffineBatch(points: JacobianPoint[]): Point[];
static normalizeZ(points: JacobianPoint[]): JacobianPoint[];
equals(other: JacobianPoint): boolean;
negate(): JacobianPoint;
double(): JacobianPoint;
add(other: JacobianPoint): JacobianPoint;
subtract(other: JacobianPoint): JacobianPoint;
multiplyUnsafe(scalar: bigint): JacobianPoint;
private precomputeWindow;
private wNAF;
multiply(scalar: number | bigint, affinePoint?: Point): JacobianPoint;
toAffine(invZ?: bigint): Point;
}
export declare class Point {

@@ -55,4 +76,4 @@ readonly x: bigint;

normalizeS(): Signature;
toDERRawBytes(isCompressed?: boolean): Uint8Array;
toDERHex(isCompressed?: boolean): string;
toDERRawBytes(): Uint8Array;
toDERHex(): string;
toRawBytes(): Uint8Array;

@@ -131,2 +152,3 @@ toHex(): string;

randomPrivateKey: () => Uint8Array;
precompute(windowSize?: number, point?: Point): Point;
sha256: (...messages: Uint8Array[]) => Promise<Uint8Array>;

@@ -138,3 +160,3 @@ hmacSha256: (key: Uint8Array, ...messages: Uint8Array[]) => Promise<Uint8Array>;

taggedHashSync: (tag: string, ...messages: Uint8Array[]) => Uint8Array;
precompute(windowSize?: number, point?: Point): Point;
_JacobianPoint: typeof JacobianPoint;
};

@@ -22,3 +22,34 @@ "use strict";

exports.CURVE = CURVE;
function weistrass(x) {
const divNearest = (a, b) => (a + b / _2n) / b;
const endo = {
beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),
splitScalar(k) {
const { n } = CURVE;
const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15');
const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3');
const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8');
const b2 = a1;
const POW_2_128 = BigInt('0x100000000000000000000000000000000');
const c1 = divNearest(b2 * k, n);
const c2 = divNearest(-b1 * k, n);
let k1 = mod(k - c1 * a1 - c2 * a2, n);
let k2 = mod(-c1 * b1 - c2 * b2, n);
const k1neg = k1 > POW_2_128;
const k2neg = k2 > POW_2_128;
if (k1neg)
k1 = n - k1;
if (k2neg)
k2 = n - k2;
if (k1 > POW_2_128 || k2 > POW_2_128) {
throw new Error('splitScalarEndo: Endomorphism failed, k=' + k);
}
return { k1neg, k1, k2neg, k2 };
},
};
const fieldLen = 32;
const groupLen = 32;
const hashLen = 32;
const compressedLen = fieldLen + 1;
const uncompressedLen = 2 * fieldLen + 1;
function weierstrass(x) {
const { a, b } = CURVE;

@@ -35,2 +66,6 @@ const x2 = mod(x * x);

}
function assertJacPoint(other) {
if (!(other instanceof JacobianPoint))
throw new TypeError('JacobianPoint expected');
}
class JacobianPoint {

@@ -46,2 +81,4 @@ constructor(x, y, z) {

}
if (p.equals(Point.ZERO))
return JacobianPoint.ZERO;
return new JacobianPoint(p.x, p.y, _1n);

@@ -57,4 +94,3 @@ }

equals(other) {
if (!(other instanceof JacobianPoint))
throw new TypeError('JacobianPoint expected');
assertJacPoint(other);
const { x: X1, y: Y1, z: Z1 } = this;

@@ -88,4 +124,3 @@ const { x: X2, y: Y2, z: Z2 } = other;

add(other) {
if (!(other instanceof JacobianPoint))
throw new TypeError('JacobianPoint expected');
assertJacPoint(other);
const { x: X1, y: Y1, z: Z1 } = this;

@@ -142,3 +177,3 @@ const { x: X2, y: Y2, z: Z2 } = other;

}
let { k1neg, k1, k2neg, k2 } = splitScalarEndo(n);
let { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);
let k1p = P0;

@@ -160,3 +195,3 @@ let k2p = P0;

k2p = k2p.negate();
k2p = new JacobianPoint(mod(k2p.x * CURVE.beta), k2p.y, k2p.z);
k2p = new JacobianPoint(mod(k2p.x * endo.beta), k2p.y, k2p.z);
return k1p.add(k2p);

@@ -196,3 +231,3 @@ }

let p = JacobianPoint.ZERO;
let f = JacobianPoint.ZERO;
let f = JacobianPoint.BASE;
const windows = 1 + (USE_ENDOMORPHISM ? 128 / W : 256 / W);

@@ -211,13 +246,11 @@ const windowSize = 2 ** (W - 1);

}
const offset1 = offset;
const offset2 = offset + Math.abs(wbits) - 1;
const cond1 = window % 2 !== 0;
const cond2 = wbits < 0;
if (wbits === 0) {
let pr = precomputes[offset];
if (window % 2)
pr = pr.negate();
f = f.add(pr);
f = f.add(constTimeNegate(cond1, precomputes[offset1]));
}
else {
let cached = precomputes[offset + Math.abs(wbits) - 1];
if (wbits < 0)
cached = cached.negate();
p = p.add(cached);
p = p.add(constTimeNegate(cond2, precomputes[offset2]));
}

@@ -232,10 +265,8 @@ }

if (USE_ENDOMORPHISM) {
const { k1neg, k1, k2neg, k2 } = splitScalarEndo(n);
const { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);
let { p: k1p, f: f1p } = this.wNAF(k1, affinePoint);
let { p: k2p, f: f2p } = this.wNAF(k2, affinePoint);
if (k1neg)
k1p = k1p.negate();
if (k2neg)
k2p = k2p.negate();
k2p = new JacobianPoint(mod(k2p.x * CURVE.beta), k2p.y, k2p.z);
k1p = constTimeNegate(k1neg, k1p);
k2p = constTimeNegate(k2neg, k2p);
k2p = new JacobianPoint(mod(k2p.x * endo.beta), k2p.y, k2p.z);
point = k1p.add(k2p);

@@ -251,4 +282,7 @@ fake = f1p.add(f2p);

}
toAffine(invZ = invert(this.z)) {
toAffine(invZ) {
const { x, y, z } = this;
const is0 = this.equals(JacobianPoint.ZERO);
if (invZ == null)
invZ = is0 ? _8n : invert(z);
const iz1 = invZ;

@@ -260,2 +294,4 @@ const iz2 = mod(iz1 * iz1);

const zz = mod(z * iz1);
if (is0)
return Point.ZERO;
if (zz !== _1n)

@@ -268,2 +304,6 @@ throw new Error('invZ was invalid');

JacobianPoint.ZERO = new JacobianPoint(_0n, _1n, _0n);
function constTimeNegate(condition, item) {
const neg = item.negate();
return condition ? neg : item;
}
const pointPrecomputes = new WeakMap();

@@ -287,3 +327,3 @@ class Point {

throw new Error('Point is not on curve');
const y2 = weistrass(x);
const y2 = weierstrass(x);
let y = sqrtMod(y2);

@@ -305,4 +345,4 @@ const isYOdd = (y & _1n) === _1n;

static fromUncompressedHex(bytes) {
const x = bytesToNumber(bytes.subarray(1, 33));
const y = bytesToNumber(bytes.subarray(33, 65));
const x = bytesToNumber(bytes.subarray(1, fieldLen + 1));
const y = bytesToNumber(bytes.subarray(fieldLen + 1, fieldLen * 2 + 1));
const point = new Point(x, y);

@@ -316,8 +356,10 @@ point.assertValidity();

const header = bytes[0];
if (len === 32 || (len === 33 && (header === 0x02 || header === 0x03))) {
if (len === fieldLen)
return this.fromCompressedHex(bytes);
if (len === compressedLen && (header === 0x02 || header === 0x03)) {
return this.fromCompressedHex(bytes);
}
if (len === 65 && header === 0x04)
if (len === uncompressedLen && header === 0x04)
return this.fromUncompressedHex(bytes);
throw new Error(`Point.fromHex: received invalid point. Expected 32-33 compressed bytes or 65 uncompressed bytes, not ${len}`);
throw new Error(`Point.fromHex: received invalid point. Expected 32-${compressedLen} compressed bytes or ${uncompressedLen} uncompressed bytes, not ${len}`);
}

@@ -328,14 +370,13 @@ static fromPrivateKey(privateKey) {

static fromSignature(msgHash, signature, recovery) {
msgHash = ensureBytes(msgHash);
const h = truncateHash(msgHash);
const { r, s } = normalizeSignature(signature);
if (recovery !== 0 && recovery !== 1) {
throw new Error('Cannot recover signature: invalid recovery bit');
}
const prefix = recovery & 1 ? '03' : '02';
const R = Point.fromHex(prefix + numTo32bStr(r));
if (![0, 1, 2, 3].includes(recovery))
throw new Error('Cannot recover: invalid recovery bit');
const h = truncateHash(ensureBytes(msgHash));
const { n } = CURVE;
const rinv = invert(r, n);
const radj = recovery === 2 || recovery === 3 ? r + n : r;
const rinv = invert(radj, n);
const u1 = mod(-h * rinv, n);
const u2 = mod(s * rinv, n);
const prefix = recovery & 1 ? '03' : '02';
const R = Point.fromHex(prefix + numTo32bStr(radj));
const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2);

@@ -372,3 +413,3 @@ if (!Q)

const left = mod(y * y);
const right = weistrass(x);
const right = weierstrass(x);
if (mod(left - right) !== _0n)

@@ -475,15 +516,15 @@ throw new Error(msg);

normalizeS() {
return this.hasHighS() ? new Signature(this.r, CURVE.n - this.s) : this;
return this.hasHighS() ? new Signature(this.r, mod(-this.s, CURVE.n)) : this;
}
toDERRawBytes(isCompressed = false) {
return hexToBytes(this.toDERHex(isCompressed));
toDERRawBytes() {
return hexToBytes(this.toDERHex());
}
toDERHex(isCompressed = false) {
toDERHex() {
const sHex = sliceDER(numberToHexUnpadded(this.s));
if (isCompressed)
return sHex;
const rHex = sliceDER(numberToHexUnpadded(this.r));
const rLen = numberToHexUnpadded(rHex.length / 2);
const sLen = numberToHexUnpadded(sHex.length / 2);
const length = numberToHexUnpadded(rHex.length / 2 + sHex.length / 2 + 4);
const sHexL = sHex.length / 2;
const rHexL = rHex.length / 2;
const sLen = numberToHexUnpadded(sHexL);
const rLen = numberToHexUnpadded(rHexL);
const length = numberToHexUnpadded(rHexL + sHexL + 4);
return `30${length}02${rLen}${rHex}02${sLen}${sHex}`;

@@ -534,3 +575,3 @@ }

if (!(_0n <= num && num < POW_2_256))
throw new Error('Expected number < 2^256');
throw new Error('Expected number 0 <= n < 2^256');
return num.toString(16).padStart(64, '0');

@@ -618,3 +659,7 @@ }

const t2 = (pow2(t1, _6n) * b2) % P;
return pow2(t2, _2n);
const rt = pow2(t2, _2n);
const xc = (rt * rt) % P;
if (xc !== x)
throw new Error('Cannot find square root');
return rt;
}

@@ -657,38 +702,13 @@ function invert(number, modulo = CURVE.P) {

}
const divNearest = (a, b) => (a + b / _2n) / b;
const ENDO = {
a1: BigInt('0x3086d221a7d46bcde86c90e49284eb15'),
b1: -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3'),
a2: BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8'),
b2: BigInt('0x3086d221a7d46bcde86c90e49284eb15'),
POW_2_128: BigInt('0x100000000000000000000000000000000'),
};
function splitScalarEndo(k) {
const { n } = CURVE;
const { a1, b1, a2, b2, POW_2_128 } = ENDO;
const c1 = divNearest(b2 * k, n);
const c2 = divNearest(-b1 * k, n);
let k1 = mod(k - c1 * a1 - c2 * a2, n);
let k2 = mod(-c1 * b1 - c2 * b2, n);
const k1neg = k1 > POW_2_128;
const k2neg = k2 > POW_2_128;
if (k1neg)
k1 = n - k1;
if (k2neg)
k2 = n - k2;
if (k1 > POW_2_128 || k2 > POW_2_128) {
throw new Error('splitScalarEndo: Endomorphism failed, k=' + k);
}
return { k1neg, k1, k2neg, k2 };
function bits2int_2(bytes) {
const delta = bytes.length * 8 - groupLen * 8;
const num = bytesToNumber(bytes);
return delta > 0 ? num >> BigInt(delta) : num;
}
function truncateHash(hash) {
function truncateHash(hash, truncateOnly = false) {
const h = bits2int_2(hash);
if (truncateOnly)
return h;
const { n } = CURVE;
const byteLength = hash.length;
const delta = byteLength * 8 - 256;
let h = bytesToNumber(hash);
if (delta > 0)
h = h >> BigInt(delta);
if (h >= n)
h -= n;
return h;
return h >= n ? h - n : h;
}

@@ -698,5 +718,11 @@ let _sha256Sync;

class HmacDrbg {
constructor() {
this.v = new Uint8Array(32).fill(1);
this.k = new Uint8Array(32).fill(0);
constructor(hashLen, qByteLen) {
this.hashLen = hashLen;
this.qByteLen = qByteLen;
if (typeof hashLen !== 'number' || hashLen < 2)
throw new Error('hashLen must be a number');
if (typeof qByteLen !== 'number' || qByteLen < 2)
throw new Error('qByteLen must be a number');
this.v = new Uint8Array(hashLen).fill(1);
this.k = new Uint8Array(hashLen).fill(0);
this.counter = 0;

@@ -738,4 +764,11 @@ }

this.incr();
this.v = await this.hmac(this.v);
return this.v;
let len = 0;
const out = [];
while (len < this.qByteLen) {
this.v = await this.hmac(this.v);
const sl = this.v.slice();
out.push(sl);
len += this.v.length;
}
return concatBytes(...out);
}

@@ -745,4 +778,11 @@ generateSync() {

this.incr();
this.v = this.hmacSync(this.v);
return this.v;
let len = 0;
const out = [];
while (len < this.qByteLen) {
this.v = this.hmacSync(this.v);
const sl = this.v.slice();
out.push(sl);
len += this.v.length;
}
return concatBytes(...out);
}

@@ -756,7 +796,8 @@ }

}
function kmdToSig(kBytes, m, d) {
const k = bytesToNumber(kBytes);
function kmdToSig(kBytes, m, d, lowS = true) {
const { n } = CURVE;
const k = truncateHash(kBytes, true);
if (!isWithinCurveOrder(k))
return;
const { n } = CURVE;
const kinv = invert(k, n);
const q = Point.BASE.multiply(k);

@@ -766,7 +807,11 @@ const r = mod(q.x, n);

return;
const s = mod(invert(k, n) * mod(m + d * r, n), n);
const s = mod(kinv * mod(m + d * r, n), n);
if (s === _0n)
return;
const sig = new Signature(r, s);
const recovery = (q.x === sig.r ? 0 : 2) | Number(q.y & _1n);
let sig = new Signature(r, s);
let recovery = (q.x === sig.r ? 0 : 2) | Number(q.y & _1n);
if (lowS && sig.hasHighS()) {
sig = sig.normalizeS();
recovery ^= 1;
}
return { sig, recovery };

@@ -783,3 +828,3 @@ }

else if (typeof key === 'string') {
if (key.length !== 64)
if (key.length !== 2 * groupLen)
throw new Error('Expected 32 bytes of private key');

@@ -789,3 +834,3 @@ num = hexToNumber(key);

else if (key instanceof Uint8Array) {
if (key.length !== 32)
if (key.length !== groupLen)
throw new Error('Expected 32 bytes of private key');

@@ -835,5 +880,5 @@ num = bytesToNumber(key);

if (arr)
return len === 33 || len === 65;
return len === compressedLen || len === uncompressedLen;
if (str)
return len === 66 || len === 130;
return len === compressedLen * 2 || len === uncompressedLen * 2;
if (item instanceof Point)

@@ -854,3 +899,3 @@ return true;

function bits2int(bytes) {
const slice = bytes.length > 32 ? bytes.slice(0, 32) : bytes;
const slice = bytes.length > fieldLen ? bytes.slice(0, fieldLen) : bytes;
return bytesToNumber(slice);

@@ -874,6 +919,6 @@ }

if (extraEntropy === true)
extraEntropy = exports.utils.randomBytes(32);
extraEntropy = exports.utils.randomBytes(fieldLen);
const e = ensureBytes(extraEntropy);
if (e.length !== 32)
throw new Error('sign: Expected 32 bytes of extra data');
if (e.length !== fieldLen)
throw new Error(`sign: Expected ${fieldLen} bytes of extra data`);
seedArgs.push(e);

@@ -886,8 +931,4 @@ }

function finalizeSig(recSig, opts) {
let { sig, recovery } = recSig;
const { canonical, der, recovered } = Object.assign({ canonical: true, der: true }, opts);
if (canonical && sig.hasHighS()) {
sig = sig.normalizeS();
recovery ^= 1;
}
const { sig, recovery } = recSig;
const { der, recovered } = Object.assign({ canonical: true, der: true }, opts);
const hashed = der ? sig.toDERRawBytes() : sig.toCompactRawBytes();

@@ -898,6 +939,6 @@ return recovered ? [hashed, recovery] : hashed;

const { seed, m, d } = initSigArgs(msgHash, privKey, opts.extraEntropy);
const drbg = new HmacDrbg(hashLen, groupLen);
await drbg.reseed(seed);
let sig;
const drbg = new HmacDrbg();
await drbg.reseed(seed);
while (!(sig = kmdToSig(await drbg.generate(), m, d)))
while (!(sig = kmdToSig(await drbg.generate(), m, d, opts.canonical)))
await drbg.reseed();

@@ -909,6 +950,6 @@ return finalizeSig(sig, opts);

const { seed, m, d } = initSigArgs(msgHash, privKey, opts.extraEntropy);
const drbg = new HmacDrbg(hashLen, groupLen);
drbg.reseedSync(seed);
let sig;
const drbg = new HmacDrbg();
drbg.reseedSync(seed);
while (!(sig = kmdToSig(drbg.generateSync(), m, d)))
while (!(sig = kmdToSig(drbg.generateSync(), m, d, opts.canonical)))
drbg.reseedSync();

@@ -1121,4 +1162,6 @@ return finalizeSig(sig, opts);

hash = ensureBytes(hash);
if (hash.length < 40 || hash.length > 1024)
throw new Error('Expected 40-1024 bytes of private key as per FIPS 186');
const minLen = groupLen + 8;
if (hash.length < minLen || hash.length > 1024) {
throw new Error(`Expected valid bytes of private key as per FIPS 186`);
}
const num = mod(bytesToNumber(hash), CURVE.n - _1n) + _1n;

@@ -1139,4 +1182,8 @@ return numTo32b(num);

},
randomPrivateKey: () => {
return exports.utils.hashToPrivateKey(exports.utils.randomBytes(40));
randomPrivateKey: () => exports.utils.hashToPrivateKey(exports.utils.randomBytes(groupLen + 8)),
precompute(windowSize = 8, point = Point.BASE) {
const cached = point === Point.BASE ? point : new Point(point.x, point.y);
cached._setWindowSize(windowSize);
cached.multiply(_3n);
return cached;
},

@@ -1197,8 +1244,3 @@ sha256: async (...messages) => {

},
precompute(windowSize = 8, point = Point.BASE) {
const cached = point === Point.BASE ? point : new Point(point.x, point.y);
cached._setWindowSize(windowSize);
cached.multiply(_3n);
return cached;
},
_JacobianPoint: JacobianPoint,
};

@@ -1205,0 +1247,0 @@ Object.defineProperties(exports.utils, {

{
"name": "@noble/secp256k1",
"version": "1.7.0",
"version": "1.7.1",
"description": "Fastest JS implementation of secp256k1. Independently audited, high-security, 0-dependency ECDSA & Schnorr signatures",

@@ -5,0 +5,0 @@ "files": [

@@ -138,3 +138,3 @@ # noble-secp256k1 ![Node CI](https://github.com/paulmillr/noble-secp256k1/workflows/Node%20CI/badge.svg) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)

```ts
import { hmac } = from '@noble/hashes/hmac';
import { hmac } from '@noble/hashes/hmac';
import { sha256 } from '@noble/hashes/sha256';

@@ -355,3 +355,3 @@ secp256k1.utils.hmacSha256Sync = (key, ...msgs) => hmac(sha256, key, secp256k1.utils.concatBytes(...msgs))

We're using built-in JS `BigInt`, which is "unsuitable for use in cryptography" as [per official spec](https://github.com/tc39/proposal-bigint#cryptography). This means that the lib is potentially vulnerable to [timing attacks](https://en.wikipedia.org/wiki/Timing_attack). But, _JIT-compiler_ and _Garbage Collector_ make "constant time" extremely hard to achieve in a scripting language. Which means _any other JS library doesn't use constant-time bigints_. Including bn.js or anything else. Even statically typed Rust, a language without GC, [makes it harder to achieve constant-time](https://www.chosenplaintext.ca/open-source/rust-timing-shield/security) for some cases. If your goal is absolute security, don't use any JS lib — including bindings to native ones. Use low-level libraries & languages. Nonetheless we've hardened implementation of ec curve multiplication to be algorithmically constant time.
We're using built-in JS `BigInt`, which is potentially vulnerable to [timing attacks](https://en.wikipedia.org/wiki/Timing_attack) as [per official spec](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#cryptography). But, _JIT-compiler_ and _Garbage Collector_ make "constant time" extremely hard to achieve in a scripting language. Which means _any other JS library doesn't use constant-time bigints_. Including bn.js or anything else. Even statically typed Rust, a language without GC, [makes it harder to achieve constant-time](https://www.chosenplaintext.ca/open-source/rust-timing-shield/security) for some cases. If your goal is absolute security, don't use any JS lib — including bindings to native ones. Use low-level libraries & languages. Nonetheless we've hardened implementation of ec curve multiplication to be algorithmically constant time.

@@ -364,12 +364,12 @@ We however consider infrastructure attacks like rogue NPM modules very important; that's why it's crucial to minimize the amount of 3rd-party dependencies & native bindings. If your app uses 500 dependencies, any dep could get hacked and you'll be downloading malware with every `npm install`. Our goal is to minimize this attack vector.

getPublicKey(utils.randomPrivateKey()) x 7,035 ops/sec @ 142μs/op
sign x 5,452 ops/sec @ 183μs/op
signSync (@noble/hashes) x 5,082 ops/sec @ 196μs/op
verify x 1,042 ops/sec @ 959μs/op
recoverPublicKey x 955 ops/sec @ 1ms/op
getSharedSecret aka ecdh x 624 ops/sec @ 1ms/op
getSharedSecret (precomputed) x 7,357 ops/sec @ 135μs/op
Point.fromHex (decompression) x 13,725 ops/sec @ 72μs/op
schnorr.sign x 770 ops/sec @ 1ms/op
schnorr.verify x 1,093 ops/sec @ 914μs/op
getPublicKey(utils.randomPrivateKey()) x 7,093 ops/sec @ 140μs/op
sign x 5,615 ops/sec @ 178μs/op
signSync (@noble/hashes) x 5,209 ops/sec @ 191μs/op
verify x 1,114 ops/sec @ 896μs/op
recoverPublicKey x 1,018 ops/sec @ 982μs/op
getSharedSecret aka ecdh x 665 ops/sec @ 1ms/op
getSharedSecret (precomputed) x 7,426 ops/sec @ 134μs/op
Point.fromHex (decompression) x 14,582 ops/sec @ 68μs/op
schnorr.sign x 805 ops/sec @ 1ms/op
schnorr.verify x 1,129 ops/sec @ 885μs/op

@@ -376,0 +376,0 @@ Compare to other libraries on M1 (`openssl` uses native bindings, not JS):

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