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 1.2.0 to 1.3.0

37

abstract/bls.d.ts

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

import { Hex, PrivKey, CHash } from './utils.js';
import * as htf from './hash-to-curve.js';
import { MapToCurve, Opts as HTFOpts, htfBasicOpts, createHasher } from './hash-to-curve.js';
import { CurvePointsType, ProjPointType as ProjPointType, CurvePointsRes } from './weierstrass.js';
type Fp = bigint;
export type ShortSignatureCoder<Fp> = {
fromHex(hex: Hex): ProjPointType<Fp>;
toRawBytes(point: ProjPointType<Fp>): Uint8Array;
toHex(point: ProjPointType<Fp>): string;
};
export type SignatureCoder<Fp2> = {

@@ -28,9 +33,10 @@ fromHex(hex: Hex): ProjPointType<Fp2>;

G1: Omit<CurvePointsType<Fp>, 'n'> & {
mapToCurve: htf.MapToCurve<Fp>;
htfDefaults: htf.Opts;
ShortSignature: SignatureCoder<Fp>;
mapToCurve: MapToCurve<Fp>;
htfDefaults: HTFOpts;
};
G2: Omit<CurvePointsType<Fp2>, 'n'> & {
Signature: SignatureCoder<Fp2>;
mapToCurve: htf.MapToCurve<Fp2>;
htfDefaults: htf.Opts;
mapToCurve: MapToCurve<Fp2>;
htfDefaults: HTFOpts;
};

@@ -60,3 +66,3 @@ fields: {

};
htfDefaults: htf.Opts;
htfDefaults: HTFOpts;
hash: CHash;

@@ -67,2 +73,3 @@ randomBytes: (bytesLength?: number) => Uint8Array;

getPublicKey: (privateKey: PrivKey) => Uint8Array;
getPublicKeyForShortSignatures: (privateKey: PrivKey) => Uint8Array;
sign: {

@@ -72,4 +79,9 @@ (message: Hex, privateKey: PrivKey): Uint8Array;

};
verify: (signature: Hex | ProjPointType<Fp2>, message: Hex | ProjPointType<Fp2>, publicKey: Hex | ProjPointType<Fp>) => boolean;
verifyBatch: (signature: Hex | ProjPointType<Fp2>, messages: (Hex | ProjPointType<Fp2>)[], publicKeys: (Hex | ProjPointType<Fp>)[]) => boolean;
signShortSignature: {
(message: Hex, privateKey: PrivKey): Uint8Array;
(message: ProjPointType<Fp>, privateKey: PrivKey): ProjPointType<Fp>;
};
verify: (signature: Hex | ProjPointType<Fp2>, message: Hex | ProjPointType<Fp2>, publicKey: Hex | ProjPointType<Fp>, htfOpts?: htfBasicOpts) => boolean;
verifyShortSignature: (signature: Hex | ProjPointType<Fp>, message: Hex | ProjPointType<Fp>, publicKey: Hex | ProjPointType<Fp2>, htfOpts?: htfBasicOpts) => boolean;
verifyBatch: (signature: Hex | ProjPointType<Fp2>, messages: (Hex | ProjPointType<Fp2>)[], publicKeys: (Hex | ProjPointType<Fp>)[], htfOpts?: htfBasicOpts) => boolean;
aggregatePublicKeys: {

@@ -83,7 +95,12 @@ (publicKeys: Hex[]): Uint8Array;

};
aggregateShortSignatures: {
(signatures: Hex[]): Uint8Array;
(signatures: ProjPointType<Fp>[]): ProjPointType<Fp>;
};
millerLoop: (ell: [Fp2, Fp2, Fp2][], g1: [Fp, Fp]) => Fp12;
pairing: (P: ProjPointType<Fp>, Q: ProjPointType<Fp2>, withFinalExponent?: boolean) => Fp12;
G1: CurvePointsRes<Fp> & ReturnType<typeof htf.createHasher<Fp>>;
G2: CurvePointsRes<Fp2> & ReturnType<typeof htf.createHasher<Fp2>>;
G1: CurvePointsRes<Fp> & ReturnType<typeof createHasher<Fp>>;
G2: CurvePointsRes<Fp2> & ReturnType<typeof createHasher<Fp2>>;
Signature: SignatureCoder<Fp2>;
ShortSignature: ShortSignatureCoder<Fp>;
params: {

@@ -90,0 +107,0 @@ x: bigint;

@@ -6,3 +6,4 @@ "use strict";

const utils_js_1 = require("./utils.js");
const htf = require("./hash-to-curve.js");
// prettier-ignore
const hash_to_curve_js_1 = require("./hash-to-curve.js");
const weierstrass_js_1 = require("./weierstrass.js");

@@ -32,4 +33,4 @@ // prettier-ignore

ell_coeff.push([
Fp2.sub(t2, t0),
Fp2.mul(Fp2.sqr(Rx), _3n),
Fp2.sub(t2, t0), // T2 - T0
Fp2.mul(Fp2.sqr(Rx), _3n), // 3 * Rx²
Fp2.neg(t4), // -T4

@@ -45,4 +46,4 @@ ]);

ell_coeff.push([
Fp2.sub(Fp2.mul(t0, Qx), Fp2.mul(t1, Qy)),
Fp2.neg(t0),
Fp2.sub(Fp2.mul(t0, Qx), Fp2.mul(t1, Qy)), // T0 * Qx - T1 * Qy
Fp2.neg(t0), // -T0
t1, // T1

@@ -88,3 +89,3 @@ ]);

const G1_ = (0, weierstrass_js_1.weierstrassPoints)({ n: Fr.ORDER, ...CURVE.G1 });
const G1 = Object.assign(G1_, htf.createHasher(G1_.ProjectivePoint, CURVE.G1.mapToCurve, {
const G1 = Object.assign(G1_, (0, hash_to_curve_js_1.createHasher)(G1_.ProjectivePoint, CURVE.G1.mapToCurve, {
...CURVE.htfDefaults,

@@ -107,6 +108,7 @@ ...CURVE.G1.htfDefaults,

const G2_ = (0, weierstrass_js_1.weierstrassPoints)({ n: Fr.ORDER, ...CURVE.G2 });
const G2 = Object.assign(G2_, htf.createHasher(G2_.ProjectivePoint, CURVE.G2.mapToCurve, {
const G2 = Object.assign(G2_, (0, hash_to_curve_js_1.createHasher)(G2_.ProjectivePoint, CURVE.G2.mapToCurve, {
...CURVE.htfDefaults,
...CURVE.G2.htfDefaults,
}));
const { ShortSignature } = CURVE.G1;
const { Signature } = CURVE.G2;

@@ -127,2 +129,7 @@ // Calculates bilinear pairing

}
function normP1Hash(point, htfOpts) {
return point instanceof G1.ProjectivePoint
? point
: G1.hashToCurve((0, utils_js_1.ensureBytes)('point', point), htfOpts);
}
function normP2(point) {

@@ -136,3 +143,3 @@ return point instanceof G2.ProjectivePoint ? point : Signature.fromHex(point);

}
// Multiplies generator by private key.
// Multiplies generator (G1) by private key.
// P = pk x G

@@ -142,2 +149,7 @@ function getPublicKey(privateKey) {

}
// Multiplies generator (G2) by private key.
// P = pk x G
function getPublicKeyForShortSignatures(privateKey) {
return G2.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true);
}
function sign(message, privateKey, htfOpts) {

@@ -151,2 +163,10 @@ const msgPoint = normP2Hash(message, htfOpts);

}
function signShortSignature(message, privateKey, htfOpts) {
const msgPoint = normP1Hash(message, htfOpts);
msgPoint.assertValidity();
const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey));
if (message instanceof G1.ProjectivePoint)
return sigPoint;
return ShortSignature.toRawBytes(sigPoint);
}
// Checks if pairing of public key & hash is equal to pairing of generator & signature.

@@ -166,2 +186,16 @@ // e(P, H(m)) == e(G, S)

}
// Checks if pairing of public key & hash is equal to pairing of generator & signature.
// e(S, G) == e(H(m), P)
function verifyShortSignature(signature, message, publicKey, htfOpts) {
const P = normP2(publicKey);
const Hm = normP1Hash(message, htfOpts);
const G = G2.ProjectivePoint.BASE;
const S = normP1(signature);
// Instead of doing 2 exponentiations, we use property of billinear maps
// and do one exp after multiplying 2 points.
const eHmP = pairing(Hm, P, false);
const eSG = pairing(S, G.negate(), false);
const exp = Fp12.finalExponentiate(Fp12.mul(eSG, eHmP));
return Fp12.eql(exp, Fp12.ONE);
}
function aggregatePublicKeys(publicKeys) {

@@ -190,2 +224,13 @@ if (!publicKeys.length)

}
function aggregateShortSignatures(signatures) {
if (!signatures.length)
throw new Error('Expected non-empty array');
const agg = signatures.map(normP1).reduce((sum, s) => sum.add(s), G1.ProjectivePoint.ZERO);
const aggAffine = agg; //.toAffine();
if (signatures[0] instanceof G1.ProjectivePoint) {
aggAffine.assertValidity();
return aggAffine;
}
return ShortSignature.toRawBytes(aggAffine);
}
// https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407

@@ -223,7 +268,11 @@ // e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))

getPublicKey,
getPublicKeyForShortSignatures,
sign,
signShortSignature,
verify,
verifyBatch,
verifyShortSignature,
aggregatePublicKeys,
aggregateSignatures,
aggregateShortSignatures,
millerLoop,

@@ -234,2 +283,3 @@ pairing,

Signature,
ShortSignature,
fields: {

@@ -236,0 +286,0 @@ Fr,

/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
import type { Group, GroupConstructor, AffinePoint } from './curve.js';
import { IField } from './modular.js';
import { CHash } from './utils.js';
import type { CHash } from './utils.js';
/**

@@ -6,0 +6,0 @@ * * `DST` is a domain separation tag, defined in section 2.2.5

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

function validateDST(dst) {
if (dst instanceof Uint8Array)
if ((0, utils_js_1.isBytes)(dst))
return dst;

@@ -35,4 +35,4 @@ if (typeof dst === 'string')

}
function isBytes(item) {
if (!(item instanceof Uint8Array))
function abytes(item) {
if (!(0, utils_js_1.isBytes)(item))
throw new Error('Uint8Array expected');

@@ -47,4 +47,4 @@ }

function expand_message_xmd(msg, DST, lenInBytes, H) {
isBytes(msg);
isBytes(DST);
abytes(msg);
abytes(DST);
isNum(lenInBytes);

@@ -78,4 +78,4 @@ // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3

function expand_message_xof(msg, DST, lenInBytes, k, H) {
isBytes(msg);
isBytes(DST);
abytes(msg);
abytes(DST);
isNum(lenInBytes);

@@ -116,3 +116,3 @@ // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3

const { p, k, m, hash, expand, DST: _DST } = options;
isBytes(msg);
abytes(msg);
isNum(count);

@@ -119,0 +119,0 @@ const DST = validateDST(_DST);

@@ -122,8 +122,5 @@ "use strict";

// MUST mask the most significant bit in the final byte.
// This is very ugly way, but it works because fieldLen-1 is outside of bounds for X448, so this becomes NOOP
// fieldLen - scalaryBytes = 1 for X448 and = 0 for X25519
const u = (0, utils_js_1.ensureBytes)('u coordinate', uEnc, montgomeryBytes);
// u[fieldLen-1] crashes QuickJS (TypeError: out-of-bound numeric index)
if (fieldLen === montgomeryBytes)
u[fieldLen - 1] &= 127; // 0b0111_1111
if (fieldLen === 32)
u[31] &= 127; // 0b0111_1111
return (0, utils_js_1.bytesToNumberLE)(u);

@@ -133,4 +130,5 @@ }

const bytes = (0, utils_js_1.ensureBytes)('scalar', n);
if (bytes.length !== montgomeryBytes && bytes.length !== fieldLen)
throw new Error(`Expected ${montgomeryBytes} or ${fieldLen} bytes, got ${bytes.length}`);
const len = bytes.length;
if (len !== montgomeryBytes && len !== fieldLen)
throw new Error(`Expected ${montgomeryBytes} or ${fieldLen} bytes, got ${len}`);
return (0, utils_js_1.bytesToNumberLE)(adjustScalarBytes(bytes));

@@ -137,0 +135,0 @@ }

@@ -12,2 +12,3 @@ export type Hex = Uint8Array | string;

export type FHash = (message: Uint8Array | string) => Uint8Array;
export declare function isBytes(a: unknown): a is Uint8Array;
/**

@@ -42,3 +43,3 @@ * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'

export declare function concatBytes(...arrays: Uint8Array[]): Uint8Array;
export declare function equalBytes(b1: Uint8Array, b2: Uint8Array): boolean;
export declare function equalBytes(a: Uint8Array, b: Uint8Array): boolean;
/**

@@ -45,0 +46,0 @@ * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateObject = exports.createHmacDrbg = exports.bitMask = exports.bitSet = exports.bitGet = exports.bitLen = exports.utf8ToBytes = 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.createHmacDrbg = exports.bitMask = exports.bitSet = exports.bitGet = exports.bitLen = exports.utf8ToBytes = exports.equalBytes = exports.concatBytes = exports.ensureBytes = exports.numberToVarBytesBE = exports.numberToBytesLE = exports.numberToBytesBE = exports.bytesToNumberLE = exports.bytesToNumberBE = exports.hexToBytes = exports.hexToNumber = exports.numberToHexUnpadded = exports.bytesToHex = exports.isBytes = void 0;
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */

@@ -12,3 +12,8 @@ // 100 lines of code in the file are duplicated from noble-hashes (utils).

const _2n = BigInt(2);
const u8a = (a) => a instanceof Uint8Array;
function isBytes(a) {
return (a instanceof Uint8Array ||
(a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array'));
}
exports.isBytes = isBytes;
// Array where index 0xf0 (240) is mapped to string 'f0'
const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));

@@ -19,3 +24,3 @@ /**

function bytesToHex(bytes) {
if (!u8a(bytes))
if (!isBytes(bytes))
throw new Error('Uint8Array expected');

@@ -42,2 +47,13 @@ // pre-caching improves the speed 6x

exports.hexToNumber = hexToNumber;
// We use optimized technique to convert hex string to byte array
const asciis = { _0: 48, _9: 57, _A: 65, _F: 70, _a: 97, _f: 102 };
function asciiToBase16(char) {
if (char >= asciis._0 && char <= asciis._9)
return char - asciis._0;
if (char >= asciis._A && char <= asciis._F)
return char - (asciis._A - 10);
if (char >= asciis._a && char <= asciis._f)
return char - (asciis._a - 10);
return;
}
/**

@@ -49,13 +65,15 @@ * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])

throw new Error('hex string expected, got ' + typeof hex);
const len = hex.length;
if (len % 2)
throw new Error('padded hex string expected, got unpadded hex of length ' + len);
const array = new Uint8Array(len / 2);
for (let i = 0; i < array.length; i++) {
const j = i * 2;
const hexByte = hex.slice(j, j + 2);
const byte = Number.parseInt(hexByte, 16);
if (Number.isNaN(byte) || byte < 0)
throw new Error('Invalid byte sequence');
array[i] = byte;
const hl = hex.length;
const al = hl / 2;
if (hl % 2)
throw new Error('padded hex string expected, got unpadded hex of length ' + hl);
const array = new Uint8Array(al);
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
const n1 = asciiToBase16(hex.charCodeAt(hi));
const n2 = asciiToBase16(hex.charCodeAt(hi + 1));
if (n1 === undefined || n2 === undefined) {
const char = hex[hi] + hex[hi + 1];
throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi);
}
array[ai] = n1 * 16 + n2;
}

@@ -71,3 +89,3 @@ return array;

function bytesToNumberLE(bytes) {
if (!u8a(bytes))
if (!isBytes(bytes))
throw new Error('Uint8Array expected');

@@ -109,3 +127,3 @@ return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));

}
else if (u8a(hex)) {
else if (isBytes(hex)) {
// Uint8Array.from() instead of hash.slice() because node.js Buffer

@@ -128,21 +146,27 @@ // is instance of Uint8Array, and its slice() creates **mutable** copy

function concatBytes(...arrays) {
const r = new Uint8Array(arrays.reduce((sum, a) => sum + a.length, 0));
let pad = 0; // walk through each item, ensure they have proper type
arrays.forEach((a) => {
if (!u8a(a))
let sum = 0;
for (let i = 0; i < arrays.length; i++) {
const a = arrays[i];
if (!isBytes(a))
throw new Error('Uint8Array expected');
r.set(a, pad);
sum += a.length;
}
let res = new Uint8Array(sum);
let pad = 0;
for (let i = 0; i < arrays.length; i++) {
const a = arrays[i];
res.set(a, pad);
pad += a.length;
});
return r;
}
return res;
}
exports.concatBytes = concatBytes;
function equalBytes(b1, b2) {
// We don't care about timing attacks here
if (b1.length !== b2.length)
// Compares 2 u8a-s in kinda constant time
function equalBytes(a, b) {
if (a.length !== b.length)
return false;
for (let i = 0; i < b1.length; i++)
if (b1[i] !== b2[i])
return false;
return true;
let diff = 0;
for (let i = 0; i < a.length; i++)
diff |= a[i] ^ b[i];
return diff === 0;
}

@@ -261,3 +285,3 @@ exports.equalBytes = equalBytes;

string: (val) => typeof val === 'string',
stringOrUint8Array: (val) => typeof val === 'string' || val instanceof Uint8Array,
stringOrUint8Array: (val) => typeof val === 'string' || isBytes(val),
isSafeInteger: (val) => Number.isSafeInteger(val),

@@ -264,0 +288,0 @@ array: (val) => Array.isArray(val),

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

};
declare function validatePointOpts<T>(curve: CurvePointsType<T>): Readonly<{
readonly nBitLength: number;
readonly nByteLength: number;
readonly Fp: mod.IField<T>;
readonly n: bigint;
readonly h: bigint;
readonly hEff?: bigint | undefined;
readonly Gx: T;
readonly Gy: T;
readonly allowInfinityPoint?: boolean | undefined;
readonly a: T;
readonly b: T;
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
readonly wrapPrivateKey?: boolean | undefined;
readonly endo?: EndomorphismOpts | undefined;
readonly isTorsionFree?: ((c: ProjConstructor<T>, point: ProjPointType<T>) => boolean) | undefined;
readonly clearCofactor?: ((c: ProjConstructor<T>, point: ProjPointType<T>) => ProjPointType<T>) | undefined;
readonly fromBytes?: ((bytes: Uint8Array) => AffinePoint<T>) | undefined;
readonly toBytes?: ((c: ProjConstructor<T>, point: ProjPointType<T>, isCompressed: boolean) => Uint8Array) | undefined;
readonly p: bigint;
}>;
export type CurvePointsRes<T> = {
CURVE: ReturnType<typeof validatePointOpts<T>>;
ProjectivePoint: ProjConstructor<T>;

@@ -114,29 +136,3 @@ normPrivateKeyToScalar: (key: PrivKey) => bigint;

};
export declare function weierstrassPoints<T>(opts: CurvePointsType<T>): {
CURVE: Readonly<{
readonly nBitLength: number;
readonly nByteLength: number;
readonly Fp: mod.IField<T>;
readonly n: bigint;
readonly h: bigint;
readonly hEff?: bigint | undefined;
readonly Gx: T;
readonly Gy: T;
readonly allowInfinityPoint?: boolean | undefined;
readonly a: T;
readonly b: T;
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
readonly wrapPrivateKey?: boolean | undefined;
readonly endo?: EndomorphismOpts | undefined;
readonly isTorsionFree?: ((c: ProjConstructor<T>, point: ProjPointType<T>) => boolean) | undefined;
readonly clearCofactor?: ((c: ProjConstructor<T>, point: ProjPointType<T>) => ProjPointType<T>) | undefined;
readonly fromBytes?: ((bytes: Uint8Array) => AffinePoint<T>) | undefined;
readonly toBytes?: ((c: ProjConstructor<T>, point: ProjPointType<T>, isCompressed: boolean) => Uint8Array) | undefined;
readonly p: bigint;
}>;
ProjectivePoint: ProjConstructor<T>;
normPrivateKeyToScalar: (key: PrivKey) => bigint;
weierstrassEquation: (x: T) => T;
isWithinCurveOrder: (num: bigint) => boolean;
};
export declare function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T>;
export interface SignatureType {

@@ -143,0 +139,0 @@ readonly r: bigint;

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

const data = typeof hex === 'string' ? h2b(hex) : hex;
if (!(data instanceof Uint8Array))
if (!ut.isBytes(data))
throw new Error('ui8a expected');

@@ -147,3 +147,3 @@ let l = data.length;

if (lengths && typeof key !== 'bigint') {
if (key instanceof Uint8Array)
if (ut.isBytes(key))
key = ut.bytesToHex(key);

@@ -727,3 +727,3 @@ // Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes

function isProbPub(item) {
const arr = item instanceof Uint8Array;
const arr = ut.isBytes(item);
const str = typeof item === 'string';

@@ -889,3 +889,3 @@ const len = (arr || str) && item.length;

try {
if (typeof sg === 'string' || sg instanceof Uint8Array) {
if (typeof sg === 'string' || ut.isBytes(sg)) {
// Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length).

@@ -892,0 +892,0 @@ // Since DER can also be 2*nByteLength bytes, we check for it first.

@@ -5,13 +5,7 @@ "use strict";

exports.bls12_381 = void 0;
// bls12-381 pairing-friendly Barreto-Lynn-Scott elliptic curve construction allows to:
// - Construct zk-SNARKs at the 128-bit security
// - Use threshold signatures, which allows a user to sign lots of messages with one signature and
// verify them swiftly in a batch, using Boneh-Lynn-Shacham signature scheme.
// bls12-381 is pairing-friendly Barreto-Lynn-Scott elliptic curve construction allowing to:
// - Construct zk-SNARKs at the 120-bit security
// - Efficiently verify N aggregate signatures with 1 pairing and N ec additions:
// the Boneh-Lynn-Shacham signature scheme is orders of magnitude more efficient than Schnorr
//
// The library uses G1 for public keys and G2 for signatures. Support for G1 signatures is planned.
// Compatible with Algorand, Chia, Dfinity, Ethereum, FIL, Zcash. Matches specs
// [pairing-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11),
// [bls-sigs-04](https:/cfrg-hash-to/tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04),
// [hash-to-curve-12](https://tools.ietf.org/html/draft-irtf--curve-12).
//
// ### Summary

@@ -31,4 +25,13 @@ // 1. BLS Relies on Bilinear Pairing (expensive)

// - `e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))` - signature aggregation
// Filecoin uses little endian byte arrays for private keys -
// so ensure to reverse byte order if you'll use it with FIL.
//
// ### Compatibility and notes
// 1. It is compatible with Algorand, Chia, Dfinity, Ethereum, Filecoin, ZEC
// Filecoin uses little endian byte arrays for private keys - make sure to reverse byte order.
// 2. Some projects use G2 for public keys and G1 for signatures. It's called "short signature"
// 3. Curve security level is about 120 bits as per Barbulescu-Duquesne 2017
// https://hal.science/hal-01534101/file/main.pdf
// 4. Compatible with specs:
// [cfrg-pairing-friendly-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11),
// [cfrg-bls-signature-05](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05),
// [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380).
const sha256_1 = require("@noble/hashes/sha256");

@@ -265,4 +268,4 @@ const utils_1 = require("@noble/hashes/utils");

return {
c0: Fp2.add(Fp2.mulByNonresidue(t3), t0),
c1: Fp2.add(Fp2.mulByNonresidue(t4), t1),
c0: Fp2.add(Fp2.mulByNonresidue(t3), t0), // T3 * (u + 1) + T0
c1: Fp2.add(Fp2.mulByNonresidue(t4), t1), // T4 * (u + 1) + T1
// T1 + (c0 - c1 + c2)² + T3 - T0 - T4

@@ -273,3 +276,3 @@ c2: Fp2.sub(Fp2.sub(Fp2.add(Fp2.add(t1, Fp2.sqr(Fp2.add(Fp2.sub(c0, c1), c2))), t3), t0), t4),

const Fp6 = {
ORDER: Fp2.ORDER,
ORDER: Fp2.ORDER, // TODO: unused, but need to verify
BITS: 3 * Fp2.BITS,

@@ -434,3 +437,3 @@ BYTES: 3 * Fp2.BYTES,

return {
c0: Fp6.add(t1, Fp6.mulByNonresidue(t2)),
c0: Fp6.add(t1, Fp6.mulByNonresidue(t2)), // T1 + T2 * v
// (c0 + c1) * (r0 + r1) - (T1 + T2)

@@ -452,3 +455,3 @@ c1: Fp6.sub(Fp6.mul(Fp6.add(c0, c1), Fp6.add(r0, r1)), Fp6.add(t1, t2)),

return {
first: Fp2.add(Fp2.mulByNonresidue(b2), a2),
first: Fp2.add(Fp2.mulByNonresidue(b2), a2), // b² * Nonresidue + a²
second: Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b²

@@ -458,3 +461,3 @@ };

const Fp12 = {
ORDER: Fp2.ORDER,
ORDER: Fp2.ORDER, // TODO: unused, but need to verify
BITS: 2 * Fp2.BITS,

@@ -534,3 +537,3 @@ BYTES: 2 * Fp2.BYTES,

return {
c0: Fp6.add(Fp6.mulByNonresidue(t1), t0),
c0: Fp6.add(Fp6.mulByNonresidue(t1), t0), // T1 * v + T0
// (c1 + c0) * [o0, o1+o4] - T0 - T1

@@ -558,9 +561,9 @@ c1: Fp6.sub(Fp6.sub(Fp6.multiplyBy01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0), t1),

c0: Fp6.create({
c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3),
c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5),
c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3
c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5
c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7),
}),
}), // 2 * (T7 - c0c2) + T7
c1: Fp6.create({
c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9),
c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4),
c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9
c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4
c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6),

@@ -791,4 +794,4 @@ }),

const G2_SWU = (0, weierstrass_js_1.mapToCurveSimpleSWU)(Fp2, {
A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(BigInt(240)) }),
B: Fp2.create({ c0: Fp.create(BigInt(1012)), c1: Fp.create(BigInt(1012)) }),
A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(BigInt(240)) }), // A' = 240 * I
B: Fp2.create({ c0: Fp.create(BigInt(1012)), c1: Fp.create(BigInt(1012)) }), // B' = 1012 * (1 + I)
Z: Fp2.create({ c0: Fp.create(BigInt(-2)), c1: Fp.create(BigInt(-1)) }), // Z: -(2 + I)

@@ -866,7 +869,35 @@ });

// Point on G1 curve: (x, y)
const C_BIT_POS = Fp.BITS; // C_bit, compression bit for serialization flag
const I_BIT_POS = Fp.BITS + 1; // I_bit, point-at-infinity bit for serialization flag
const S_BIT_POS = Fp.BITS + 2; // S_bit, sign bit for serialization flag
// Compressed point of infinity
const COMPRESSED_ZERO = Fp.toBytes((0, utils_js_1.bitSet)((0, utils_js_1.bitSet)(_0n, I_BIT_POS, true), S_BIT_POS, true)); // set compressed & point-at-infinity bits
const COMPRESSED_ZERO = setMask(Fp.toBytes(_0n), { infinity: true, compressed: true }); // set compressed & point-at-infinity bits
function parseMask(bytes) {
// Copy, so we can remove mask data. It will be removed also later, when Fp.create will call modulo.
bytes = bytes.slice();
const mask = bytes[0] & 224;
const compressed = !!((mask >> 7) & 1); // compression bit (0b1000_0000)
const infinity = !!((mask >> 6) & 1); // point at infinity bit (0b0100_0000)
const sort = !!((mask >> 5) & 1); // sort bit (0b0010_0000)
bytes[0] &= 31; // clear mask (zero first 3 bits)
return { compressed, infinity, sort, value: bytes };
}
function setMask(bytes, mask) {
if (bytes[0] & 224)
throw new Error('setMask: non-empty mask');
if (mask.compressed)
bytes[0] |= 128;
if (mask.infinity)
bytes[0] |= 64;
if (mask.sort)
bytes[0] |= 32;
return bytes;
}
function signatureG1ToRawBytes(point) {
point.assertValidity();
const isZero = point.equals(exports.bls12_381.G1.ProjectivePoint.ZERO);
const { x, y } = point.toAffine();
if (isZero)
return COMPRESSED_ZERO.slice();
const P = Fp.ORDER;
const sort = Boolean((y * _2n) / P);
return setMask((0, utils_js_1.numberToBytesBE)(x, Fp.BYTES), { compressed: true, sort });
}
function signatureG2ToRawBytes(point) {

@@ -882,6 +913,5 @@ // NOTE: by some reasons it was missed in bls12-381, looks like bug

const tmp = y1 > _0n ? y1 * _2n : y0 * _2n;
const aflag1 = Boolean((tmp / Fp.ORDER) & _1n);
const z1 = (0, utils_js_1.bitSet)((0, utils_js_1.bitSet)(x1, 381, aflag1), S_BIT_POS, true);
const sort = Boolean((tmp / Fp.ORDER) & _1n);
const z2 = x0;
return (0, utils_js_1.concatBytes)((0, utils_js_1.numberToBytesBE)(z1, len), (0, utils_js_1.numberToBytesBE)(z2, len));
return (0, utils_js_1.concatBytes)(setMask((0, utils_js_1.numberToBytesBE)(x1, len), { sort, compressed: true }), (0, utils_js_1.numberToBytesBE)(z2, len));
}

@@ -920,3 +950,3 @@ // To verify curve parameters, see pairing-friendly-curves spec:

b: _4n,
htfDefaults: { ...htfDefaults, m: 1 },
htfDefaults: { ...htfDefaults, m: 1, DST: 'BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_' },
wrapPrivateKey: true,

@@ -959,12 +989,14 @@ allowInfinityPoint: true,

fromBytes: (bytes) => {
bytes = bytes.slice();
if (bytes.length === 48) {
const { compressed, infinity, sort, value } = parseMask(bytes);
if (value.length === 48 && compressed) {
// TODO: Fp.bytes
const P = Fp.ORDER;
const compressedValue = (0, utils_js_1.bytesToNumberBE)(bytes);
const bflag = (0, utils_js_1.bitGet)(compressedValue, I_BIT_POS);
const compressedValue = (0, utils_js_1.bytesToNumberBE)(value);
// Zero
if (bflag === _1n)
const x = Fp.create(compressedValue & Fp.MASK);
if (infinity) {
if (x !== _0n)
throw new Error('G1: non-empty compressed point at infinity');
return { x: _0n, y: _0n };
const x = Fp.create(compressedValue & Fp.MASK);
}
const right = Fp.add(Fp.pow(x, _3n), Fp.create(exports.bls12_381.params.G1b)); // y² = x³ + b

@@ -974,13 +1006,15 @@ let y = Fp.sqrt(right);

throw new Error('Invalid compressed G1 point');
const aflag = (0, utils_js_1.bitGet)(compressedValue, C_BIT_POS);
if ((y * _2n) / P !== aflag)
if ((y * _2n) / P !== BigInt(sort))
y = Fp.neg(y);
return { x: Fp.create(x), y: Fp.create(y) };
}
else if (bytes.length === 96) {
else if (value.length === 96 && !compressed) {
// Check if the infinity flag is set
if ((bytes[0] & (1 << 6)) !== 0)
const x = (0, utils_js_1.bytesToNumberBE)(value.subarray(0, Fp.BYTES));
const y = (0, utils_js_1.bytesToNumberBE)(value.subarray(Fp.BYTES));
if (infinity) {
if (x !== _0n || y !== _0n)
throw new Error('G1: non-empty point at infinity');
return exports.bls12_381.G1.ProjectivePoint.ZERO.toAffine();
const x = (0, utils_js_1.bytesToNumberBE)(bytes.subarray(0, Fp.BYTES));
const y = (0, utils_js_1.bytesToNumberBE)(bytes.subarray(Fp.BYTES));
}
return { x: Fp.create(x), y: Fp.create(y) };

@@ -999,6 +1033,4 @@ }

const P = Fp.ORDER;
let num;
num = (0, utils_js_1.bitSet)(x, C_BIT_POS, Boolean((y * _2n) / P)); // set aflag
num = (0, utils_js_1.bitSet)(num, S_BIT_POS, true);
return (0, utils_js_1.numberToBytesBE)(num, Fp.BYTES);
const sort = Boolean((y * _2n) / P);
return setMask((0, utils_js_1.numberToBytesBE)(x, Fp.BYTES), { compressed: true, sort });
}

@@ -1016,2 +1048,29 @@ else {

},
ShortSignature: {
fromHex(hex) {
const { infinity, sort, value } = parseMask((0, utils_js_1.ensureBytes)('signatureHex', hex, 48));
const P = Fp.ORDER;
const compressedValue = (0, utils_js_1.bytesToNumberBE)(value);
// Zero
if (infinity)
return exports.bls12_381.G1.ProjectivePoint.ZERO;
const x = Fp.create(compressedValue & Fp.MASK);
const right = Fp.add(Fp.pow(x, _3n), Fp.create(exports.bls12_381.params.G1b)); // y² = x³ + b
let y = Fp.sqrt(right);
if (!y)
throw new Error('Invalid compressed G1 point');
const aflag = BigInt(sort);
if ((y * _2n) / P !== aflag)
y = Fp.neg(y);
const point = exports.bls12_381.G1.ProjectivePoint.fromAffine({ x, y });
point.assertValidity();
return point;
},
toRawBytes(point) {
return signatureG1ToRawBytes(point);
},
toHex(point) {
return (0, utils_js_1.bytesToHex)(signatureG1ToRawBytes(point));
},
},
},

@@ -1076,19 +1135,17 @@ // G2 is the order-q subgroup of E2(Fp²) : y² = x³+4(1+√−1),

fromBytes: (bytes) => {
bytes = bytes.slice();
const m_byte = bytes[0] & 0xe0;
if (m_byte === 0x20 || m_byte === 0x60 || m_byte === 0xe0) {
throw new Error('Invalid encoding flag: ' + m_byte);
const { compressed, infinity, sort, value } = parseMask(bytes);
if ((!compressed && !infinity && sort) || // 00100000
(!compressed && infinity && sort) || // 01100000
(sort && infinity && compressed) // 11100000
) {
throw new Error('Invalid encoding flag: ' + (bytes[0] & 224));
}
const bitC = m_byte & 0x80; // compression bit
const bitI = m_byte & 0x40; // point at infinity bit
const bitS = m_byte & 0x20; // sign bit
const L = Fp.BYTES;
const slc = (b, from, to) => (0, utils_js_1.bytesToNumberBE)(b.slice(from, to));
if (bytes.length === 96 && bitC) {
if (value.length === 96 && compressed) {
const b = exports.bls12_381.params.G2b;
const P = Fp.ORDER;
bytes[0] = bytes[0] & 0x1f; // clear flags
if (bitI) {
if (infinity) {
// check that all bytes are 0
if (bytes.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) {
if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) {
throw new Error('Invalid compressed G2 point');

@@ -1098,4 +1155,4 @@ }

}
const x_1 = slc(bytes, 0, L);
const x_0 = slc(bytes, L, 2 * L);
const x_1 = slc(value, 0, L);
const x_0 = slc(value, L, 2 * L);
const x = Fp2.create({ c0: Fp.create(x_0), c1: Fp.create(x_1) });

@@ -1105,14 +1162,16 @@ const right = Fp2.add(Fp2.pow(x, _3n), b); // y² = x³ + 4 * (u+1) = x³ + b

const Y_bit = y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P ? _1n : _0n;
y = bitS > 0 && Y_bit > 0 ? y : Fp2.neg(y);
y = sort && Y_bit > 0 ? y : Fp2.neg(y);
return { x, y };
}
else if (bytes.length === 192 && !bitC) {
// Check if the infinity flag is set
if ((bytes[0] & (1 << 6)) !== 0) {
else if (value.length === 192 && !compressed) {
if (infinity) {
if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) {
throw new Error('Invalid uncompressed G2 point');
}
return { x: Fp2.ZERO, y: Fp2.ZERO };
}
const x1 = slc(bytes, 0, L);
const x0 = slc(bytes, L, 2 * L);
const y1 = slc(bytes, 2 * L, 3 * L);
const y0 = slc(bytes, 3 * L, 4 * L);
const x1 = slc(value, 0, L);
const x0 = slc(value, L, 2 * L);
const y1 = slc(value, 2 * L, 3 * L);
const y0 = slc(value, 3 * L, 4 * L);
return { x: Fp2.fromBigTuple([x0, x1]), y: Fp2.fromBigTuple([y0, y1]) };

@@ -1132,6 +1191,3 @@ }

const flag = Boolean(y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P);
// set compressed & sign bits (looks like different offsets than for G1/Fp?)
let x_1 = (0, utils_js_1.bitSet)(x.c1, C_BIT_POS, flag);
x_1 = (0, utils_js_1.bitSet)(x_1, S_BIT_POS, true);
return (0, utils_js_1.concatBytes)((0, utils_js_1.numberToBytesBE)(x_1, len), (0, utils_js_1.numberToBytesBE)(x.c0, len));
return (0, utils_js_1.concatBytes)(setMask((0, utils_js_1.numberToBytesBE)(x.c1, len), { compressed: true, sort: flag }), (0, utils_js_1.numberToBytesBE)(x.c0, len));
}

@@ -1149,3 +1205,3 @@ else {

fromHex(hex) {
hex = (0, utils_js_1.ensureBytes)('signatureHex', hex);
const { infinity, sort, value } = parseMask((0, utils_js_1.ensureBytes)('signatureHex', hex));
const P = Fp.ORDER;

@@ -1155,7 +1211,6 @@ const half = hex.length / 2;

throw new Error('Invalid compressed signature length, must be 96 or 192');
const z1 = (0, utils_js_1.bytesToNumberBE)(hex.slice(0, half));
const z2 = (0, utils_js_1.bytesToNumberBE)(hex.slice(half));
const z1 = (0, utils_js_1.bytesToNumberBE)(value.slice(0, half));
const z2 = (0, utils_js_1.bytesToNumberBE)(value.slice(half));
// Indicates the infinity point
const bflag1 = (0, utils_js_1.bitGet)(z1, I_BIT_POS);
if (bflag1 === _1n)
if (infinity)
return exports.bls12_381.G2.ProjectivePoint.ZERO;

@@ -1173,3 +1228,3 @@ const x1 = Fp.create(z1 & Fp.MASK);

const { re: y0, im: y1 } = Fp2.reim(y);
const aflag1 = (0, utils_js_1.bitGet)(z1, 381);
const aflag1 = BigInt(sort);
const isGreater = y1 > _0n && (y1 * _2n) / P !== aflag1;

@@ -1192,3 +1247,3 @@ const isZero = y1 === _0n && (y0 * _2n) / P !== aflag1;

params: {
x: BLS_X,
x: BLS_X, // The BLS parameter x for BLS12-381
r: Fr.ORDER, // order; z⁴ − z² + 1; CURVE.n from other curves

@@ -1195,0 +1250,0 @@ },

/**
* bn254 pairing-friendly curve.
* Previously known as alt_bn_128, when it had 128-bit security.
* Recent research shown it's weaker, the naming has been adjusted to its prime bit count.
* https://github.com/zcash/zcash/issues/2502
* Barbulescu-Duquesne 2017 shown it's weaker: just about 100 bits,
* so the naming has been adjusted to its prime bit count
* https://hal.science/hal-01534101/file/main.pdf
*/
export declare const bn254: import("./abstract/weierstrass.js").CurveFn;
//# sourceMappingURL=bn254.d.ts.map

@@ -12,4 +12,5 @@ "use strict";

* Previously known as alt_bn_128, when it had 128-bit security.
* Recent research shown it's weaker, the naming has been adjusted to its prime bit count.
* https://github.com/zcash/zcash/issues/2502
* Barbulescu-Duquesne 2017 shown it's weaker: just about 100 bits,
* so the naming has been adjusted to its prime bit count
* https://hal.science/hal-01534101/file/main.pdf
*/

@@ -16,0 +17,0 @@ exports.bn254 = (0, weierstrass_js_1.weierstrass)({

import { ExtPointType } from './abstract/edwards.js';
import { Hex } from './abstract/utils.js';
import { htfBasicOpts } from './abstract/hash-to-curve.js';
import { AffinePoint } from './abstract/curve.js';
import { AffinePoint, Group } from './abstract/curve.js';
export declare const ED25519_TORSION_SUBGROUP: string[];

@@ -39,3 +39,3 @@ export declare const ed25519: import("./abstract/edwards.js").CurveFn;

*/
declare class RistPoint {
declare class RistPoint implements Group<RistPoint> {
private readonly ep;

@@ -72,2 +72,4 @@ static BASE: RistPoint;

multiplyUnsafe(scalar: bigint): RistPoint;
double(): RistPoint;
negate(): RistPoint;
}

@@ -74,0 +76,0 @@ export declare const RistrettoPoint: typeof RistPoint;

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

// Param: a
a: BigInt(-1),
a: BigInt(-1), // Fp.create(-1) is proper; our way still works and is faster
// d is equal to -121665/121666 over finite field.

@@ -129,3 +129,3 @@ // Negative number is P - number, and division is invert(number, P)

a: BigInt(486662),
montgomeryBits: 255,
montgomeryBits: 255, // n is 253 bits
nByteLength: 32,

@@ -423,2 +423,8 @@ Gu: BigInt(9),

}
double() {
return new RistPoint(this.ep.double());
}
negate() {
return new RistPoint(this.ep.negate());
}
}

@@ -425,0 +431,0 @@ exports.RistrettoPoint = (() => {

import { ExtPointType } from './abstract/edwards.js';
import { htfBasicOpts } from './abstract/hash-to-curve.js';
import { Hex } from './abstract/utils.js';
import { AffinePoint } from './abstract/curve.js';
import { AffinePoint, Group } from './abstract/curve.js';
export declare const ed448: import("./abstract/edwards.js").CurveFn;

@@ -28,3 +28,3 @@ export declare const ed448ph: import("./abstract/edwards.js").CurveFn;

*/
declare class DcfPoint {
declare class DcfPoint implements Group<DcfPoint> {
private readonly ep;

@@ -61,2 +61,4 @@ static BASE: DcfPoint;

multiplyUnsafe(scalar: bigint): DcfPoint;
double(): DcfPoint;
negate(): DcfPoint;
}

@@ -63,0 +65,0 @@ export declare const DecafPoint: typeof DcfPoint;

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

n: BigInt('181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779'),
// RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys
nBitLength: 456,

@@ -111,4 +112,5 @@ // Cofactor

a: BigInt(156326),
// RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys
montgomeryBits: 448,
nByteLength: 57,
nByteLength: 56,
P: ed448P,

@@ -140,2 +142,3 @@ Gu: BigInt(5),

exports.edwardsToMontgomery = edwardsToMontgomeryPub; // deprecated
// TODO: add edwardsToMontgomeryPriv, similar to ed25519 version
// Hash To Curve Elligator2 Map

@@ -380,2 +383,8 @@ const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4); // 1. c1 = (q - 3) / 4 # Integer arithmetic

}
double() {
return new DcfPoint(this.ep.double());
}
negate() {
return new DcfPoint(this.ep.negate());
}
}

@@ -382,0 +391,0 @@ exports.DecafPoint = (() => {

import { getMinHashLength, mapHashToField } from './modular.js';
import { bitLen, bitGet, ensureBytes } from './utils.js';
import * as htf from './hash-to-curve.js';
// prettier-ignore
import { createHasher } from './hash-to-curve.js';
import { weierstrassPoints, } from './weierstrass.js';

@@ -28,4 +29,4 @@ // prettier-ignore

ell_coeff.push([
Fp2.sub(t2, t0),
Fp2.mul(Fp2.sqr(Rx), _3n),
Fp2.sub(t2, t0), // T2 - T0
Fp2.mul(Fp2.sqr(Rx), _3n), // 3 * Rx²
Fp2.neg(t4), // -T4

@@ -41,4 +42,4 @@ ]);

ell_coeff.push([
Fp2.sub(Fp2.mul(t0, Qx), Fp2.mul(t1, Qy)),
Fp2.neg(t0),
Fp2.sub(Fp2.mul(t0, Qx), Fp2.mul(t1, Qy)), // T0 * Qx - T1 * Qy
Fp2.neg(t0), // -T0
t1, // T1

@@ -84,3 +85,3 @@ ]);

const G1_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G1 });
const G1 = Object.assign(G1_, htf.createHasher(G1_.ProjectivePoint, CURVE.G1.mapToCurve, {
const G1 = Object.assign(G1_, createHasher(G1_.ProjectivePoint, CURVE.G1.mapToCurve, {
...CURVE.htfDefaults,

@@ -103,6 +104,7 @@ ...CURVE.G1.htfDefaults,

const G2_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G2 });
const G2 = Object.assign(G2_, htf.createHasher(G2_.ProjectivePoint, CURVE.G2.mapToCurve, {
const G2 = Object.assign(G2_, createHasher(G2_.ProjectivePoint, CURVE.G2.mapToCurve, {
...CURVE.htfDefaults,
...CURVE.G2.htfDefaults,
}));
const { ShortSignature } = CURVE.G1;
const { Signature } = CURVE.G2;

@@ -123,2 +125,7 @@ // Calculates bilinear pairing

}
function normP1Hash(point, htfOpts) {
return point instanceof G1.ProjectivePoint
? point
: G1.hashToCurve(ensureBytes('point', point), htfOpts);
}
function normP2(point) {

@@ -132,3 +139,3 @@ return point instanceof G2.ProjectivePoint ? point : Signature.fromHex(point);

}
// Multiplies generator by private key.
// Multiplies generator (G1) by private key.
// P = pk x G

@@ -138,2 +145,7 @@ function getPublicKey(privateKey) {

}
// Multiplies generator (G2) by private key.
// P = pk x G
function getPublicKeyForShortSignatures(privateKey) {
return G2.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true);
}
function sign(message, privateKey, htfOpts) {

@@ -147,2 +159,10 @@ const msgPoint = normP2Hash(message, htfOpts);

}
function signShortSignature(message, privateKey, htfOpts) {
const msgPoint = normP1Hash(message, htfOpts);
msgPoint.assertValidity();
const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey));
if (message instanceof G1.ProjectivePoint)
return sigPoint;
return ShortSignature.toRawBytes(sigPoint);
}
// Checks if pairing of public key & hash is equal to pairing of generator & signature.

@@ -162,2 +182,16 @@ // e(P, H(m)) == e(G, S)

}
// Checks if pairing of public key & hash is equal to pairing of generator & signature.
// e(S, G) == e(H(m), P)
function verifyShortSignature(signature, message, publicKey, htfOpts) {
const P = normP2(publicKey);
const Hm = normP1Hash(message, htfOpts);
const G = G2.ProjectivePoint.BASE;
const S = normP1(signature);
// Instead of doing 2 exponentiations, we use property of billinear maps
// and do one exp after multiplying 2 points.
const eHmP = pairing(Hm, P, false);
const eSG = pairing(S, G.negate(), false);
const exp = Fp12.finalExponentiate(Fp12.mul(eSG, eHmP));
return Fp12.eql(exp, Fp12.ONE);
}
function aggregatePublicKeys(publicKeys) {

@@ -186,2 +220,13 @@ if (!publicKeys.length)

}
function aggregateShortSignatures(signatures) {
if (!signatures.length)
throw new Error('Expected non-empty array');
const agg = signatures.map(normP1).reduce((sum, s) => sum.add(s), G1.ProjectivePoint.ZERO);
const aggAffine = agg; //.toAffine();
if (signatures[0] instanceof G1.ProjectivePoint) {
aggAffine.assertValidity();
return aggAffine;
}
return ShortSignature.toRawBytes(aggAffine);
}
// https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407

@@ -219,7 +264,11 @@ // e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))

getPublicKey,
getPublicKeyForShortSignatures,
sign,
signShortSignature,
verify,
verifyBatch,
verifyShortSignature,
aggregatePublicKeys,
aggregateSignatures,
aggregateShortSignatures,
millerLoop,

@@ -230,2 +279,3 @@ pairing,

Signature,
ShortSignature,
fields: {

@@ -232,0 +282,0 @@ Fr,

import { mod } from './modular.js';
import { bytesToNumberBE, concatBytes, utf8ToBytes, validateObject } from './utils.js';
import { bytesToNumberBE, isBytes, concatBytes, utf8ToBytes, validateObject } from './utils.js';
function validateDST(dst) {
if (dst instanceof Uint8Array)
if (isBytes(dst))
return dst;

@@ -31,4 +31,4 @@ if (typeof dst === 'string')

}
function isBytes(item) {
if (!(item instanceof Uint8Array))
function abytes(item) {
if (!isBytes(item))
throw new Error('Uint8Array expected');

@@ -43,4 +43,4 @@ }

export function expand_message_xmd(msg, DST, lenInBytes, H) {
isBytes(msg);
isBytes(DST);
abytes(msg);
abytes(DST);
isNum(lenInBytes);

@@ -73,4 +73,4 @@ // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3

export function expand_message_xof(msg, DST, lenInBytes, k, H) {
isBytes(msg);
isBytes(DST);
abytes(msg);
abytes(DST);
isNum(lenInBytes);

@@ -110,3 +110,3 @@ // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3

const { p, k, m, hash, expand, DST: _DST } = options;
isBytes(msg);
abytes(msg);
isNum(count);

@@ -113,0 +113,0 @@ const DST = validateDST(_DST);

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

// MUST mask the most significant bit in the final byte.
// This is very ugly way, but it works because fieldLen-1 is outside of bounds for X448, so this becomes NOOP
// fieldLen - scalaryBytes = 1 for X448 and = 0 for X25519
const u = ensureBytes('u coordinate', uEnc, montgomeryBytes);
// u[fieldLen-1] crashes QuickJS (TypeError: out-of-bound numeric index)
if (fieldLen === montgomeryBytes)
u[fieldLen - 1] &= 127; // 0b0111_1111
if (fieldLen === 32)
u[31] &= 127; // 0b0111_1111
return bytesToNumberLE(u);

@@ -130,4 +127,5 @@ }

const bytes = ensureBytes('scalar', n);
if (bytes.length !== montgomeryBytes && bytes.length !== fieldLen)
throw new Error(`Expected ${montgomeryBytes} or ${fieldLen} bytes, got ${bytes.length}`);
const len = bytes.length;
if (len !== montgomeryBytes && len !== fieldLen)
throw new Error(`Expected ${montgomeryBytes} or ${fieldLen} bytes, got ${len}`);
return bytesToNumberLE(adjustScalarBytes(bytes));

@@ -134,0 +132,0 @@ }

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

const _2n = BigInt(2);
const u8a = (a) => a instanceof Uint8Array;
export function isBytes(a) {
return (a instanceof Uint8Array ||
(a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array'));
}
// Array where index 0xf0 (240) is mapped to string 'f0'
const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));

@@ -16,3 +20,3 @@ /**

export function bytesToHex(bytes) {
if (!u8a(bytes))
if (!isBytes(bytes))
throw new Error('Uint8Array expected');

@@ -36,2 +40,13 @@ // pre-caching improves the speed 6x

}
// We use optimized technique to convert hex string to byte array
const asciis = { _0: 48, _9: 57, _A: 65, _F: 70, _a: 97, _f: 102 };
function asciiToBase16(char) {
if (char >= asciis._0 && char <= asciis._9)
return char - asciis._0;
if (char >= asciis._A && char <= asciis._F)
return char - (asciis._A - 10);
if (char >= asciis._a && char <= asciis._f)
return char - (asciis._a - 10);
return;
}
/**

@@ -43,13 +58,15 @@ * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])

throw new Error('hex string expected, got ' + typeof hex);
const len = hex.length;
if (len % 2)
throw new Error('padded hex string expected, got unpadded hex of length ' + len);
const array = new Uint8Array(len / 2);
for (let i = 0; i < array.length; i++) {
const j = i * 2;
const hexByte = hex.slice(j, j + 2);
const byte = Number.parseInt(hexByte, 16);
if (Number.isNaN(byte) || byte < 0)
throw new Error('Invalid byte sequence');
array[i] = byte;
const hl = hex.length;
const al = hl / 2;
if (hl % 2)
throw new Error('padded hex string expected, got unpadded hex of length ' + hl);
const array = new Uint8Array(al);
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
const n1 = asciiToBase16(hex.charCodeAt(hi));
const n2 = asciiToBase16(hex.charCodeAt(hi + 1));
if (n1 === undefined || n2 === undefined) {
const char = hex[hi] + hex[hi + 1];
throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi);
}
array[ai] = n1 * 16 + n2;
}

@@ -63,3 +80,3 @@ return array;

export function bytesToNumberLE(bytes) {
if (!u8a(bytes))
if (!isBytes(bytes))
throw new Error('Uint8Array expected');

@@ -97,3 +114,3 @@ return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));

}
else if (u8a(hex)) {
else if (isBytes(hex)) {
// Uint8Array.from() instead of hash.slice() because node.js Buffer

@@ -115,20 +132,26 @@ // is instance of Uint8Array, and its slice() creates **mutable** copy

export function concatBytes(...arrays) {
const r = new Uint8Array(arrays.reduce((sum, a) => sum + a.length, 0));
let pad = 0; // walk through each item, ensure they have proper type
arrays.forEach((a) => {
if (!u8a(a))
let sum = 0;
for (let i = 0; i < arrays.length; i++) {
const a = arrays[i];
if (!isBytes(a))
throw new Error('Uint8Array expected');
r.set(a, pad);
sum += a.length;
}
let res = new Uint8Array(sum);
let pad = 0;
for (let i = 0; i < arrays.length; i++) {
const a = arrays[i];
res.set(a, pad);
pad += a.length;
});
return r;
}
return res;
}
export function equalBytes(b1, b2) {
// We don't care about timing attacks here
if (b1.length !== b2.length)
// Compares 2 u8a-s in kinda constant time
export function equalBytes(a, b) {
if (a.length !== b.length)
return false;
for (let i = 0; i < b1.length; i++)
if (b1[i] !== b2[i])
return false;
return true;
let diff = 0;
for (let i = 0; i < a.length; i++)
diff |= a[i] ^ b[i];
return diff === 0;
}

@@ -240,3 +263,3 @@ /**

string: (val) => typeof val === 'string',
stringOrUint8Array: (val) => typeof val === 'string' || val instanceof Uint8Array,
stringOrUint8Array: (val) => typeof val === 'string' || isBytes(val),
isSafeInteger: (val) => Number.isSafeInteger(val),

@@ -243,0 +266,0 @@ array: (val) => Array.isArray(val),

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

const data = typeof hex === 'string' ? h2b(hex) : hex;
if (!(data instanceof Uint8Array))
if (!ut.isBytes(data))
throw new Error('ui8a expected');

@@ -144,3 +144,3 @@ let l = data.length;

if (lengths && typeof key !== 'bigint') {
if (key instanceof Uint8Array)
if (ut.isBytes(key))
key = ut.bytesToHex(key);

@@ -723,3 +723,3 @@ // Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes

function isProbPub(item) {
const arr = item instanceof Uint8Array;
const arr = ut.isBytes(item);
const str = typeof item === 'string';

@@ -885,3 +885,3 @@ const len = (arr || str) && item.length;

try {
if (typeof sg === 'string' || sg instanceof Uint8Array) {
if (typeof sg === 'string' || ut.isBytes(sg)) {
// Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length).

@@ -888,0 +888,0 @@ // Since DER can also be 2*nByteLength bytes, we check for it first.

/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
// bls12-381 pairing-friendly Barreto-Lynn-Scott elliptic curve construction allows to:
// - Construct zk-SNARKs at the 128-bit security
// - Use threshold signatures, which allows a user to sign lots of messages with one signature and
// verify them swiftly in a batch, using Boneh-Lynn-Shacham signature scheme.
// bls12-381 is pairing-friendly Barreto-Lynn-Scott elliptic curve construction allowing to:
// - Construct zk-SNARKs at the 120-bit security
// - Efficiently verify N aggregate signatures with 1 pairing and N ec additions:
// the Boneh-Lynn-Shacham signature scheme is orders of magnitude more efficient than Schnorr
//
// The library uses G1 for public keys and G2 for signatures. Support for G1 signatures is planned.
// Compatible with Algorand, Chia, Dfinity, Ethereum, FIL, Zcash. Matches specs
// [pairing-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11),
// [bls-sigs-04](https:/cfrg-hash-to/tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04),
// [hash-to-curve-12](https://tools.ietf.org/html/draft-irtf--curve-12).
//
// ### Summary

@@ -27,4 +21,13 @@ // 1. BLS Relies on Bilinear Pairing (expensive)

// - `e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))` - signature aggregation
// Filecoin uses little endian byte arrays for private keys -
// so ensure to reverse byte order if you'll use it with FIL.
//
// ### Compatibility and notes
// 1. It is compatible with Algorand, Chia, Dfinity, Ethereum, Filecoin, ZEC
// Filecoin uses little endian byte arrays for private keys - make sure to reverse byte order.
// 2. Some projects use G2 for public keys and G1 for signatures. It's called "short signature"
// 3. Curve security level is about 120 bits as per Barbulescu-Duquesne 2017
// https://hal.science/hal-01534101/file/main.pdf
// 4. Compatible with specs:
// [cfrg-pairing-friendly-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11),
// [cfrg-bls-signature-05](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05),
// [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380).
import { sha256 } from '@noble/hashes/sha256';

@@ -34,3 +37,3 @@ import { randomBytes } from '@noble/hashes/utils';

import * as mod from './abstract/modular.js';
import { concatBytes as concatB, ensureBytes, numberToBytesBE, bytesToNumberBE, bitLen, bitSet, bitGet, bitMask, bytesToHex, } from './abstract/utils.js';
import { concatBytes as concatB, ensureBytes, numberToBytesBE, bytesToNumberBE, bitLen, bitGet, bitMask, bytesToHex, } from './abstract/utils.js';
// Types

@@ -262,4 +265,4 @@ import { mapToCurveSimpleSWU, } from './abstract/weierstrass.js';

return {
c0: Fp2.add(Fp2.mulByNonresidue(t3), t0),
c1: Fp2.add(Fp2.mulByNonresidue(t4), t1),
c0: Fp2.add(Fp2.mulByNonresidue(t3), t0), // T3 * (u + 1) + T0
c1: Fp2.add(Fp2.mulByNonresidue(t4), t1), // T4 * (u + 1) + T1
// T1 + (c0 - c1 + c2)² + T3 - T0 - T4

@@ -270,3 +273,3 @@ c2: Fp2.sub(Fp2.sub(Fp2.add(Fp2.add(t1, Fp2.sqr(Fp2.add(Fp2.sub(c0, c1), c2))), t3), t0), t4),

const Fp6 = {
ORDER: Fp2.ORDER,
ORDER: Fp2.ORDER, // TODO: unused, but need to verify
BITS: 3 * Fp2.BITS,

@@ -431,3 +434,3 @@ BYTES: 3 * Fp2.BYTES,

return {
c0: Fp6.add(t1, Fp6.mulByNonresidue(t2)),
c0: Fp6.add(t1, Fp6.mulByNonresidue(t2)), // T1 + T2 * v
// (c0 + c1) * (r0 + r1) - (T1 + T2)

@@ -449,3 +452,3 @@ c1: Fp6.sub(Fp6.mul(Fp6.add(c0, c1), Fp6.add(r0, r1)), Fp6.add(t1, t2)),

return {
first: Fp2.add(Fp2.mulByNonresidue(b2), a2),
first: Fp2.add(Fp2.mulByNonresidue(b2), a2), // b² * Nonresidue + a²
second: Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b²

@@ -455,3 +458,3 @@ };

const Fp12 = {
ORDER: Fp2.ORDER,
ORDER: Fp2.ORDER, // TODO: unused, but need to verify
BITS: 2 * Fp2.BITS,

@@ -531,3 +534,3 @@ BYTES: 2 * Fp2.BYTES,

return {
c0: Fp6.add(Fp6.mulByNonresidue(t1), t0),
c0: Fp6.add(Fp6.mulByNonresidue(t1), t0), // T1 * v + T0
// (c1 + c0) * [o0, o1+o4] - T0 - T1

@@ -555,9 +558,9 @@ c1: Fp6.sub(Fp6.sub(Fp6.multiplyBy01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0), t1),

c0: Fp6.create({
c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3),
c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5),
c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3
c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5
c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7),
}),
}), // 2 * (T7 - c0c2) + T7
c1: Fp6.create({
c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9),
c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4),
c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9
c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4
c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6),

@@ -788,4 +791,4 @@ }),

const G2_SWU = mapToCurveSimpleSWU(Fp2, {
A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(BigInt(240)) }),
B: Fp2.create({ c0: Fp.create(BigInt(1012)), c1: Fp.create(BigInt(1012)) }),
A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(BigInt(240)) }), // A' = 240 * I
B: Fp2.create({ c0: Fp.create(BigInt(1012)), c1: Fp.create(BigInt(1012)) }), // B' = 1012 * (1 + I)
Z: Fp2.create({ c0: Fp.create(BigInt(-2)), c1: Fp.create(BigInt(-1)) }), // Z: -(2 + I)

@@ -863,7 +866,35 @@ });

// Point on G1 curve: (x, y)
const C_BIT_POS = Fp.BITS; // C_bit, compression bit for serialization flag
const I_BIT_POS = Fp.BITS + 1; // I_bit, point-at-infinity bit for serialization flag
const S_BIT_POS = Fp.BITS + 2; // S_bit, sign bit for serialization flag
// Compressed point of infinity
const COMPRESSED_ZERO = Fp.toBytes(bitSet(bitSet(_0n, I_BIT_POS, true), S_BIT_POS, true)); // set compressed & point-at-infinity bits
const COMPRESSED_ZERO = setMask(Fp.toBytes(_0n), { infinity: true, compressed: true }); // set compressed & point-at-infinity bits
function parseMask(bytes) {
// Copy, so we can remove mask data. It will be removed also later, when Fp.create will call modulo.
bytes = bytes.slice();
const mask = bytes[0] & 224;
const compressed = !!((mask >> 7) & 1); // compression bit (0b1000_0000)
const infinity = !!((mask >> 6) & 1); // point at infinity bit (0b0100_0000)
const sort = !!((mask >> 5) & 1); // sort bit (0b0010_0000)
bytes[0] &= 31; // clear mask (zero first 3 bits)
return { compressed, infinity, sort, value: bytes };
}
function setMask(bytes, mask) {
if (bytes[0] & 224)
throw new Error('setMask: non-empty mask');
if (mask.compressed)
bytes[0] |= 128;
if (mask.infinity)
bytes[0] |= 64;
if (mask.sort)
bytes[0] |= 32;
return bytes;
}
function signatureG1ToRawBytes(point) {
point.assertValidity();
const isZero = point.equals(bls12_381.G1.ProjectivePoint.ZERO);
const { x, y } = point.toAffine();
if (isZero)
return COMPRESSED_ZERO.slice();
const P = Fp.ORDER;
const sort = Boolean((y * _2n) / P);
return setMask(numberToBytesBE(x, Fp.BYTES), { compressed: true, sort });
}
function signatureG2ToRawBytes(point) {

@@ -879,6 +910,5 @@ // NOTE: by some reasons it was missed in bls12-381, looks like bug

const tmp = y1 > _0n ? y1 * _2n : y0 * _2n;
const aflag1 = Boolean((tmp / Fp.ORDER) & _1n);
const z1 = bitSet(bitSet(x1, 381, aflag1), S_BIT_POS, true);
const sort = Boolean((tmp / Fp.ORDER) & _1n);
const z2 = x0;
return concatB(numberToBytesBE(z1, len), numberToBytesBE(z2, len));
return concatB(setMask(numberToBytesBE(x1, len), { sort, compressed: true }), numberToBytesBE(z2, len));
}

@@ -917,3 +947,3 @@ // To verify curve parameters, see pairing-friendly-curves spec:

b: _4n,
htfDefaults: { ...htfDefaults, m: 1 },
htfDefaults: { ...htfDefaults, m: 1, DST: 'BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_' },
wrapPrivateKey: true,

@@ -956,12 +986,14 @@ allowInfinityPoint: true,

fromBytes: (bytes) => {
bytes = bytes.slice();
if (bytes.length === 48) {
const { compressed, infinity, sort, value } = parseMask(bytes);
if (value.length === 48 && compressed) {
// TODO: Fp.bytes
const P = Fp.ORDER;
const compressedValue = bytesToNumberBE(bytes);
const bflag = bitGet(compressedValue, I_BIT_POS);
const compressedValue = bytesToNumberBE(value);
// Zero
if (bflag === _1n)
const x = Fp.create(compressedValue & Fp.MASK);
if (infinity) {
if (x !== _0n)
throw new Error('G1: non-empty compressed point at infinity');
return { x: _0n, y: _0n };
const x = Fp.create(compressedValue & Fp.MASK);
}
const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)); // y² = x³ + b

@@ -971,13 +1003,15 @@ let y = Fp.sqrt(right);

throw new Error('Invalid compressed G1 point');
const aflag = bitGet(compressedValue, C_BIT_POS);
if ((y * _2n) / P !== aflag)
if ((y * _2n) / P !== BigInt(sort))
y = Fp.neg(y);
return { x: Fp.create(x), y: Fp.create(y) };
}
else if (bytes.length === 96) {
else if (value.length === 96 && !compressed) {
// Check if the infinity flag is set
if ((bytes[0] & (1 << 6)) !== 0)
const x = bytesToNumberBE(value.subarray(0, Fp.BYTES));
const y = bytesToNumberBE(value.subarray(Fp.BYTES));
if (infinity) {
if (x !== _0n || y !== _0n)
throw new Error('G1: non-empty point at infinity');
return bls12_381.G1.ProjectivePoint.ZERO.toAffine();
const x = bytesToNumberBE(bytes.subarray(0, Fp.BYTES));
const y = bytesToNumberBE(bytes.subarray(Fp.BYTES));
}
return { x: Fp.create(x), y: Fp.create(y) };

@@ -996,6 +1030,4 @@ }

const P = Fp.ORDER;
let num;
num = bitSet(x, C_BIT_POS, Boolean((y * _2n) / P)); // set aflag
num = bitSet(num, S_BIT_POS, true);
return numberToBytesBE(num, Fp.BYTES);
const sort = Boolean((y * _2n) / P);
return setMask(numberToBytesBE(x, Fp.BYTES), { compressed: true, sort });
}

@@ -1013,2 +1045,29 @@ else {

},
ShortSignature: {
fromHex(hex) {
const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex, 48));
const P = Fp.ORDER;
const compressedValue = bytesToNumberBE(value);
// Zero
if (infinity)
return bls12_381.G1.ProjectivePoint.ZERO;
const x = Fp.create(compressedValue & Fp.MASK);
const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)); // y² = x³ + b
let y = Fp.sqrt(right);
if (!y)
throw new Error('Invalid compressed G1 point');
const aflag = BigInt(sort);
if ((y * _2n) / P !== aflag)
y = Fp.neg(y);
const point = bls12_381.G1.ProjectivePoint.fromAffine({ x, y });
point.assertValidity();
return point;
},
toRawBytes(point) {
return signatureG1ToRawBytes(point);
},
toHex(point) {
return bytesToHex(signatureG1ToRawBytes(point));
},
},
},

@@ -1073,19 +1132,17 @@ // G2 is the order-q subgroup of E2(Fp²) : y² = x³+4(1+√−1),

fromBytes: (bytes) => {
bytes = bytes.slice();
const m_byte = bytes[0] & 0xe0;
if (m_byte === 0x20 || m_byte === 0x60 || m_byte === 0xe0) {
throw new Error('Invalid encoding flag: ' + m_byte);
const { compressed, infinity, sort, value } = parseMask(bytes);
if ((!compressed && !infinity && sort) || // 00100000
(!compressed && infinity && sort) || // 01100000
(sort && infinity && compressed) // 11100000
) {
throw new Error('Invalid encoding flag: ' + (bytes[0] & 224));
}
const bitC = m_byte & 0x80; // compression bit
const bitI = m_byte & 0x40; // point at infinity bit
const bitS = m_byte & 0x20; // sign bit
const L = Fp.BYTES;
const slc = (b, from, to) => bytesToNumberBE(b.slice(from, to));
if (bytes.length === 96 && bitC) {
if (value.length === 96 && compressed) {
const b = bls12_381.params.G2b;
const P = Fp.ORDER;
bytes[0] = bytes[0] & 0x1f; // clear flags
if (bitI) {
if (infinity) {
// check that all bytes are 0
if (bytes.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) {
if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) {
throw new Error('Invalid compressed G2 point');

@@ -1095,4 +1152,4 @@ }

}
const x_1 = slc(bytes, 0, L);
const x_0 = slc(bytes, L, 2 * L);
const x_1 = slc(value, 0, L);
const x_0 = slc(value, L, 2 * L);
const x = Fp2.create({ c0: Fp.create(x_0), c1: Fp.create(x_1) });

@@ -1102,14 +1159,16 @@ const right = Fp2.add(Fp2.pow(x, _3n), b); // y² = x³ + 4 * (u+1) = x³ + b

const Y_bit = y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P ? _1n : _0n;
y = bitS > 0 && Y_bit > 0 ? y : Fp2.neg(y);
y = sort && Y_bit > 0 ? y : Fp2.neg(y);
return { x, y };
}
else if (bytes.length === 192 && !bitC) {
// Check if the infinity flag is set
if ((bytes[0] & (1 << 6)) !== 0) {
else if (value.length === 192 && !compressed) {
if (infinity) {
if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) {
throw new Error('Invalid uncompressed G2 point');
}
return { x: Fp2.ZERO, y: Fp2.ZERO };
}
const x1 = slc(bytes, 0, L);
const x0 = slc(bytes, L, 2 * L);
const y1 = slc(bytes, 2 * L, 3 * L);
const y0 = slc(bytes, 3 * L, 4 * L);
const x1 = slc(value, 0, L);
const x0 = slc(value, L, 2 * L);
const y1 = slc(value, 2 * L, 3 * L);
const y0 = slc(value, 3 * L, 4 * L);
return { x: Fp2.fromBigTuple([x0, x1]), y: Fp2.fromBigTuple([y0, y1]) };

@@ -1129,6 +1188,3 @@ }

const flag = Boolean(y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P);
// set compressed & sign bits (looks like different offsets than for G1/Fp?)
let x_1 = bitSet(x.c1, C_BIT_POS, flag);
x_1 = bitSet(x_1, S_BIT_POS, true);
return concatB(numberToBytesBE(x_1, len), numberToBytesBE(x.c0, len));
return concatB(setMask(numberToBytesBE(x.c1, len), { compressed: true, sort: flag }), numberToBytesBE(x.c0, len));
}

@@ -1146,3 +1202,3 @@ else {

fromHex(hex) {
hex = ensureBytes('signatureHex', hex);
const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex));
const P = Fp.ORDER;

@@ -1152,7 +1208,6 @@ const half = hex.length / 2;

throw new Error('Invalid compressed signature length, must be 96 or 192');
const z1 = bytesToNumberBE(hex.slice(0, half));
const z2 = bytesToNumberBE(hex.slice(half));
const z1 = bytesToNumberBE(value.slice(0, half));
const z2 = bytesToNumberBE(value.slice(half));
// Indicates the infinity point
const bflag1 = bitGet(z1, I_BIT_POS);
if (bflag1 === _1n)
if (infinity)
return bls12_381.G2.ProjectivePoint.ZERO;

@@ -1170,3 +1225,3 @@ const x1 = Fp.create(z1 & Fp.MASK);

const { re: y0, im: y1 } = Fp2.reim(y);
const aflag1 = bitGet(z1, 381);
const aflag1 = BigInt(sort);
const isGreater = y1 > _0n && (y1 * _2n) / P !== aflag1;

@@ -1189,3 +1244,3 @@ const isZero = y1 === _0n && (y0 * _2n) / P !== aflag1;

params: {
x: BLS_X,
x: BLS_X, // The BLS parameter x for BLS12-381
r: Fr.ORDER, // order; z⁴ − z² + 1; CURVE.n from other curves

@@ -1192,0 +1247,0 @@ },

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

* Previously known as alt_bn_128, when it had 128-bit security.
* Recent research shown it's weaker, the naming has been adjusted to its prime bit count.
* https://github.com/zcash/zcash/issues/2502
* Barbulescu-Duquesne 2017 shown it's weaker: just about 100 bits,
* so the naming has been adjusted to its prime bit count
* https://hal.science/hal-01534101/file/main.pdf
*/

@@ -13,0 +14,0 @@ export const bn254 = weierstrass({

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

// Param: a
a: BigInt(-1),
a: BigInt(-1), // Fp.create(-1) is proper; our way still works and is faster
// d is equal to -121665/121666 over finite field.

@@ -126,3 +126,3 @@ // Negative number is P - number, and division is invert(number, P)

a: BigInt(486662),
montgomeryBits: 255,
montgomeryBits: 255, // n is 253 bits
nByteLength: 32,

@@ -418,2 +418,8 @@ Gu: BigInt(9),

}
double() {
return new RistPoint(this.ep.double());
}
negate() {
return new RistPoint(this.ep.negate());
}
}

@@ -420,0 +426,0 @@ export const RistrettoPoint = /* @__PURE__ */ (() => {

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

n: BigInt('181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779'),
// RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys
nBitLength: 456,

@@ -108,4 +109,5 @@ // Cofactor

a: BigInt(156326),
// RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys
montgomeryBits: 448,
nByteLength: 57,
nByteLength: 56,
P: ed448P,

@@ -136,2 +138,3 @@ Gu: BigInt(5),

export const edwardsToMontgomery = edwardsToMontgomeryPub; // deprecated
// TODO: add edwardsToMontgomeryPriv, similar to ed25519 version
// Hash To Curve Elligator2 Map

@@ -376,2 +379,8 @@ const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4); // 1. c1 = (q - 3) / 4 # Integer arithmetic

}
double() {
return new DcfPoint(this.ep.double());
}
negate() {
return new DcfPoint(this.ep.negate());
}
}

@@ -378,0 +387,0 @@ export const DecafPoint = /* @__PURE__ */ (() => {

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

export const p256 = createCurve({
a: CURVE_A,
a: CURVE_A, // Equation params: a, b
b: CURVE_B,
Fp,
Fp, // Field: 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n
// Curve order, total count of valid points in the field

@@ -19,0 +19,0 @@ n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'),

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

export const p384 = createCurve({
a: CURVE_A,
a: CURVE_A, // Equation params: a, b
b: CURVE_B,
Fp,
Fp, // Field: 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n
// Curve order, total count of valid points in the field.

@@ -23,0 +23,0 @@ n: BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973'),

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

export const p521 = createCurve({
a: CURVE.a,
a: CURVE.a, // Equation params: a, b
b: CURVE.b,
Fp,
Fp, // Field: 2n**521n - 1n
// Curve order, total count of valid points in the field
n: CURVE.n,
Gx: CURVE.Gx,
Gx: CURVE.Gx, // Base point (x, y) aka generator point
Gy: CURVE.Gy,

@@ -33,0 +33,0 @@ h: CURVE.h,

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

export const secp256k1 = createCurve({
a: BigInt(0),
b: BigInt(7),
Fp,
n: secp256k1N,
a: BigInt(0), // equation params: a, b
b: BigInt(7), // Seem to be rigid: bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975
Fp, // Field's prime: 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n
n: secp256k1N, // Curve order, total count of valid points in the field
// Base point (x, y) aka generator point
Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'),
Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'),
h: BigInt(1),
lowS: true,
h: BigInt(1), // Cofactor
lowS: true, // Allow only low-S signatures by default in sign() and verify()
/**

@@ -55,0 +55,0 @@ * secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism.

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

exports.p256 = (0, _shortw_utils_js_1.createCurve)({
a: CURVE_A,
a: CURVE_A, // Equation params: a, b
b: CURVE_B,
Fp,
Fp, // Field: 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n
// Curve order, total count of valid points in the field

@@ -22,0 +22,0 @@ n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'),

@@ -21,5 +21,5 @@ "use strict";

exports.p384 = (0, _shortw_utils_js_1.createCurve)({
a: CURVE_A,
a: CURVE_A, // Equation params: a, b
b: CURVE_B,
Fp,
Fp, // Field: 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n
// Curve order, total count of valid points in the field.

@@ -26,0 +26,0 @@ n: BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973'),

@@ -28,8 +28,8 @@ "use strict";

exports.p521 = (0, _shortw_utils_js_1.createCurve)({
a: CURVE.a,
a: CURVE.a, // Equation params: a, b
b: CURVE.b,
Fp,
Fp, // Field: 2n**521n - 1n
// Curve order, total count of valid points in the field
n: CURVE.n,
Gx: CURVE.Gx,
Gx: CURVE.Gx, // Base point (x, y) aka generator point
Gy: CURVE.Gy,

@@ -36,0 +36,0 @@ h: CURVE.h,

{
"name": "@noble/curves",
"version": "1.2.0",
"version": "1.3.0",
"description": "Audited & minimal JS implementation of elliptic curve cryptography",

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

"build": "tsc && tsc -p tsconfig.esm.json",
"build:release": "rollup -c rollup.config.js",
"build:release": "cd build; npm install && npm run build",
"build:clean": "rm *.{js,d.ts,d.ts.map,js.map} esm/*.{js,d.ts,d.ts.map,js.map} 2> /dev/null",

@@ -32,3 +32,3 @@ "lint": "prettier --check 'src/**/*.{js,ts}' 'test/*.js'",

"dependencies": {
"@noble/hashes": "1.3.2"
"@noble/hashes": "1.3.3"
},

@@ -39,4 +39,4 @@ "devDependencies": {

"micro-should": "0.4.0",
"prettier": "2.8.4",
"typescript": "5.0.2"
"prettier": "3.1.1",
"typescript": "5.3.2"
},

@@ -43,0 +43,0 @@ "sideEffects": false,

@@ -5,3 +5,3 @@ # noble-curves

- 🔒 [**Audited**](#security) by an independent security firm
- 🔒 [**Audited**](#security) by independent security firms
- 🔻 Tree-shaking-friendly: use only what's necessary, other code won't be included

@@ -12,3 +12,3 @@ - 🏎 Ultra-fast, hand-optimized for caveats of JS engines

- ✍️ ECDSA, EdDSA, Schnorr, BLS signature schemes, ECDH key agreement
- 🔖 SUF-CMA and SBS (non-repudiation) for ed25519, ed448 and others
- 🔖 SUF-CMA, SBS (non-repudiation), ZIP215 (consensus friendliness) features for ed25519
- #️⃣ hash-to-curve for encoding or hashing an arbitrary string to an elliptic curve point

@@ -21,12 +21,11 @@ - 🧜‍♂️ Poseidon ZK-friendly hash

- No dependencies, protection against supply chain attacks
- Auditable TypeScript / JS code
- Supported on all major platforms
- Releases are signed with PGP keys and built transparently with NPM provenance
- Check out [homepage](https://paulmillr.com/noble/) & all libraries:
- Zero or minimal dependencies
- Highly readable TypeScript / JS code
- PGP-signed releases and transparent NPM builds
- All libraries:
[ciphers](https://github.com/paulmillr/noble-ciphers),
[curves](https://github.com/paulmillr/noble-curves),
[hashes](https://github.com/paulmillr/noble-hashes),
4kb [secp256k1](https://github.com/paulmillr/noble-secp256k1) /
[ed25519](https://github.com/paulmillr/noble-ed25519)
[hashes](https://github.com/paulmillr/noble-hashes)
- [Check out homepage](https://paulmillr.com/noble/)
for reading resources, documentation and apps built with noble

@@ -39,9 +38,15 @@ ## Usage

For [Deno](https://deno.land), ensure to use [npm specifier](https://deno.land/manual@v1.28.0/node/npm_specifiers).
For React Native, you may need a [polyfill for crypto.getRandomValues](https://github.com/LinusU/react-native-get-random-values).
If you don't like NPM, a standalone [noble-curves.js](https://github.com/paulmillr/noble-curves/releases) is also available.
For React Native, you may need a [polyfill for getRandomValues](https://github.com/LinusU/react-native-get-random-values).
A standalone file [noble-curves.js](https://github.com/paulmillr/noble-curves/releases) is also available.
```js
// import * from '@noble/curves'; // Error: use sub-imports, to ensure small app size
import { secp256k1 } from '@noble/curves/secp256k1'; // ESM and Common.js
// import { secp256k1 } from 'npm:@noble/curves@1.2.0/secp256k1'; // Deno
```
- [Implementations](#implementations)
- [ECDSA signature scheme](#ecdsa-signature-scheme)
- [ECDSA public key recovery & extra entropy](#ecdsa-public-key-recovery--extra-entropy)
- [ECDH (Elliptic Curve Diffie-Hellman)](#ecdh-elliptic-curve-diffie-hellman)
- [ECDH: Elliptic Curve Diffie-Hellman](#ecdh-elliptic-curve-diffie-hellman)
- [Schnorr signatures over secp256k1, BIP340](#schnorr-signatures-over-secp256k1-bip340)

@@ -54,24 +59,21 @@ - [ed25519, X25519, ristretto255](#ed25519-x25519-ristretto255)

- [Abstract API](#abstract-api)
- [abstract/weierstrass: Short Weierstrass curve](#abstractweierstrass-short-weierstrass-curve)
- [abstract/edwards: Twisted Edwards curve](#abstractedwards-twisted-edwards-curve)
- [abstract/montgomery: Montgomery curve](#abstractmontgomery-montgomery-curve)
- [abstract/bls: Barreto-Lynn-Scott curves](#abstractbls-barreto-lynn-scott-curves)
- [abstract/hash-to-curve: Hashing strings to curve points](#abstracthash-to-curve-hashing-strings-to-curve-points)
- [abstract/poseidon: Poseidon hash](#abstractposeidon-poseidon-hash)
- [abstract/modular: Modular arithmetics utilities](#abstractmodular-modular-arithmetics-utilities)
- [weierstrass: Short Weierstrass curve](#weierstrass-short-weierstrass-curve)
- [edwards: Twisted Edwards curve](#edwards-twisted-edwards-curve)
- [montgomery: Montgomery curve](#montgomery-montgomery-curve)
- [bls: Barreto-Lynn-Scott curves](#bls-barreto-lynn-scott-curves)
- [hash-to-curve: Hashing strings to curve points](#hash-to-curve-hashing-strings-to-curve-points)
- [poseidon: Poseidon hash](#poseidon-poseidon-hash)
- [modular: Modular arithmetics utilities](#modular-modular-arithmetics-utilities)
- [Creating private keys from hashes](#creating-private-keys-from-hashes)
- [abstract/utils: Useful utilities](#abstractutils-useful-utilities)
- [utils: Useful utilities](#utils-useful-utilities)
- [Security](#security)
- [Speed](#speed)
- [Upgrading](#upgrading)
- [Contributing & testing](#contributing--testing)
- [Upgrading](#upgrading)
- [Resources](#resources)
- [Demos](#demos)
- [Projects using curves](#projects-using-curves)
- [License](#license)
### Implementations
Implementations are utilizing [noble-hashes](https://github.com/paulmillr/noble-hashes).
[Abstract API](#abstract-api) doesn't depend on them: you can use a different hashing library.
Implementations use [noble-hashes](https://github.com/paulmillr/noble-hashes).
If you want to use a different hashing library, [abstract API](#abstract-api) doesn't depend on them.

@@ -83,5 +85,3 @@ #### ECDSA signature scheme

```ts
// import * from '@noble/curves'; // Error: use sub-imports, to ensure small app size
import { secp256k1 } from '@noble/curves/secp256k1'; // ESM and Common.js
// import { secp256k1 } from 'npm:@noble/curves@1.2.0/secp256k1'; // Deno
import { secp256k1 } from '@noble/curves/secp256k1';
const priv = secp256k1.utils.randomPrivateKey();

@@ -101,2 +101,4 @@ const pub = secp256k1.getPublicKey(priv);

```ts
// let sig = secp256k1.Signature.fromCompact(sigHex); // or .fromDER(sigDERHex)
// sig = sig.addRecoveryBit(bit); // bit is not serialized into compact / der format
sig.recoverPublicKey(msg).toRawBytes(); // === pub; // public key recovery

@@ -108,3 +110,3 @@

#### ECDH (Elliptic Curve Diffie-Hellman)
#### ECDH: Elliptic Curve Diffie-Hellman

@@ -285,3 +287,3 @@ ```ts

### abstract/weierstrass: Short Weierstrass curve
### weierstrass: Short Weierstrass curve

@@ -328,2 +330,6 @@ ```ts

};
// example
function sha256(message: Uint8Array) { return _internal_lowlvl(message) }
sha256.outputLen = 32; // 32 bytes of output for sha2-256
```

@@ -454,3 +460,3 @@

### abstract/edwards: Twisted Edwards curve
### edwards: Twisted Edwards curve

@@ -545,3 +551,3 @@ ```ts

### abstract/montgomery: Montgomery curve
### montgomery: Montgomery curve

@@ -573,3 +579,3 @@ ```typescript

### abstract/bls: Barreto-Lynn-Scott curves
### bls: Barreto-Lynn-Scott curves

@@ -583,2 +589,4 @@ The module abstracts BLS (Barreto-Lynn-Scott) pairing-friendly elliptic curve construction.

The module doesn't expose `CURVE` property: use `G1.CURVE`, `G2.CURVE` instead.
Only BLS12-381 is implemented currently.
Defining BLS12-377 and BLS24 should be straightforward.

@@ -596,5 +604,10 @@ Main methods and properties are:

Right now we only implement BLS12-381 (compatible with ETH and others),
but in theory defining BLS12-377, BLS24 should be straightforward. An example:
The default BLS uses short public keys (with public keys in G1 and signatures in G2).
Short signatures (public keys in G2 and signatures in G1) is also supported, using:
- `getPublicKeyForShortSignatures(privateKey)`
- `signShortSignature(message, privateKey)`
- `verifyShortSignature(signature, message, publicKey)`
- `aggregateShortSignatures(signatures)`
```ts

@@ -630,9 +643,10 @@ import { bls12_381 as bls } from '@noble/curves/bls12-381';

// Pairings, with and without final exponentiation
// bls.pairing(PointG1, PointG2);
// bls.pairing(PointG1, PointG2, false);
// bls.fields.Fp12.finalExponentiate(bls.fields.Fp12.mul(eGS, ePHm));
bls.pairing(PointG1, PointG2);
bls.pairing(PointG1, PointG2, false);
bls.fields.Fp12.finalExponentiate(bls.fields.Fp12.mul(PointG1, PointG2));
// Others
// bls.G1.ProjectivePoint.BASE, bls.G2.ProjectivePoint.BASE
// bls.fields.Fp, bls.fields.Fp2, bls.fields.Fp12, bls.fields.Fr
bls.G1.ProjectivePoint.BASE, bls.G2.ProjectivePoint.BASE
bls.fields.Fp, bls.fields.Fp2, bls.fields.Fp12, bls.fields.Fr
bls.params.x, bls.params.r, bls.params.G1b, bls.params.G2b

@@ -642,54 +656,4 @@ // hash-to-curve examples can be seen below

Full types:
### hash-to-curve: Hashing strings to curve points
```ts
getPublicKey: (privateKey: PrivKey) => Uint8Array;
sign: {
(message: Hex, privateKey: PrivKey): Uint8Array;
(message: ProjPointType<Fp2>, privateKey: PrivKey): ProjPointType<Fp2>;
};
verify: (
signature: Hex | ProjPointType<Fp2>,
message: Hex | ProjPointType<Fp2>,
publicKey: Hex | ProjPointType<Fp>
) => boolean;
verifyBatch: (
signature: Hex | ProjPointType<Fp2>,
messages: (Hex | ProjPointType<Fp2>)[],
publicKeys: (Hex | ProjPointType<Fp>)[]
) => boolean;
aggregatePublicKeys: {
(publicKeys: Hex[]): Uint8Array;
(publicKeys: ProjPointType<Fp>[]): ProjPointType<Fp>;
};
aggregateSignatures: {
(signatures: Hex[]): Uint8Array;
(signatures: ProjPointType<Fp2>[]): ProjPointType<Fp2>;
};
millerLoop: (ell: [Fp2, Fp2, Fp2][], g1: [Fp, Fp]) => Fp12;
pairing: (P: ProjPointType<Fp>, Q: ProjPointType<Fp2>, withFinalExponent?: boolean) => Fp12;
G1: CurvePointsRes<Fp> & ReturnType<typeof htf.createHasher<Fp>>;
G2: CurvePointsRes<Fp2> & ReturnType<typeof htf.createHasher<Fp2>>;
Signature: SignatureCoder<Fp2>;
params: {
x: bigint;
r: bigint;
G1b: bigint;
G2b: Fp2;
};
fields: {
Fp: IField<Fp>;
Fp2: IField<Fp2>;
Fp6: IField<Fp6>;
Fp12: IField<Fp12>;
Fr: IField<bigint>;
};
utils: {
randomPrivateKey: () => Uint8Array;
calcPairingPrecomputes: (p: AffinePoint<Fp2>) => [Fp2, Fp2, Fp2][];
};
```
### abstract/hash-to-curve: Hashing strings to curve points
The module allows to hash arbitrary strings to elliptic curve points. Implements [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380).

@@ -751,3 +715,3 @@

### abstract/poseidon: Poseidon hash
### poseidon: Poseidon hash

@@ -776,3 +740,3 @@ Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash.

### abstract/modular: Modular arithmetics utilities
### modular: Modular arithmetics utilities

@@ -821,2 +785,3 @@ ```ts

import { hkdf } from '@noble/hashes/hkdf';
import * as mod from '@noble/curves/abstract/modular';
const someKey = new Uint8Array(32).fill(2); // Needs to actually be random, not .fill(2)

@@ -827,3 +792,3 @@ const derived = hkdf(sha256, someKey, undefined, 'application', 48); // 48 bytes for 32-byte priv

### abstract/utils: Useful utilities
### utils: Useful utilities

@@ -850,39 +815,57 @@ ```ts

1. The library has been independently audited:
The library has been independently audited:
- in Feb 2023 by [Trail of Bits](https://www.trailofbits.com):
[PDF](https://github.com/trailofbits/publications/blob/master/reviews/2023-01-ryanshea-noblecurveslibrary-securityreview.pdf).
The audit has been funded by [Ryan Shea](https://www.shea.io).
Audit scope was abstract modules `curve`, `hash-to-curve`, `modular`, `poseidon`, `utils`, `weierstrass`,
and top-level modules `_shortw_utils` and `secp256k1`.
See [changes since v0.7.3 audit](https://github.com/paulmillr/noble-curves/compare/0.7.3..main).
- at version 1.2.0, in Sep 2023, by [Kudelski Security](https://kudelskisecurity.com)
- PDFs: [offline](./audit/2023-09-kudelski-audit-starknet.pdf)
- [Changes since audit](https://github.com/paulmillr/noble-curves/compare/1.2.0..main)
- Scope: [scure-starknet](https://github.com/paulmillr/scure-starknet) and its related
abstract modules of noble-curves: `curve`, `modular`, `poseidon`, `weierstrass`
- The audit has been funded by [Starkware](https://starkware.co)
- at version 0.7.3, in Feb 2023, by [Trail of Bits](https://www.trailofbits.com)
- PDFs: [online](https://github.com/trailofbits/publications/blob/master/reviews/2023-01-ryanshea-noblecurveslibrary-securityreview.pdf),
[offline](./audit/2023-01-trailofbits-audit-curves.pdf)
- [Changes since audit](https://github.com/paulmillr/noble-curves/compare/0.7.3..main)
- Scope: abstract modules `curve`, `hash-to-curve`, `modular`, `poseidon`, `utils`, `weierstrass` and
top-level modules `_shortw_utils` and `secp256k1`
- The audit has been funded by [Ryan Shea](https://www.shea.io)
2. The library has been fuzzed by [Guido Vranken's cryptofuzz](https://github.com/guidovranken/cryptofuzz).
You can run the fuzzer by yourself to check it.
3. [Timing attack](https://en.wikipedia.org/wiki/Timing_attack) considerations:
_JIT-compiler_ and _Garbage Collector_ make "constant time" extremely hard to
achieve in a scripting language. Which means _any other JS library can't have
constant-timeness_. 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're targetting algorithmic constant time.
It is tested against property-based, cross-library and Wycheproof vectors,
and has fuzzing by [Guido Vranken's cryptofuzz](https://github.com/guidovranken/cryptofuzz).
We 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.
As for devDependencies used by the library:
If you see anything unusual: investigate and report.
- `@scure` base, bip32, bip39 (used in tests), micro-bmark (benchmark), micro-should (testing)
are developed by us and follow the same practices such as: minimal library size, auditability,
signed releases
- prettier (linter), fast-check (property-based testing), typescript versions
are locked and rarely updated. Every update is checked with `npm-diff`.
The packages are big, which makes it hard to audit their source code thoroughly and fully.
- They are only used if you clone the git repo and want to add some feature to it. End-users won't use them.
### Constant-timeness
As for key generation, we're deferring to built-in
_JIT-compiler_ and _Garbage Collector_ make "constant time" extremely hard to
achieve [timing attack](https://en.wikipedia.org/wiki/Timing_attack) resistance
in a scripting language. Which means _any other JS library can't have
constant-timeness_. 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're targetting algorithmic constant time.
### Supply chain security
* **Commits** are signed with PGP keys, to prevent forgery. Make sure to verify commit signatures.
* **Releases** are transparent and built on GitHub CI. Make sure to verify [provenance](https://docs.npmjs.com/generating-provenance-statements) logs
* **Rare releasing** is followed to ensure less re-audit need for end-users
* **Dependencies** are minimized and locked-down:
- If your app has 500 dependencies, any dep could get hacked and you'll be downloading
malware with every install. We make sure to use as few dependencies as possible
- We prevent automatic dependency updates by locking-down version ranges. Every update is checked with `npm-diff`
- One dependency [noble-hashes](https://github.com/paulmillr/noble-hashes) is used, by the same author, to provide hashing functionality
* **Dev Dependencies** are only used if you want to contribute to the repo. They are disabled for end-users:
- scure-base, scure-bip32, scure-bip39, micro-bmark and micro-should are developed by the same author and follow identical security practices
- prettier (linter), fast-check (property-based testing) and typescript are used for code quality, vector generation and ts compilation. The packages are big, which makes it hard to audit their source code thoroughly and fully
### Randomness
We're deferring to built-in
[crypto.getRandomValues](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues)
which is considered cryptographically secure (CSPRNG).
In the past, browsers had bugs that made it weak: it may happen again.
Implementing a userspace CSPRNG to get resilient to the weakness
is even worse: there is no reliable userspace source of quality entropy.
## Speed

@@ -969,9 +952,2 @@

## Contributing & testing
1. Clone the repository
2. `npm install` to install build dependencies like TypeScript
3. `npm run build` to compile TypeScript code
4. `npm run test` will execute all main tests
## Upgrading

@@ -997,3 +973,3 @@

- `sign`
- is now sync; use `signAsync` for async version
- is now sync
- now returns `Signature` instance with `{ r, s, recovery }` properties

@@ -1007,2 +983,3 @@ - `canonical` option was renamed to `lowS`

- `verify`
- is now sync
- `strict` option was renamed to `lowS`

@@ -1037,58 +1014,15 @@ - `getSharedSecret`

## Resources
## Contributing & testing
- [Learning fast elliptic-curve cryptography](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/)
- EdDSA
- [A Deep dive into Ed25519 Signatures](https://cendyne.dev/posts/2022-03-06-ed25519-signatures.html)
- [Ed25519 Deep Dive Addendum](https://cendyne.dev/posts/2022-09-11-ed25519-deep-dive-addendum.html)
- [It’s 255:19AM. Do you know what your validation criteria are?](https://hdevalence.ca/blog/2020-10-04-its-25519am)
- [Taming the many EdDSAs](https://csrc.nist.gov/csrc/media/Presentations/2023/crclub-2023-03-08/images-media/20230308-crypto-club-slides--taming-the-many-EdDSAs.pdf)
that describes concepts of Strong UnForgeability under Chosen Message Attacks and Strongly Binding Signatures
- [Cofactor Explained: Clearing Elliptic Curves’ dirty little secret](https://loup-vaillant.fr/tutorials/cofactor)
- [Surrounded by Elligators](https://loup-vaillant.fr/articles/implementing-elligator)
- Pairings and BLS
- [BLS signatures for busy people](https://gist.github.com/paulmillr/18b802ad219b1aee34d773d08ec26ca2)
- [BLS12-381 for the rest of us](https://hackmd.io/@benjaminion/bls12-381)
- [Key concepts of pairings](https://medium.com/@alonmuroch_65570/bls-signatures-part-2-key-concepts-of-pairings-27a8a9533d0c)
- Pairing over bls12-381:
[fields](https://research.nccgroup.com/2020/07/06/pairing-over-bls12-381-part-1-fields/),
[curves](https://research.nccgroup.com/2020/07/13/pairing-over-bls12-381-part-2-curves/),
[pairings](https://research.nccgroup.com/2020/08/13/pairing-over-bls12-381-part-3-pairing/)
- [Estimating the bit security of pairing-friendly curves](https://research.nccgroup.com/2022/02/03/estimating-the-bit-security-of-pairing-friendly-curves/)
1. Clone the repository
2. `npm install` to install build dependencies like TypeScript
3. `npm run build` to compile TypeScript code
4. `npm run test` will execute all main tests
### Demos
## Resources
- [Elliptic Curve Calculator](https://paulmillr.com/noble): add / multiply points, sign messages
- [BLS threshold signatures](https://genthresh.com)
Check out [paulmillr.com/noble](https://paulmillr.com/noble/)
for useful resources, articles, documentation and demos
related to the library.
### Projects using curves
- HDkey libraries: [scure-bip32](https://github.com/paulmillr/scure-bip32), [bip32](https://github.com/bitcoinjs/bip32)
- Social networks: [nostr](https://github.com/nbd-wtf/nostr-tools), [bluesky](https://github.com/bluesky-social/atproto)
- Ethereum libraries:
- [ethereum-cryptography](https://github.com/ethereum/js-ethereum-cryptography)
- [micro-eth-signer](https://github.com/paulmillr/micro-eth-signer),
[ethers](https://github.com/ethers-io/ethers.js) (old noble),
[viem.sh](https://viem.sh),
[@ethereumjs](https://github.com/ethereumjs/ethereumjs-monorepo)
- [metamask's eth-sig-util](https://github.com/MetaMask/eth-sig-util)
- [gridplus lattice sdk](https://github.com/GridPlus/lattice-eth2-utils)
- Bitcoin libraries:
- [scure-btc-signer](https://github.com/paulmillr/scure-btc-signer)
- [tapscript](https://github.com/cmdruid/tapscript)
- Solana libraries: [micro-sol-signer](https://github.com/paulmillr/micro-sol-signer), [solana-web3.js](https://github.com/solana-labs/solana-web3.js)
- Other web3 stuff:
- [scure-starknet](https://github.com/paulmillr/scure-starknet)
- [aztec](https://github.com/AztecProtocol/aztec-packages)
- [polkadot.js](https://github.com/polkadot-js/common), [drand-client](https://github.com/drand/drand-client), [moneroj](https://github.com/beritani/moneroj), [tronlib](https://github.com/CoinSpace/tronlib)
- [protonmail](https://github.com/ProtonMail/WebClients) (old noble for now)
- [did-jwt](https://github.com/decentralized-identity/did-jwt), [hpke-js](https://github.com/dajiaji/hpke-js),
[js-libp2p-noise](https://github.com/ChainSafe/js-libp2p-noise)
- [ed25519-keygen](https://github.com/paulmillr/ed25519-keygen) SSH, PGP, TOR key generation
- [secp256k1 compatibility layer](https://github.com/ethereum/js-ethereum-cryptography/blob/2.0.0/src/secp256k1-compat.ts)
for users who want to switch from secp256k1-node or tiny-secp256k1. Allows to see which methods map to corresponding noble code.
- [BLS BBS signatures](https://github.com/Wind4Greg/BBS-Draft-Checks) following [draft-irtf-cfrg-bbs-signatures-latest](https://identity.foundation/bbs-signature/draft-irtf-cfrg-bbs-signatures.html)
- [KZG trusted setup ceremony](https://github.com/dsrvlabs/czg-keremony)
- See [full list of projects on GitHub](https://github.com/paulmillr/noble-curves/network/dependents).
## License

@@ -1095,0 +1029,0 @@

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

exports.secp256k1 = (0, _shortw_utils_js_1.createCurve)({
a: BigInt(0),
b: BigInt(7),
Fp,
n: secp256k1N,
a: BigInt(0), // equation params: a, b
b: BigInt(7), // Seem to be rigid: bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975
Fp, // Field's prime: 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n
n: secp256k1N, // Curve order, total count of valid points in the field
// Base point (x, y) aka generator point
Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'),
Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'),
h: BigInt(1),
lowS: true,
h: BigInt(1), // Cofactor
lowS: true, // Allow only low-S signatures by default in sign() and verify()
/**

@@ -58,0 +58,0 @@ * secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism.

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

import { Hex, PrivKey, CHash, bitLen, bitGet, ensureBytes } from './utils.js';
import * as htf from './hash-to-curve.js';
// prettier-ignore
import {
MapToCurve, Opts as HTFOpts, H2CPointConstructor, htfBasicOpts,
createHasher
} from './hash-to-curve.js';
import {
CurvePointsType,

@@ -31,2 +35,8 @@ ProjPointType as ProjPointType,

export type ShortSignatureCoder<Fp> = {
fromHex(hex: Hex): ProjPointType<Fp>;
toRawBytes(point: ProjPointType<Fp>): Uint8Array;
toHex(point: ProjPointType<Fp>): string;
};
export type SignatureCoder<Fp2> = {

@@ -40,9 +50,10 @@ fromHex(hex: Hex): ProjPointType<Fp2>;

G1: Omit<CurvePointsType<Fp>, 'n'> & {
mapToCurve: htf.MapToCurve<Fp>;
htfDefaults: htf.Opts;
ShortSignature: SignatureCoder<Fp>;
mapToCurve: MapToCurve<Fp>;
htfDefaults: HTFOpts;
};
G2: Omit<CurvePointsType<Fp2>, 'n'> & {
Signature: SignatureCoder<Fp2>;
mapToCurve: htf.MapToCurve<Fp2>;
htfDefaults: htf.Opts;
mapToCurve: MapToCurve<Fp2>;
htfDefaults: HTFOpts;
};

@@ -69,3 +80,3 @@ fields: {

};
htfDefaults: htf.Opts;
htfDefaults: HTFOpts;
hash: CHash; // Because we need outputLen for DRBG

@@ -77,2 +88,3 @@ randomBytes: (bytesLength?: number) => Uint8Array;

getPublicKey: (privateKey: PrivKey) => Uint8Array;
getPublicKeyForShortSignatures: (privateKey: PrivKey) => Uint8Array;
sign: {

@@ -82,11 +94,23 @@ (message: Hex, privateKey: PrivKey): Uint8Array;

};
signShortSignature: {
(message: Hex, privateKey: PrivKey): Uint8Array;
(message: ProjPointType<Fp>, privateKey: PrivKey): ProjPointType<Fp>;
};
verify: (
signature: Hex | ProjPointType<Fp2>,
message: Hex | ProjPointType<Fp2>,
publicKey: Hex | ProjPointType<Fp>
publicKey: Hex | ProjPointType<Fp>,
htfOpts?: htfBasicOpts
) => boolean;
verifyShortSignature: (
signature: Hex | ProjPointType<Fp>,
message: Hex | ProjPointType<Fp>,
publicKey: Hex | ProjPointType<Fp2>,
htfOpts?: htfBasicOpts
) => boolean;
verifyBatch: (
signature: Hex | ProjPointType<Fp2>,
messages: (Hex | ProjPointType<Fp2>)[],
publicKeys: (Hex | ProjPointType<Fp>)[]
publicKeys: (Hex | ProjPointType<Fp>)[],
htfOpts?: htfBasicOpts
) => boolean;

@@ -101,7 +125,12 @@ aggregatePublicKeys: {

};
aggregateShortSignatures: {
(signatures: Hex[]): Uint8Array;
(signatures: ProjPointType<Fp>[]): ProjPointType<Fp>;
};
millerLoop: (ell: [Fp2, Fp2, Fp2][], g1: [Fp, Fp]) => Fp12;
pairing: (P: ProjPointType<Fp>, Q: ProjPointType<Fp2>, withFinalExponent?: boolean) => Fp12;
G1: CurvePointsRes<Fp> & ReturnType<typeof htf.createHasher<Fp>>;
G2: CurvePointsRes<Fp2> & ReturnType<typeof htf.createHasher<Fp2>>;
G1: CurvePointsRes<Fp> & ReturnType<typeof createHasher<Fp>>;
G2: CurvePointsRes<Fp2> & ReturnType<typeof createHasher<Fp2>>;
Signature: SignatureCoder<Fp2>;
ShortSignature: ShortSignatureCoder<Fp>;
params: {

@@ -208,3 +237,3 @@ x: bigint;

G1_,
htf.createHasher(G1_.ProjectivePoint, CURVE.G1.mapToCurve, {
createHasher(G1_.ProjectivePoint, CURVE.G1.mapToCurve, {
...CURVE.htfDefaults,

@@ -235,3 +264,3 @@ ...CURVE.G1.htfDefaults,

G2_,
htf.createHasher(G2_.ProjectivePoint as htf.H2CPointConstructor<Fp2>, CURVE.G2.mapToCurve, {
createHasher(G2_.ProjectivePoint as H2CPointConstructor<Fp2>, CURVE.G2.mapToCurve, {
...CURVE.htfDefaults,

@@ -242,2 +271,3 @@ ...CURVE.G2.htfDefaults,

const { ShortSignature } = CURVE.G1;
const { Signature } = CURVE.G2;

@@ -264,6 +294,11 @@

}
function normP1Hash(point: G1Hex, htfOpts?: htfBasicOpts): G1 {
return point instanceof G1.ProjectivePoint
? point
: (G1.hashToCurve(ensureBytes('point', point), htfOpts) as G1);
}
function normP2(point: G2Hex): G2 {
return point instanceof G2.ProjectivePoint ? point : Signature.fromHex(point);
}
function normP2Hash(point: G2Hex, htfOpts?: htf.htfBasicOpts): G2 {
function normP2Hash(point: G2Hex, htfOpts?: htfBasicOpts): G2 {
return point instanceof G2.ProjectivePoint

@@ -274,3 +309,3 @@ ? point

// Multiplies generator by private key.
// Multiplies generator (G1) by private key.
// P = pk x G

@@ -281,7 +316,13 @@ function getPublicKey(privateKey: PrivKey): Uint8Array {

// Multiplies generator (G2) by private key.
// P = pk x G
function getPublicKeyForShortSignatures(privateKey: PrivKey): Uint8Array {
return G2.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true);
}
// Executes `hashToCurve` on the message and then multiplies the result by private key.
// S = pk x H(m)
function sign(message: Hex, privateKey: PrivKey, htfOpts?: htf.htfBasicOpts): Uint8Array;
function sign(message: G2, privateKey: PrivKey, htfOpts?: htf.htfBasicOpts): G2;
function sign(message: G2Hex, privateKey: PrivKey, htfOpts?: htf.htfBasicOpts): Uint8Array | G2 {
function sign(message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array;
function sign(message: G2, privateKey: PrivKey, htfOpts?: htfBasicOpts): G2;
function sign(message: G2Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array | G2 {
const msgPoint = normP2Hash(message, htfOpts);

@@ -294,2 +335,20 @@ msgPoint.assertValidity();

function signShortSignature(
message: Hex,
privateKey: PrivKey,
htfOpts?: htfBasicOpts
): Uint8Array;
function signShortSignature(message: G1, privateKey: PrivKey, htfOpts?: htfBasicOpts): G1;
function signShortSignature(
message: G1Hex,
privateKey: PrivKey,
htfOpts?: htfBasicOpts
): Uint8Array | G1 {
const msgPoint = normP1Hash(message, htfOpts);
msgPoint.assertValidity();
const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey));
if (message instanceof G1.ProjectivePoint) return sigPoint;
return ShortSignature.toRawBytes(sigPoint);
}
// Checks if pairing of public key & hash is equal to pairing of generator & signature.

@@ -301,3 +360,3 @@ // e(P, H(m)) == e(G, S)

publicKey: G1Hex,
htfOpts?: htf.htfBasicOpts
htfOpts?: htfBasicOpts
): boolean {

@@ -316,2 +375,22 @@ const P = normP1(publicKey);

// Checks if pairing of public key & hash is equal to pairing of generator & signature.
// e(S, G) == e(H(m), P)
function verifyShortSignature(
signature: G1Hex,
message: G1Hex,
publicKey: G2Hex,
htfOpts?: htfBasicOpts
): boolean {
const P = normP2(publicKey);
const Hm = normP1Hash(message, htfOpts);
const G = G2.ProjectivePoint.BASE;
const S = normP1(signature);
// Instead of doing 2 exponentiations, we use property of billinear maps
// and do one exp after multiplying 2 points.
const eHmP = pairing(Hm, P, false);
const eSG = pairing(S, G.negate(), false);
const exp = Fp12.finalExponentiate(Fp12.mul(eSG, eHmP));
return Fp12.eql(exp, Fp12.ONE);
}
// Adds a bunch of public key points together.

@@ -347,2 +426,16 @@ // pk1 + pk2 + pk3 = pkA

// Adds a bunch of signature points together.
function aggregateShortSignatures(signatures: Hex[]): Uint8Array;
function aggregateShortSignatures(signatures: G1[]): G1;
function aggregateShortSignatures(signatures: G1Hex[]): Uint8Array | G1 {
if (!signatures.length) throw new Error('Expected non-empty array');
const agg = signatures.map(normP1).reduce((sum, s) => sum.add(s), G1.ProjectivePoint.ZERO);
const aggAffine = agg; //.toAffine();
if (signatures[0] instanceof G1.ProjectivePoint) {
aggAffine.assertValidity();
return aggAffine;
}
return ShortSignature.toRawBytes(aggAffine);
}
// https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407

@@ -354,3 +447,3 @@ // e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))

publicKeys: G1Hex[],
htfOpts?: htf.htfBasicOpts
htfOpts?: htfBasicOpts
): boolean {

@@ -391,7 +484,11 @@ // @ts-ignore

getPublicKey,
getPublicKeyForShortSignatures,
sign,
signShortSignature,
verify,
verifyBatch,
verifyShortSignature,
aggregatePublicKeys,
aggregateSignatures,
aggregateShortSignatures,
millerLoop,

@@ -402,2 +499,3 @@ pairing,

Signature,
ShortSignature,
fields: {

@@ -404,0 +502,0 @@ Fr,

/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
import type { Group, GroupConstructor, AffinePoint } from './curve.js';
import { mod, IField } from './modular.js';
import { bytesToNumberBE, CHash, concatBytes, utf8ToBytes, validateObject } from './utils.js';
import type { CHash } from './utils.js';
import { bytesToNumberBE, isBytes, concatBytes, utf8ToBytes, validateObject } from './utils.js';

@@ -25,3 +26,3 @@ /**

function validateDST(dst: UnicodeOrBytes): Uint8Array {
if (dst instanceof Uint8Array) return dst;
if (isBytes(dst)) return dst;
if (typeof dst === 'string') return utf8ToBytes(dst);

@@ -55,4 +56,4 @@ throw new Error('DST must be Uint8Array or string');

function isBytes(item: unknown): void {
if (!(item instanceof Uint8Array)) throw new Error('Uint8Array expected');
function abytes(item: unknown): void {
if (!isBytes(item)) throw new Error('Uint8Array expected');
}

@@ -71,4 +72,4 @@ function isNum(item: unknown): void {

): Uint8Array {
isBytes(msg);
isBytes(DST);
abytes(msg);
abytes(DST);
isNum(lenInBytes);

@@ -106,4 +107,4 @@ // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3

): Uint8Array {
isBytes(msg);
isBytes(DST);
abytes(msg);
abytes(DST);
isNum(lenInBytes);

@@ -146,3 +147,3 @@ // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3

const { p, k, m, hash, expand, DST: _DST } = options;
isBytes(msg);
abytes(msg);
isNum(count);

@@ -149,0 +150,0 @@ const DST = validateDST(_DST);

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

// MUST mask the most significant bit in the final byte.
// This is very ugly way, but it works because fieldLen-1 is outside of bounds for X448, so this becomes NOOP
// fieldLen - scalaryBytes = 1 for X448 and = 0 for X25519
const u = ensureBytes('u coordinate', uEnc, montgomeryBytes);
// u[fieldLen-1] crashes QuickJS (TypeError: out-of-bound numeric index)
if (fieldLen === montgomeryBytes) u[fieldLen - 1] &= 127; // 0b0111_1111
if (fieldLen === 32) u[31] &= 127; // 0b0111_1111
return bytesToNumberLE(u);

@@ -163,4 +160,5 @@ }

const bytes = ensureBytes('scalar', n);
if (bytes.length !== montgomeryBytes && bytes.length !== fieldLen)
throw new Error(`Expected ${montgomeryBytes} or ${fieldLen} bytes, got ${bytes.length}`);
const len = bytes.length;
if (len !== montgomeryBytes && len !== fieldLen)
throw new Error(`Expected ${montgomeryBytes} or ${fieldLen} bytes, got ${len}`);
return bytesToNumberLE(adjustScalarBytes(bytes));

@@ -167,0 +165,0 @@ }

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

const _2n = BigInt(2);
const u8a = (a: any): a is Uint8Array => a instanceof Uint8Array;
export type Hex = Uint8Array | string; // hex strings are accepted for simplicity

@@ -21,2 +20,10 @@ export type PrivKey = Hex | bigint; // bigints are accepted to ease learning curve

export function isBytes(a: unknown): a is Uint8Array {
return (
a instanceof Uint8Array ||
(a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array')
);
}
// Array where index 0xf0 (240) is mapped to string 'f0'
const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) =>

@@ -29,3 +36,3 @@ i.toString(16).padStart(2, '0')

export function bytesToHex(bytes: Uint8Array): string {
if (!u8a(bytes)) throw new Error('Uint8Array expected');
if (!isBytes(bytes)) throw new Error('Uint8Array expected');
// pre-caching improves the speed 6x

@@ -50,2 +57,11 @@ let hex = '';

// We use optimized technique to convert hex string to byte array
const asciis = { _0: 48, _9: 57, _A: 65, _F: 70, _a: 97, _f: 102 } as const;
function asciiToBase16(char: number): number | undefined {
if (char >= asciis._0 && char <= asciis._9) return char - asciis._0;
if (char >= asciis._A && char <= asciis._F) return char - (asciis._A - 10);
if (char >= asciis._a && char <= asciis._f) return char - (asciis._a - 10);
return;
}
/**

@@ -56,11 +72,14 @@ * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])

if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex);
const len = hex.length;
if (len % 2) throw new Error('padded hex string expected, got unpadded hex of length ' + len);
const array = new Uint8Array(len / 2);
for (let i = 0; i < array.length; i++) {
const j = i * 2;
const hexByte = hex.slice(j, j + 2);
const byte = Number.parseInt(hexByte, 16);
if (Number.isNaN(byte) || byte < 0) throw new Error('Invalid byte sequence');
array[i] = byte;
const hl = hex.length;
const al = hl / 2;
if (hl % 2) throw new Error('padded hex string expected, got unpadded hex of length ' + hl);
const array = new Uint8Array(al);
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
const n1 = asciiToBase16(hex.charCodeAt(hi));
const n2 = asciiToBase16(hex.charCodeAt(hi + 1));
if (n1 === undefined || n2 === undefined) {
const char = hex[hi] + hex[hi + 1];
throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi);
}
array[ai] = n1 * 16 + n2;
}

@@ -75,3 +94,3 @@ return array;

export function bytesToNumberLE(bytes: Uint8Array): bigint {
if (!u8a(bytes)) throw new Error('Uint8Array expected');
if (!isBytes(bytes)) throw new Error('Uint8Array expected');
return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));

@@ -108,3 +127,3 @@ }

}
} else if (u8a(hex)) {
} else if (isBytes(hex)) {
// Uint8Array.from() instead of hash.slice() because node.js Buffer

@@ -126,17 +145,24 @@ // is instance of Uint8Array, and its slice() creates **mutable** copy

export function concatBytes(...arrays: Uint8Array[]): Uint8Array {
const r = new Uint8Array(arrays.reduce((sum, a) => sum + a.length, 0));
let pad = 0; // walk through each item, ensure they have proper type
arrays.forEach((a) => {
if (!u8a(a)) throw new Error('Uint8Array expected');
r.set(a, pad);
let sum = 0;
for (let i = 0; i < arrays.length; i++) {
const a = arrays[i];
if (!isBytes(a)) throw new Error('Uint8Array expected');
sum += a.length;
}
let res = new Uint8Array(sum);
let pad = 0;
for (let i = 0; i < arrays.length; i++) {
const a = arrays[i];
res.set(a, pad);
pad += a.length;
});
return r;
}
return res;
}
export function equalBytes(b1: Uint8Array, b2: Uint8Array) {
// We don't care about timing attacks here
if (b1.length !== b2.length) return false;
for (let i = 0; i < b1.length; i++) if (b1[i] !== b2[i]) return false;
return true;
// Compares 2 u8a-s in kinda constant time
export function equalBytes(a: Uint8Array, b: Uint8Array) {
if (a.length !== b.length) return false;
let diff = 0;
for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];
return diff === 0;
}

@@ -259,3 +285,3 @@

string: (val: any) => typeof val === 'string',
stringOrUint8Array: (val: any) => typeof val === 'string' || val instanceof Uint8Array,
stringOrUint8Array: (val: any) => typeof val === 'string' || isBytes(val),
isSafeInteger: (val: any) => Number.isSafeInteger(val),

@@ -262,0 +288,0 @@ array: (val: any) => Array.isArray(val),

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

export type CurvePointsRes<T> = {
CURVE: ReturnType<typeof validatePointOpts<T>>;
ProjectivePoint: ProjConstructor<T>;

@@ -161,3 +162,3 @@ normPrivateKeyToScalar: (key: PrivKey) => bigint;

const data = typeof hex === 'string' ? h2b(hex) : hex;
if (!(data instanceof Uint8Array)) throw new Error('ui8a expected');
if (!ut.isBytes(data)) throw new Error('ui8a expected');
let l = data.length;

@@ -192,3 +193,3 @@ if (l < 2 || data[0] != 0x30) throw new E('Invalid signature tag');

export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
export function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T> {
const CURVE = validatePointOpts(opts);

@@ -243,3 +244,3 @@ const { Fp } = CURVE; // All curves has same field / group length as for now, but they can differ

if (lengths && typeof key !== 'bigint') {
if (key instanceof Uint8Array) key = ut.bytesToHex(key);
if (ut.isBytes(key)) key = ut.bytesToHex(key);
// Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes

@@ -276,3 +277,7 @@ if (typeof key !== 'string' || !lengths.includes(key.length)) throw new Error('Invalid key');

constructor(readonly px: T, readonly py: T, readonly pz: T) {
constructor(
readonly px: T,
readonly py: T,
readonly pz: T
) {
if (px == null || !Fp.isValid(px)) throw new Error('x required');

@@ -771,3 +776,7 @@ if (py == null || !Fp.isValid(py)) throw new Error('y required');

class Signature implements SignatureType {
constructor(readonly r: bigint, readonly s: bigint, readonly recovery?: number) {
constructor(
readonly r: bigint,
readonly s: bigint,
readonly recovery?: number
) {
this.assertValidity();

@@ -893,3 +902,3 @@ }

function isProbPub(item: PrivKey | PubKey): boolean {
const arr = item instanceof Uint8Array;
const arr = ut.isBytes(item);
const str = typeof item === 'string';

@@ -1058,3 +1067,3 @@ const len = (arr || str) && (item as Hex).length;

try {
if (typeof sg === 'string' || sg instanceof Uint8Array) {
if (typeof sg === 'string' || ut.isBytes(sg)) {
// Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length).

@@ -1061,0 +1070,0 @@ // Since DER can also be 2*nByteLength bytes, we check for it first.

/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
// bls12-381 pairing-friendly Barreto-Lynn-Scott elliptic curve construction allows to:
// - Construct zk-SNARKs at the 128-bit security
// - Use threshold signatures, which allows a user to sign lots of messages with one signature and
// verify them swiftly in a batch, using Boneh-Lynn-Shacham signature scheme.
// bls12-381 is pairing-friendly Barreto-Lynn-Scott elliptic curve construction allowing to:
// - Construct zk-SNARKs at the 120-bit security
// - Efficiently verify N aggregate signatures with 1 pairing and N ec additions:
// the Boneh-Lynn-Shacham signature scheme is orders of magnitude more efficient than Schnorr
//
// The library uses G1 for public keys and G2 for signatures. Support for G1 signatures is planned.
// Compatible with Algorand, Chia, Dfinity, Ethereum, FIL, Zcash. Matches specs
// [pairing-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11),
// [bls-sigs-04](https:/cfrg-hash-to/tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04),
// [hash-to-curve-12](https://tools.ietf.org/html/draft-irtf--curve-12).
//
// ### Summary

@@ -28,4 +22,13 @@ // 1. BLS Relies on Bilinear Pairing (expensive)

// - `e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))` - signature aggregation
// Filecoin uses little endian byte arrays for private keys -
// so ensure to reverse byte order if you'll use it with FIL.
//
// ### Compatibility and notes
// 1. It is compatible with Algorand, Chia, Dfinity, Ethereum, Filecoin, ZEC
// Filecoin uses little endian byte arrays for private keys - make sure to reverse byte order.
// 2. Some projects use G2 for public keys and G1 for signatures. It's called "short signature"
// 3. Curve security level is about 120 bits as per Barbulescu-Duquesne 2017
// https://hal.science/hal-01534101/file/main.pdf
// 4. Compatible with specs:
// [cfrg-pairing-friendly-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11),
// [cfrg-bls-signature-05](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05),
// [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380).
import { sha256 } from '@noble/hashes/sha256';

@@ -41,3 +44,2 @@ import { randomBytes } from '@noble/hashes/utils';

bitLen,
bitSet,
bitGet,

@@ -1021,8 +1023,38 @@ Hex,

// Point on G1 curve: (x, y)
const C_BIT_POS = Fp.BITS; // C_bit, compression bit for serialization flag
const I_BIT_POS = Fp.BITS + 1; // I_bit, point-at-infinity bit for serialization flag
const S_BIT_POS = Fp.BITS + 2; // S_bit, sign bit for serialization flag
// Compressed point of infinity
const COMPRESSED_ZERO = Fp.toBytes(bitSet(bitSet(_0n, I_BIT_POS, true), S_BIT_POS, true)); // set compressed & point-at-infinity bits
const COMPRESSED_ZERO = setMask(Fp.toBytes(_0n), { infinity: true, compressed: true }); // set compressed & point-at-infinity bits
function parseMask(bytes: Uint8Array) {
// Copy, so we can remove mask data. It will be removed also later, when Fp.create will call modulo.
bytes = bytes.slice();
const mask = bytes[0] & 0b1110_0000;
const compressed = !!((mask >> 7) & 1); // compression bit (0b1000_0000)
const infinity = !!((mask >> 6) & 1); // point at infinity bit (0b0100_0000)
const sort = !!((mask >> 5) & 1); // sort bit (0b0010_0000)
bytes[0] &= 0b0001_1111; // clear mask (zero first 3 bits)
return { compressed, infinity, sort, value: bytes };
}
function setMask(
bytes: Uint8Array,
mask: { compressed?: boolean; infinity?: boolean; sort?: boolean }
) {
if (bytes[0] & 0b1110_0000) throw new Error('setMask: non-empty mask');
if (mask.compressed) bytes[0] |= 0b1000_0000;
if (mask.infinity) bytes[0] |= 0b0100_0000;
if (mask.sort) bytes[0] |= 0b0010_0000;
return bytes;
}
function signatureG1ToRawBytes(point: ProjPointType<Fp>) {
point.assertValidity();
const isZero = point.equals(bls12_381.G1.ProjectivePoint.ZERO);
const { x, y } = point.toAffine();
if (isZero) return COMPRESSED_ZERO.slice();
const P = Fp.ORDER;
const sort = Boolean((y * _2n) / P);
return setMask(numberToBytesBE(x, Fp.BYTES), { compressed: true, sort });
}
function signatureG2ToRawBytes(point: ProjPointType<Fp2>) {

@@ -1038,6 +1070,8 @@ // NOTE: by some reasons it was missed in bls12-381, looks like bug

const tmp = y1 > _0n ? y1 * _2n : y0 * _2n;
const aflag1 = Boolean((tmp / Fp.ORDER) & _1n);
const z1 = bitSet(bitSet(x1, 381, aflag1), S_BIT_POS, true);
const sort = Boolean((tmp / Fp.ORDER) & _1n);
const z2 = x0;
return concatB(numberToBytesBE(z1, len), numberToBytesBE(z2, len));
return concatB(
setMask(numberToBytesBE(x1, len), { sort, compressed: true }),
numberToBytesBE(z2, len)
);
}

@@ -1081,3 +1115,3 @@

b: _4n,
htfDefaults: { ...htfDefaults, m: 1 },
htfDefaults: { ...htfDefaults, m: 1, DST: 'BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_' },
wrapPrivateKey: true,

@@ -1124,22 +1158,26 @@ allowInfinityPoint: true,

fromBytes: (bytes: Uint8Array): AffinePoint<Fp> => {
bytes = bytes.slice();
if (bytes.length === 48) {
const { compressed, infinity, sort, value } = parseMask(bytes);
if (value.length === 48 && compressed) {
// TODO: Fp.bytes
const P = Fp.ORDER;
const compressedValue = bytesToNumberBE(bytes);
const bflag = bitGet(compressedValue, I_BIT_POS);
const compressedValue = bytesToNumberBE(value);
// Zero
if (bflag === _1n) return { x: _0n, y: _0n };
const x = Fp.create(compressedValue & Fp.MASK);
if (infinity) {
if (x !== _0n) throw new Error('G1: non-empty compressed point at infinity');
return { x: _0n, y: _0n };
}
const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)); // y² = x³ + b
let y = Fp.sqrt(right);
if (!y) throw new Error('Invalid compressed G1 point');
const aflag = bitGet(compressedValue, C_BIT_POS);
if ((y * _2n) / P !== aflag) y = Fp.neg(y);
if ((y * _2n) / P !== BigInt(sort)) y = Fp.neg(y);
return { x: Fp.create(x), y: Fp.create(y) };
} else if (bytes.length === 96) {
} else if (value.length === 96 && !compressed) {
// Check if the infinity flag is set
if ((bytes[0] & (1 << 6)) !== 0) return bls12_381.G1.ProjectivePoint.ZERO.toAffine();
const x = bytesToNumberBE(bytes.subarray(0, Fp.BYTES));
const y = bytesToNumberBE(bytes.subarray(Fp.BYTES));
const x = bytesToNumberBE(value.subarray(0, Fp.BYTES));
const y = bytesToNumberBE(value.subarray(Fp.BYTES));
if (infinity) {
if (x !== _0n || y !== _0n) throw new Error('G1: non-empty point at infinity');
return bls12_381.G1.ProjectivePoint.ZERO.toAffine();
}
return { x: Fp.create(x), y: Fp.create(y) };

@@ -1156,6 +1194,4 @@ } else {

const P = Fp.ORDER;
let num;
num = bitSet(x, C_BIT_POS, Boolean((y * _2n) / P)); // set aflag
num = bitSet(num, S_BIT_POS, true);
return numberToBytesBE(num, Fp.BYTES);
const sort = Boolean((y * _2n) / P);
return setMask(numberToBytesBE(x, Fp.BYTES), { compressed: true, sort });
} else {

@@ -1171,2 +1207,26 @@ if (isZero) {

},
ShortSignature: {
fromHex(hex: Hex): ProjPointType<Fp> {
const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex, 48));
const P = Fp.ORDER;
const compressedValue = bytesToNumberBE(value);
// Zero
if (infinity) return bls12_381.G1.ProjectivePoint.ZERO;
const x = Fp.create(compressedValue & Fp.MASK);
const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)); // y² = x³ + b
let y = Fp.sqrt(right);
if (!y) throw new Error('Invalid compressed G1 point');
const aflag = BigInt(sort);
if ((y * _2n) / P !== aflag) y = Fp.neg(y);
const point = bls12_381.G1.ProjectivePoint.fromAffine({ x, y });
point.assertValidity();
return point;
},
toRawBytes(point: ProjPointType<Fp>) {
return signatureG1ToRawBytes(point);
},
toHex(point: ProjPointType<Fp>) {
return bytesToHex(signatureG1ToRawBytes(point));
},
},
},

@@ -1243,20 +1303,18 @@ // G2 is the order-q subgroup of E2(Fp²) : y² = x³+4(1+√−1),

fromBytes: (bytes: Uint8Array): AffinePoint<Fp2> => {
bytes = bytes.slice();
const m_byte = bytes[0] & 0xe0;
if (m_byte === 0x20 || m_byte === 0x60 || m_byte === 0xe0) {
throw new Error('Invalid encoding flag: ' + m_byte);
const { compressed, infinity, sort, value } = parseMask(bytes);
if (
(!compressed && !infinity && sort) || // 00100000
(!compressed && infinity && sort) || // 01100000
(sort && infinity && compressed) // 11100000
) {
throw new Error('Invalid encoding flag: ' + (bytes[0] & 0b1110_0000));
}
const bitC = m_byte & 0x80; // compression bit
const bitI = m_byte & 0x40; // point at infinity bit
const bitS = m_byte & 0x20; // sign bit
const L = Fp.BYTES;
const slc = (b: Uint8Array, from: number, to?: number) => bytesToNumberBE(b.slice(from, to));
if (bytes.length === 96 && bitC) {
if (value.length === 96 && compressed) {
const b = bls12_381.params.G2b;
const P = Fp.ORDER;
bytes[0] = bytes[0] & 0x1f; // clear flags
if (bitI) {
if (infinity) {
// check that all bytes are 0
if (bytes.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) {
if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) {
throw new Error('Invalid compressed G2 point');

@@ -1266,4 +1324,4 @@ }

}
const x_1 = slc(bytes, 0, L);
const x_0 = slc(bytes, L, 2 * L);
const x_1 = slc(value, 0, L);
const x_0 = slc(value, L, 2 * L);
const x = Fp2.create({ c0: Fp.create(x_0), c1: Fp.create(x_1) });

@@ -1273,13 +1331,15 @@ const right = Fp2.add(Fp2.pow(x, _3n), b); // y² = x³ + 4 * (u+1) = x³ + b

const Y_bit = y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P ? _1n : _0n;
y = bitS > 0 && Y_bit > 0 ? y : Fp2.neg(y);
y = sort && Y_bit > 0 ? y : Fp2.neg(y);
return { x, y };
} else if (bytes.length === 192 && !bitC) {
// Check if the infinity flag is set
if ((bytes[0] & (1 << 6)) !== 0) {
} else if (value.length === 192 && !compressed) {
if (infinity) {
if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) {
throw new Error('Invalid uncompressed G2 point');
}
return { x: Fp2.ZERO, y: Fp2.ZERO };
}
const x1 = slc(bytes, 0, L);
const x0 = slc(bytes, L, 2 * L);
const y1 = slc(bytes, 2 * L, 3 * L);
const y0 = slc(bytes, 3 * L, 4 * L);
const x1 = slc(value, 0, L);
const x0 = slc(value, L, 2 * L);
const y1 = slc(value, 2 * L, 3 * L);
const y0 = slc(value, 3 * L, 4 * L);
return { x: Fp2.fromBigTuple([x0, x1]), y: Fp2.fromBigTuple([y0, y1]) };

@@ -1297,6 +1357,6 @@ } else {

const flag = Boolean(y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P);
// set compressed & sign bits (looks like different offsets than for G1/Fp?)
let x_1 = bitSet(x.c1, C_BIT_POS, flag);
x_1 = bitSet(x_1, S_BIT_POS, true);
return concatB(numberToBytesBE(x_1, len), numberToBytesBE(x.c0, len));
return concatB(
setMask(numberToBytesBE(x.c1, len), { compressed: true, sort: flag }),
numberToBytesBE(x.c0, len)
);
} else {

@@ -1317,3 +1377,3 @@ if (isZero) return concatB(new Uint8Array([0x40]), new Uint8Array(4 * len - 1)); // bytes[0] |= 1 << 6;

fromHex(hex: Hex): ProjPointType<Fp2> {
hex = ensureBytes('signatureHex', hex);
const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex));
const P = Fp.ORDER;

@@ -1323,8 +1383,6 @@ const half = hex.length / 2;

throw new Error('Invalid compressed signature length, must be 96 or 192');
const z1 = bytesToNumberBE(hex.slice(0, half));
const z2 = bytesToNumberBE(hex.slice(half));
const z1 = bytesToNumberBE(value.slice(0, half));
const z2 = bytesToNumberBE(value.slice(half));
// Indicates the infinity point
const bflag1 = bitGet(z1, I_BIT_POS);
if (bflag1 === _1n) return bls12_381.G2.ProjectivePoint.ZERO;
if (infinity) return bls12_381.G2.ProjectivePoint.ZERO;
const x1 = Fp.create(z1 & Fp.MASK);

@@ -1341,3 +1399,3 @@ const x2 = Fp.create(z2);

const { re: y0, im: y1 } = Fp2.reim(y);
const aflag1 = bitGet(z1, 381);
const aflag1 = BigInt(sort);
const isGreater = y1 > _0n && (y1 * _2n) / P !== aflag1;

@@ -1344,0 +1402,0 @@ const isZero = y1 === _0n && (y0 * _2n) / P !== aflag1;

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

* Previously known as alt_bn_128, when it had 128-bit security.
* Recent research shown it's weaker, the naming has been adjusted to its prime bit count.
* https://github.com/zcash/zcash/issues/2502
* Barbulescu-Duquesne 2017 shown it's weaker: just about 100 bits,
* so the naming has been adjusted to its prime bit count
* https://hal.science/hal-01534101/file/main.pdf
*/

@@ -13,0 +14,0 @@ export const bn254 = weierstrass({

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

import { createHasher, htfBasicOpts, expand_message_xmd } from './abstract/hash-to-curve.js';
import { AffinePoint } from './abstract/curve.js';
import { AffinePoint, Group } from './abstract/curve.js';

@@ -347,3 +347,3 @@ /**

*/
class RistPoint {
class RistPoint implements Group<RistPoint> {
static BASE: RistPoint;

@@ -476,2 +476,10 @@ static ZERO: RistPoint;

}
double(): RistPoint {
return new RistPoint(this.ep.double());
}
negate(): RistPoint {
return new RistPoint(this.ep.negate());
}
}

@@ -478,0 +486,0 @@ export const RistrettoPoint = /* @__PURE__ */ (() => {

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

} from './abstract/utils.js';
import { AffinePoint } from './abstract/curve.js';
import { AffinePoint, Group } from './abstract/curve.js';

@@ -107,2 +107,3 @@ /**

),
// RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys
nBitLength: 456,

@@ -142,4 +143,5 @@ // Cofactor

a: BigInt(156326),
// RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys
montgomeryBits: 448,
nByteLength: 57,
nByteLength: 56,
P: ed448P,

@@ -170,3 +172,5 @@ Gu: BigInt(5),

}
export const edwardsToMontgomery = edwardsToMontgomeryPub; // deprecated
// TODO: add edwardsToMontgomeryPriv, similar to ed25519 version

@@ -176,2 +180,3 @@ // Hash To Curve Elligator2 Map

const ELL2_J = BigInt(156326);
function map_to_curve_elligator2_curve448(u: bigint) {

@@ -206,2 +211,3 @@ let tv1 = Fp.sqr(u); // 1. tv1 = u^2

}
function map_to_curve_elligator2_edwards448(u: bigint) {

@@ -332,3 +338,3 @@ let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u); // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u)

*/
class DcfPoint {
class DcfPoint implements Group<DcfPoint> {
static BASE: DcfPoint;

@@ -455,3 +461,12 @@ static ZERO: DcfPoint;

}
double(): DcfPoint {
return new DcfPoint(this.ep.double());
}
negate(): DcfPoint {
return new DcfPoint(this.ep.negate());
}
}
export const DecafPoint = /* @__PURE__ */ (() => {

@@ -458,0 +473,0 @@ // decaf448 base point is ed448 base x 2

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc