Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@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.5.4 to 1.5.5

111

lib/esm/index.js

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

const USE_ENDOMORPHISM = CURVE.a === _0n;
export class JacobianPoint {
class JacobianPoint {
constructor(x, y, z) {

@@ -262,3 +262,3 @@ this.x = x;

const isShort = bytes.length === 32;
const x = bytesToNumber(isShort ? bytes : bytes.slice(1));
const x = bytesToNumber(isShort ? bytes : bytes.subarray(1));
if (!isValidFieldElement(x))

@@ -283,4 +283,4 @@ throw new Error('Point is not on curve');

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

@@ -292,9 +292,10 @@ point.assertValidity();

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

@@ -305,5 +306,4 @@ static fromPrivateKey(privateKey) {

static fromSignature(msgHash, signature, recovery) {
const { n } = CURVE;
msgHash = ensureBytes(msgHash);
const z = truncateHash(msgHash);
const h = truncateHash(msgHash);
const { r, s } = normalizeSignature(signature);

@@ -313,18 +313,15 @@ if (recovery !== 0 && recovery !== 1) {

}
if (z === _0n)
if (h === _0n)
throw new Error('Cannot recover signature: msgHash cannot be 0');
const prefix = recovery & 1 ? '03' : '02';
const Ra = Point.fromHex(prefix + numTo32bStr(r));
const R = JacobianPoint.fromAffine(Ra);
const R = Point.fromHex(prefix + numTo32bStr(r));
const { n } = CURVE;
const rinv = invert(r, n);
const u1 = mod(-z * rinv, n);
const u1 = mod(-h * rinv, n);
const u2 = mod(s * rinv, n);
const u1G = JacobianPoint.BASE.multiply(u1);
const u2R = R.multiplyUnsafe(u2);
const Q = u1G.add(u2R);
if (Q.equals(JacobianPoint.ZERO))
const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2);
if (!Q)
throw new Error('Cannot recover signature: point at infinify');
const Qa = Q.toAffine();
Qa.assertValidity();
return Qa;
Q.assertValidity();
return Q;
}

@@ -337,3 +334,4 @@ toRawBytes(isCompressed = false) {

if (isCompressed) {
return `${this.y & _1n ? '03' : '02'}${x}`;
const prefix = this.y & _1n ? '03' : '02';
return `${prefix}${x}`;
}

@@ -378,2 +376,9 @@ else {

}
multiplyAndAddUnsafe(Q, a, b) {
const P = JacobianPoint.fromAffine(this);
const aP = P.multiply(a);
const bQ = JacobianPoint.fromAffine(Q).multiplyUnsafe(b);
const sum = aP.add(bQ);
return sum.equals(JacobianPoint.ZERO) ? undefined : sum.toAffine();
}
}

@@ -883,5 +888,5 @@ Point.BASE = new Point(CURVE.Gx, CURVE.Gy);

return false;
let pubKey;
let P;
try {
pubKey = JacobianPoint.fromAffine(normalizePublicKey(publicKey));
P = normalizePublicKey(publicKey);
}

@@ -892,8 +897,8 @@ catch (error) {

const { n } = CURVE;
const s1 = invert(s, n);
const u1 = mod(h * s1, n);
const u2 = mod(r * s1, n);
const Ghs1 = JacobianPoint.BASE.multiply(u1);
const Prs1 = pubKey.multiplyUnsafe(u2);
const R = Ghs1.add(Prs1).toAffine();
const sinv = invert(s, n);
const u1 = mod(h * sinv, n);
const u2 = mod(r * sinv, n);
const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2);
if (!R)
return false;
const v = mod(R.x, n);

@@ -914,3 +919,3 @@ return v === r;

function hasEvenY(point) {
return mod(point.y, _2n) === _0n;
return (point.y & _1n) === _0n;
}

@@ -921,4 +926,3 @@ class SchnorrSignature {

this.s = s;
if (!isValidFieldElement(r) || !isWithinCurveOrder(s))
throw new Error('Invalid signature');
this.assertValidity();
}

@@ -929,6 +933,11 @@ static fromHex(hex) {

throw new TypeError(`SchnorrSignature.fromHex: expected 64 bytes, not ${bytes.length}`);
const r = bytesToNumber(bytes.slice(0, 32));
const s = bytesToNumber(bytes.slice(32, 64));
const r = bytesToNumber(bytes.subarray(0, 32));
const s = bytesToNumber(bytes.subarray(32, 64));
return new SchnorrSignature(r, s);
}
assertValidity() {
const { r, s } = this;
if (!isValidFieldElement(r) || !isWithinCurveOrder(s))
throw new Error('Invalid signature');
}
toHex() {

@@ -964,18 +973,32 @@ return numTo32bStr(this.r) + numTo32bStr(this.s);

const e = await createChallenge(R.x, P, m);
const sig = new SchnorrSignature(R.x, mod(k + e * d, n));
const isValid = await schnorrVerify(sig.toRawBytes(), m, P.toRawX());
const sig = new SchnorrSignature(R.x, mod(k + e * d, n)).toRawBytes();
const isValid = await schnorrVerify(sig, m, P.toRawX());
if (!isValid)
throw new Error('sign: Invalid signature produced');
return sig.toRawBytes();
return sig;
}
async function schnorrVerify(signature, message, publicKey) {
const sig = signature instanceof SchnorrSignature ? signature : SchnorrSignature.fromHex(signature);
const raw = signature instanceof SchnorrSignature;
let sig;
try {
sig = raw ? signature : SchnorrSignature.fromHex(signature);
if (raw)
sig.assertValidity();
}
catch (error) {
return false;
}
const { r, s } = sig;
const m = ensureBytes(message);
const P = normalizePublicKey(publicKey);
const e = await createChallenge(sig.r, P, m);
const sG = Point.fromPrivateKey(sig.s);
const eP = P.multiply(e);
const R = sG.subtract(eP);
if (R.equals(Point.BASE) || !hasEvenY(R) || R.x !== sig.r)
let P;
try {
P = normalizePublicKey(publicKey);
}
catch (error) {
return false;
}
const e = await createChallenge(r, P, m);
const R = Point.BASE.multiplyAndAddUnsafe(P, normalizePrivateKey(s), mod(-e, CURVE.n));
if (!R || !hasEvenY(R) || R.x !== r)
return false;
return true;

@@ -982,0 +1005,0 @@ }

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

declare type Sig = Hex | Signature;
export 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 {

@@ -63,2 +42,3 @@ readonly x: bigint;

multiply(scalar: number | bigint): Point;
multiplyAndAddUnsafe(Q: Point, a: bigint, b: bigint): Point | undefined;
}

@@ -115,2 +95,3 @@ export declare class Signature {

static fromHex(hex: Hex): SchnorrSignature;
assertValidity(): void;
toHex(): string;

@@ -117,0 +98,0 @@ toRawBytes(): Uint8Array;

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

Object.defineProperty(exports, "__esModule", { value: true });
exports.utils = exports.schnorr = exports.verify = exports.signSync = exports.sign = exports.getSharedSecret = exports.recoverPublicKey = exports.getPublicKey = exports.Signature = exports.Point = exports.JacobianPoint = exports.CURVE = void 0;
exports.utils = exports.schnorr = exports.verify = exports.signSync = exports.sign = exports.getSharedSecret = exports.recoverPublicKey = exports.getPublicKey = exports.Signature = exports.Point = exports.CURVE = void 0;
const crypto_1 = __importDefault(require("crypto"));

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

}
exports.JacobianPoint = JacobianPoint;
JacobianPoint.BASE = new JacobianPoint(CURVE.Gx, CURVE.Gy, _1n);

@@ -270,3 +269,3 @@ JacobianPoint.ZERO = new JacobianPoint(_0n, _1n, _0n);

const isShort = bytes.length === 32;
const x = bytesToNumber(isShort ? bytes : bytes.slice(1));
const x = bytesToNumber(isShort ? bytes : bytes.subarray(1));
if (!isValidFieldElement(x))

@@ -291,4 +290,4 @@ throw new Error('Point is not on curve');

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

@@ -300,9 +299,10 @@ point.assertValidity();

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

@@ -313,5 +313,4 @@ static fromPrivateKey(privateKey) {

static fromSignature(msgHash, signature, recovery) {
const { n } = CURVE;
msgHash = ensureBytes(msgHash);
const z = truncateHash(msgHash);
const h = truncateHash(msgHash);
const { r, s } = normalizeSignature(signature);

@@ -321,18 +320,15 @@ if (recovery !== 0 && recovery !== 1) {

}
if (z === _0n)
if (h === _0n)
throw new Error('Cannot recover signature: msgHash cannot be 0');
const prefix = recovery & 1 ? '03' : '02';
const Ra = Point.fromHex(prefix + numTo32bStr(r));
const R = JacobianPoint.fromAffine(Ra);
const R = Point.fromHex(prefix + numTo32bStr(r));
const { n } = CURVE;
const rinv = invert(r, n);
const u1 = mod(-z * rinv, n);
const u1 = mod(-h * rinv, n);
const u2 = mod(s * rinv, n);
const u1G = JacobianPoint.BASE.multiply(u1);
const u2R = R.multiplyUnsafe(u2);
const Q = u1G.add(u2R);
if (Q.equals(JacobianPoint.ZERO))
const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2);
if (!Q)
throw new Error('Cannot recover signature: point at infinify');
const Qa = Q.toAffine();
Qa.assertValidity();
return Qa;
Q.assertValidity();
return Q;
}

@@ -345,3 +341,4 @@ toRawBytes(isCompressed = false) {

if (isCompressed) {
return `${this.y & _1n ? '03' : '02'}${x}`;
const prefix = this.y & _1n ? '03' : '02';
return `${prefix}${x}`;
}

@@ -386,2 +383,9 @@ else {

}
multiplyAndAddUnsafe(Q, a, b) {
const P = JacobianPoint.fromAffine(this);
const aP = P.multiply(a);
const bQ = JacobianPoint.fromAffine(Q).multiplyUnsafe(b);
const sum = aP.add(bQ);
return sum.equals(JacobianPoint.ZERO) ? undefined : sum.toAffine();
}
}

@@ -897,5 +901,5 @@ exports.Point = Point;

return false;
let pubKey;
let P;
try {
pubKey = JacobianPoint.fromAffine(normalizePublicKey(publicKey));
P = normalizePublicKey(publicKey);
}

@@ -906,8 +910,8 @@ catch (error) {

const { n } = CURVE;
const s1 = invert(s, n);
const u1 = mod(h * s1, n);
const u2 = mod(r * s1, n);
const Ghs1 = JacobianPoint.BASE.multiply(u1);
const Prs1 = pubKey.multiplyUnsafe(u2);
const R = Ghs1.add(Prs1).toAffine();
const sinv = invert(s, n);
const u1 = mod(h * sinv, n);
const u2 = mod(r * sinv, n);
const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2);
if (!R)
return false;
const v = mod(R.x, n);

@@ -929,3 +933,3 @@ return v === r;

function hasEvenY(point) {
return mod(point.y, _2n) === _0n;
return (point.y & _1n) === _0n;
}

@@ -936,4 +940,3 @@ class SchnorrSignature {

this.s = s;
if (!isValidFieldElement(r) || !isWithinCurveOrder(s))
throw new Error('Invalid signature');
this.assertValidity();
}

@@ -944,6 +947,11 @@ static fromHex(hex) {

throw new TypeError(`SchnorrSignature.fromHex: expected 64 bytes, not ${bytes.length}`);
const r = bytesToNumber(bytes.slice(0, 32));
const s = bytesToNumber(bytes.slice(32, 64));
const r = bytesToNumber(bytes.subarray(0, 32));
const s = bytesToNumber(bytes.subarray(32, 64));
return new SchnorrSignature(r, s);
}
assertValidity() {
const { r, s } = this;
if (!isValidFieldElement(r) || !isWithinCurveOrder(s))
throw new Error('Invalid signature');
}
toHex() {

@@ -979,18 +987,32 @@ return numTo32bStr(this.r) + numTo32bStr(this.s);

const e = await createChallenge(R.x, P, m);
const sig = new SchnorrSignature(R.x, mod(k + e * d, n));
const isValid = await schnorrVerify(sig.toRawBytes(), m, P.toRawX());
const sig = new SchnorrSignature(R.x, mod(k + e * d, n)).toRawBytes();
const isValid = await schnorrVerify(sig, m, P.toRawX());
if (!isValid)
throw new Error('sign: Invalid signature produced');
return sig.toRawBytes();
return sig;
}
async function schnorrVerify(signature, message, publicKey) {
const sig = signature instanceof SchnorrSignature ? signature : SchnorrSignature.fromHex(signature);
const raw = signature instanceof SchnorrSignature;
let sig;
try {
sig = raw ? signature : SchnorrSignature.fromHex(signature);
if (raw)
sig.assertValidity();
}
catch (error) {
return false;
}
const { r, s } = sig;
const m = ensureBytes(message);
const P = normalizePublicKey(publicKey);
const e = await createChallenge(sig.r, P, m);
const sG = Point.fromPrivateKey(sig.s);
const eP = P.multiply(e);
const R = sG.subtract(eP);
if (R.equals(Point.BASE) || !hasEvenY(R) || R.x !== sig.r)
let P;
try {
P = normalizePublicKey(publicKey);
}
catch (error) {
return false;
}
const e = await createChallenge(r, P, m);
const R = Point.BASE.multiplyAndAddUnsafe(P, normalizePrivateKey(s), mod(-e, CURVE.n));
if (!R || !hasEvenY(R) || R.x !== r)
return false;
return true;

@@ -997,0 +1019,0 @@ }

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

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

@@ -310,4 +310,4 @@ # 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)

Point.fromHex (decompression) x 12,553 ops/sec @ 79μs/op
schnorr.sign x 426 ops/sec @ 2ms/op
schnorr.verify x 520 ops/sec @ 1ms/op
schnorr.sign x 687 ops/sec @ 1ms/op
schnorr.verify x 990 ops/sec @ 1ms/op

@@ -314,0 +314,0 @@ Compare to other libraries (`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