Socket
Socket
Sign inDemoInstall

@noble/curves

Package Overview
Dependencies
Maintainers
1
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@noble/curves - npm Package Compare versions

Comparing version 0.9.1 to 1.0.0

bn254.d.ts

74

abstract/bls.d.ts

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

export type SignatureCoder<Fp2> = {
decode(hex: Hex): ProjPointType<Fp2>;
encode(point: ProjPointType<Fp2>): Uint8Array;
fromHex(hex: Hex): ProjPointType<Fp2>;
toRawBytes(point: ProjPointType<Fp2>): Uint8Array;
toHex(point: ProjPointType<Fp2>): string;
};
export type CurveType<Fp, Fp2, Fp6, Fp12> = {
r: bigint;
G1: Omit<CurvePointsType<Fp>, 'n'> & {

@@ -36,19 +36,24 @@ mapToCurve: htf.MapToCurve<Fp>;

};
x: bigint;
Fp: IField<Fp>;
Fr: IField<bigint>;
Fp2: IField<Fp2> & {
reim: (num: Fp2) => {
re: bigint;
im: bigint;
fields: {
Fp: IField<Fp>;
Fr: IField<bigint>;
Fp2: IField<Fp2> & {
reim: (num: Fp2) => {
re: bigint;
im: bigint;
};
multiplyByB: (num: Fp2) => Fp2;
frobeniusMap(num: Fp2, power: number): Fp2;
};
multiplyByB: (num: Fp2) => Fp2;
frobeniusMap(num: Fp2, power: number): Fp2;
Fp6: IField<Fp6>;
Fp12: IField<Fp12> & {
frobeniusMap(num: Fp12, power: number): Fp12;
multiplyBy014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12;
conjugate(num: Fp12): Fp12;
finalExponentiate(num: Fp12): Fp12;
};
};
Fp6: IField<Fp6>;
Fp12: IField<Fp12> & {
frobeniusMap(num: Fp12, power: number): Fp12;
multiplyBy014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12;
conjugate(num: Fp12): Fp12;
finalExponentiate(num: Fp12): Fp12;
params: {
x: bigint;
r: bigint;
};

@@ -60,14 +65,2 @@ htfDefaults: htf.Opts;

export type CurveFn<Fp, Fp2, Fp6, Fp12> = {
CURVE: CurveType<Fp, Fp2, Fp6, Fp12>;
Fr: IField<bigint>;
Fp: IField<Fp>;
Fp2: IField<Fp2>;
Fp6: IField<Fp6>;
Fp12: IField<Fp12>;
G1: CurvePointsRes<Fp> & ReturnType<typeof htf.createHasher<Fp>>;
G2: CurvePointsRes<Fp2> & ReturnType<typeof htf.createHasher<Fp2>>;
Signature: SignatureCoder<Fp2>;
millerLoop: (ell: [Fp2, Fp2, Fp2][], g1: [Fp, Fp]) => Fp12;
calcPairingPrecomputes: (p: AffinePoint<Fp2>) => [Fp2, Fp2, Fp2][];
pairing: (P: ProjPointType<Fp>, Q: ProjPointType<Fp2>, withFinalExponent?: boolean) => Fp12;
getPublicKey: (privateKey: PrivKey) => Uint8Array;

@@ -79,2 +72,3 @@ sign: {

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: {

@@ -88,5 +82,23 @@ (publicKeys: Hex[]): Uint8Array;

};
verifyBatch: (signature: Hex | ProjPointType<Fp2>, messages: (Hex | ProjPointType<Fp2>)[], publicKeys: (Hex | ProjPointType<Fp>)[]) => boolean;
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][];
};

@@ -93,0 +105,0 @@ };

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

const weierstrass_js_1 = require("./weierstrass.js");
// prettier-ignore
const _2n = BigInt(2), _3n = BigInt(3);
function bls(CURVE) {
// Fields looks pretty specific for curve, so for now we need to pass them with opts
const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE;
const BLS_X_LEN = (0, utils_js_1.bitLen)(CURVE.x);
// Fields are specific for curve, so for now we'll need to pass them with opts
const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE.fields;
const BLS_X_LEN = (0, utils_js_1.bitLen)(CURVE.params.x);
const groupLen = 32; // TODO: calculate; hardcoded for now

@@ -27,14 +29,14 @@ // Pre-compute coefficients for sparse multiplication

let t1 = Fp2.sqr(Rz); // Rz²
let t2 = Fp2.multiplyByB(Fp2.mul(t1, 3n)); // 3 * T1 * B
let t3 = Fp2.mul(t2, 3n); // 3 * T2
let t2 = Fp2.multiplyByB(Fp2.mul(t1, _3n)); // 3 * T1 * B
let t3 = Fp2.mul(t2, _3n); // 3 * T2
let t4 = Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(Ry, Rz)), t1), t0); // (Ry + Rz)² - T1 - T0
ell_coeff.push([
Fp2.sub(t2, t0),
Fp2.mul(Fp2.sqr(Rx), 3n),
Fp2.mul(Fp2.sqr(Rx), _3n),
Fp2.neg(t4), // -T4
]);
Rx = Fp2.div(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), 2n); // ((T0 - T3) * Rx * Ry) / 2
Ry = Fp2.sub(Fp2.sqr(Fp2.div(Fp2.add(t0, t3), 2n)), Fp2.mul(Fp2.sqr(t2), 3n)); // ((T0 + T3) / 2)² - 3 * T2²
Rx = Fp2.div(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), _2n); // ((T0 - T3) * Rx * Ry) / 2
Ry = Fp2.sub(Fp2.sqr(Fp2.div(Fp2.add(t0, t3), _2n)), Fp2.mul(Fp2.sqr(t2), _3n)); // ((T0 + T3) / 2)² - 3 * T2²
Rz = Fp2.mul(t0, t4); // T0 * T4
if ((0, utils_js_1.bitGet)(CURVE.x, i)) {
if ((0, utils_js_1.bitGet)(CURVE.params.x, i)) {
// Addition

@@ -51,3 +53,3 @@ let t0 = Fp2.sub(Ry, Fp2.mul(Qy, Rz)); // Ry - Qy * Rz

let t4 = Fp2.mul(t2, Rx); // T2 * Rx
let t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, 2n)), Fp2.mul(Fp2.sqr(t0), Rz)); // T3 - 2 * T4 + T0² * Rz
let t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, _2n)), Fp2.mul(Fp2.sqr(t0), Rz)); // T3 - 2 * T4 + T0² * Rz
Rx = Fp2.mul(t1, t5); // T1 * T5

@@ -61,3 +63,3 @@ Ry = Fp2.sub(Fp2.mul(Fp2.sub(t4, t5), t0), Fp2.mul(t3, Ry)); // (T4 - T5) * T0 - T3 * Ry

function millerLoop(ell, g1) {
const { x } = CURVE;
const { x } = CURVE.params;
const Px = g1[0];

@@ -81,4 +83,5 @@ const Py = g1[1];

randomPrivateKey: () => {
return Fr.toBytes((0, modular_js_1.hashToPrivateScalar)(CURVE.randomBytes(groupLen + 8), CURVE.r));
return Fr.toBytes((0, modular_js_1.hashToPrivateScalar)(CURVE.randomBytes(groupLen + 8), CURVE.params.r));
},
calcPairingPrecomputes,
};

@@ -125,3 +128,3 @@ // Point on G1 curve: (x, y)

function normP2(point) {
return point instanceof G2.ProjectivePoint ? point : Signature.decode(point);
return point instanceof G2.ProjectivePoint ? point : Signature.fromHex(point);
}

@@ -144,3 +147,3 @@ function normP2Hash(point, htfOpts) {

return sigPoint;
return Signature.encode(sigPoint);
return Signature.toRawBytes(sigPoint);
}

@@ -182,3 +185,3 @@ // Checks if pairing of public key & hash is equal to pairing of generator & signature.

}
return Signature.encode(aggAffine);
return Signature.toRawBytes(aggAffine);
}

@@ -216,20 +219,26 @@ // https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407

return {
CURVE,
Fr,
Fp,
Fp2,
Fp6,
Fp12,
G1,
G2,
Signature,
millerLoop,
calcPairingPrecomputes,
pairing,
getPublicKey,
sign,
verify,
verifyBatch,
aggregatePublicKeys,
aggregateSignatures,
verifyBatch,
millerLoop,
pairing,
G1,
G2,
Signature,
fields: {
Fr,
Fp,
Fp2,
Fp6,
Fp12,
},
params: {
x: CURVE.params.x,
r: CURVE.params.r,
G1b: CURVE.G1.b,
G2b: CURVE.G2.b,
},
utils,

@@ -236,0 +245,0 @@ };

@@ -15,3 +15,3 @@ import * as ut from './utils.js';

};
preHash?: FHash;
prehash?: FHash;
mapToCurve?: (scalar: bigint[]) => AffinePoint<bigint>;

@@ -39,3 +39,3 @@ };

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

@@ -42,0 +42,0 @@ readonly p: bigint;

@@ -13,2 +13,4 @@ "use strict";

const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _8n = BigInt(8);
// verification rule is either zip215 or rfc8032 / nist186-5. Consult fromHex:
const VERIFY_DEFAULT = { zip215: true };
function validateOpts(curve) {

@@ -33,3 +35,3 @@ const opts = (0, curve_js_1.validateBasic)(curve);

const CURVE = validateOpts(curveDef);
const { Fp, n: CURVE_ORDER, preHash, hash: cHash, randomBytes, nByteLength, h: cofactor } = CURVE;
const { Fp, n: CURVE_ORDER, prehash: prehash, hash: cHash, randomBytes, nByteLength, h: cofactor, } = CURVE;
const MASK = _2n ** BigInt(nByteLength * 8);

@@ -279,3 +281,3 @@ const modP = Fp.create; // Function overrides

// Uses algo from RFC8032 5.1.3.
static fromHex(hex, strict = true) {
static fromHex(hex, zip215 = false) {
const { d, a } = CURVE;

@@ -293,6 +295,6 @@ const len = Fp.BYTES;

// RFC8032 prohibits >= p, but ZIP215 doesn't
if (strict)
assertInRange(y, Fp.ORDER); // strict=true [1..P-1] (2^255-19-1 for ed25519)
if (zip215)
assertInRange(y, MASK); // zip215=true [1..P-1] (2^255-19-1 for ed25519)
else
assertInRange(y, MASK); // strict=false [1..MASK-1] (2^256-1 for ed25519)
assertInRange(y, Fp.ORDER); // zip215=false [1..MASK-1] (2^256-1 for ed25519)
}

@@ -358,13 +360,13 @@ // Ed25519: x² = (y²-1)/(dy²+1) mod p. Ed448: x² = (y²-1)/(dy²-1) mod p. Generic case:

const msg = ut.concatBytes(...msgs);
return modN_LE(cHash(domain(msg, (0, utils_js_1.ensureBytes)('context', context), !!preHash)));
return modN_LE(cHash(domain(msg, (0, utils_js_1.ensureBytes)('context', context), !!prehash)));
}
/** Signs message with privateKey. RFC8032 5.1.6 */
function sign(msg, privKey, context) {
function sign(msg, privKey, options = {}) {
msg = (0, utils_js_1.ensureBytes)('message', msg);
if (preHash)
msg = preHash(msg); // for ed25519ph etc.
if (prehash)
msg = prehash(msg); // for ed25519ph etc.
const { prefix, scalar, pointBytes } = getExtendedPublicKey(privKey);
const r = hashDomainToScalar(context, prefix, msg); // r = dom2(F, C) || prefix || PH(M)
const r = hashDomainToScalar(options.context, prefix, msg); // r = dom2(F, C) || prefix || PH(M)
const R = G.multiply(r).toRawBytes(); // R = rG
const k = hashDomainToScalar(context, R, pointBytes, msg); // R || A || PH(M)
const k = hashDomainToScalar(options.context, R, pointBytes, msg); // R || A || PH(M)
const s = modN(r + k * scalar); // S = (r + k * s) mod L

@@ -375,12 +377,22 @@ assertGE0(s); // 0 <= s < l

}
function verify(sig, msg, publicKey, context) {
const verifyOpts = VERIFY_DEFAULT;
function verify(sig, msg, publicKey, options = verifyOpts) {
const { context, zip215 } = options;
const len = Fp.BYTES; // Verifies EdDSA signature against message and public key. RFC8032 5.1.7.
sig = (0, utils_js_1.ensureBytes)('signature', sig, 2 * len); // An extended group equation is checked.
msg = (0, utils_js_1.ensureBytes)('message', msg); // ZIP215 compliant, which means not fully RFC8032 compliant.
if (preHash)
msg = preHash(msg); // for ed25519ph, etc
const A = Point.fromHex(publicKey, false); // Check for s bounds, hex validity
const R = Point.fromHex(sig.slice(0, len), false); // 0 <= R < 2^256: ZIP215 R can be >= P
msg = (0, utils_js_1.ensureBytes)('message', msg);
if (prehash)
msg = prehash(msg); // for ed25519ph, etc
const s = ut.bytesToNumberLE(sig.slice(len, 2 * len));
const SB = G.multiplyUnsafe(s); // 0 <= s < l is done inside
// zip215: true is good for consensus-critical apps and allows points < 2^256
// zip215: false follows RFC8032 / NIST186-5 and restricts points to CURVE.p
let A, R, SB;
try {
A = Point.fromHex(publicKey, zip215);
R = Point.fromHex(sig.slice(0, len), zip215);
SB = G.multiplyUnsafe(s); // 0 <= s < l is done inside
}
catch (error) {
return false;
}
const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg);

@@ -387,0 +399,0 @@ const RkA = R.add(A.multiplyUnsafe(k));

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

k: number;
expand?: 'xmd' | 'xof';
expand: 'xmd' | 'xof';
hash: CHash;

@@ -22,0 +22,0 @@ };

@@ -120,7 +120,8 @@ "use strict";

}
else if (expand === undefined) {
else if (expand === '_internal_pass') {
// for internal tests only
prb = msg;
}
else {
throw new Error('expand must be "xmd", "xof" or undefined');
throw new Error('expand must be "xmd" or "xof"');
}

@@ -127,0 +128,0 @@ const u = new Array(count);

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

let len;
for (len = 0; n > 0n; n >>= _1n, len += 1)
for (len = 0; n > _0n; n >>= _1n, len += 1)
;

@@ -135,3 +135,3 @@ return len;

// Same as !!+Array.from(n.toString(2)).reverse()[pos]
const bitGet = (n, pos) => (n >> BigInt(pos)) & 1n;
const bitGet = (n, pos) => (n >> BigInt(pos)) & _1n;
exports.bitGet = bitGet;

@@ -138,0 +138,0 @@ // Sets single bit at position

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

};
export declare const DER: {
Err: {
new (m?: string): {
name: string;
message: string;
stack?: string | undefined;
};
};
_parseInt(data: Uint8Array): {
d: bigint;
l: Uint8Array;
};
toSig(hex: string | Uint8Array): {
r: bigint;
s: bigint;
};
hexFromSig(sig: {
r: bigint;
s: bigint;
}): string;
};
export declare function weierstrassPoints<T>(opts: CurvePointsType<T>): {

@@ -94,0 +115,0 @@ CURVE: Readonly<{

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.mapToCurveSimpleSWU = exports.SWUFpSqrtRatio = exports.weierstrass = exports.weierstrassPoints = void 0;
exports.mapToCurveSimpleSWU = exports.SWUFpSqrtRatio = exports.weierstrass = exports.weierstrassPoints = exports.DER = void 0;
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */

@@ -39,3 +39,3 @@ // Short Weierstrass curve. The formula is: y² = x³ + ax + b

const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut;
const DER = {
exports.DER = {
// asn.1 DER encoding utils

@@ -48,3 +48,3 @@ Err: class DERErr extends Error {

_parseInt(data) {
const { Err: E } = DER;
const { Err: E } = exports.DER;
if (data.length < 2 || data[0] !== 0x02)

@@ -56,5 +56,10 @@ throw new E('Invalid signature integer tag');

throw new E('Invalid signature integer: wrong length');
if (res[0] === 0x00 && res[1] <= 0x7f)
throw new E('Invalid signature integer: trailing length');
// ^ Weird condition: not about length, but about first bytes of number.
// https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag,
// since we always use positive integers here. It must always be empty:
// - add zero byte if exists
// - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding)
if (res[0] & 0b10000000)
throw new E('Invalid signature integer: negative');
if (res[0] === 0x00 && !(res[1] & 0b10000000))
throw new E('Invalid signature integer: unnecessary leading zero');
return { d: b2n(res), l: data.subarray(len + 2) }; // d is data, l is left

@@ -64,3 +69,3 @@ },

// parse DER signature
const { Err: E } = DER;
const { Err: E } = exports.DER;
const data = typeof hex === 'string' ? h2b(hex) : hex;

@@ -74,4 +79,4 @@ if (!(data instanceof Uint8Array))

throw new E('Invalid signature: incorrect length');
const { d: r, l: sBytes } = DER._parseInt(data.subarray(2));
const { d: s, l: rBytesLeft } = DER._parseInt(sBytes);
const { d: r, l: sBytes } = exports.DER._parseInt(data.subarray(2));
const { d: s, l: rBytesLeft } = exports.DER._parseInt(sBytes);
if (rBytesLeft.length)

@@ -82,3 +87,4 @@ throw new E('Invalid signature: left bytes after parsing');

hexFromSig(sig) {
const slice = (s) => (Number.parseInt(s[0], 16) >= 8 ? '00' + s : s); // slice DER
// Add leading zero if first byte has negative bit enabled. More details in '_parseInt'
const slice = (s) => (Number.parseInt(s[0], 16) & 0b1000 ? '00' + s : s);
const h = (num) => {

@@ -127,2 +133,8 @@ const hex = num.toString(16);

}
// Validate whether the passed curve params are valid.
// We check if curve equation works for generator point.
// `assertValidity()` won't work: `isTorsionFree()` is not available at this point in bls12-381.
// ProjectivePoint class has not been initialized yet.
if (!Fp.eql(Fp.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx)))
throw new Error('bad generator point: equation left != right');
// Valid group elements reside in range 1..n-1

@@ -511,2 +523,3 @@ function isWithinCurveOrder(num) {

const wnaf = (0, curve_js_1.wNAF)(Point, CURVE.endo ? Math.ceil(_bits / 2) : _bits);
// Validate if generator point is on curve
return {

@@ -618,3 +631,3 @@ CURVE,

static fromDER(hex) {
const { r, s } = DER.toSig((0, utils_js_1.ensureBytes)('DER', hex));
const { r, s } = exports.DER.toSig((0, utils_js_1.ensureBytes)('DER', hex));
return new Signature(r, s);

@@ -663,3 +676,3 @@ }

toDERHex() {
return DER.hexFromSig({ r: this.r, s: this.s });
return exports.DER.hexFromSig({ r: this.r, s: this.s });
}

@@ -885,3 +898,3 @@ // padded bytes of r, then padded bytes of s

catch (derError) {
if (!(derError instanceof DER.Err))
if (!(derError instanceof exports.DER.Err))
throw derError;

@@ -967,3 +980,3 @@ _sig = Signature.fromCompact(sg);

// 17. for i in (c1, c1 - 1, ..., 2):
for (let i = c1; i > 1; i--) {
for (let i = c1; i > _1n; i--) {
let tv5 = _2n ** (i - _2n); // 18. tv5 = i - 2; 19. tv5 = 2^tv5

@@ -970,0 +983,0 @@ let tvv5 = Fp.pow(tv4, tv5); // 20. tv5 = tv4^tv5

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

// Compatible with Algorand, Chia, Dfinity, Ethereum, FIL, Zcash. Matches specs
// [pairing-curves-10](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-10),
// [pairing-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11),
// [bls-sigs-04](https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04),

@@ -33,19 +33,2 @@ // [hash-to-curve-12](https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-12).

// so ensure to reverse byte order if you'll use it with FIL.
//
// ### Resources
// - [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:
// [part 1](https://research.nccgroup.com/2020/07/06/pairing-over-bls12-381-part-1-fields/),
// [part 2](https://research.nccgroup.com/2020/07/13/pairing-over-bls12-381-part-2-curves/),
// [part 3](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/)
//
// ### Differences from @noble/bls12-381 1.4
// - PointG1 -> G1.Point
// - PointG2 -> G2.Point
// - PointG2.fromSignature -> Signature.decode
// - PointG2.toSignature -> Signature.encode
// - Fixed Fp2 ORDER
// - Points now have only two coordinates
const sha256_1 = require("@noble/hashes/sha256");

@@ -62,2 +45,3 @@ const utils_1 = require("@noble/hashes/utils");

const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);
// prettier-ignore
const _8n = BigInt(8), _16n = BigInt(16);

@@ -801,5 +785,5 @@ // CURVE FIELDS

const G2_SWU = (0, weierstrass_js_1.mapToCurveSimpleSWU)(Fp2, {
A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(240n) }),
B: Fp2.create({ c0: Fp.create(1012n), c1: Fp.create(1012n) }),
Z: Fp2.create({ c0: Fp.create(-2n), c1: Fp.create(-1n) }), // Z: -(2 + I)
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)) }),
Z: Fp2.create({ c0: Fp.create(BigInt(-2)), c1: Fp.create(BigInt(-1)) }), // Z: -(2 + I)
});

@@ -810,3 +794,3 @@ // Optimized SWU Map - Fp to G1

B: Fp.create(BigInt('0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0')),
Z: Fp.create(11n),
Z: Fp.create(BigInt(11)),
});

@@ -881,3 +865,18 @@ // Endomorphisms (for fast cofactor clearing)

// 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 = 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
function signatureG2ToRawBytes(point) {
// NOTE: by some reasons it was missed in bls12-381, looks like bug
point.assertValidity();
const len = Fp.BYTES;
if (point.equals(exports.bls12_381.G2.ProjectivePoint.ZERO))
return (0, utils_js_1.concatBytes)(COMPRESSED_ZERO, (0, utils_js_1.numberToBytesBE)(_0n, len));
const { x, y } = point.toAffine();
const { re: x0, im: x1 } = Fp2.reim(x);
const { re: y0, im: y1 } = Fp2.reim(y);
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 z2 = x0;
return (0, utils_js_1.concatBytes)((0, utils_js_1.numberToBytesBE)(z1, len), (0, utils_js_1.numberToBytesBE)(z2, len));
}
// To verify curve parameters, see pairing-friendly-curves spec:

@@ -895,9 +894,9 @@ // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-09

// Fields
Fr,
Fp,
Fp2,
Fp6,
Fp12,
// order; z⁴ − z² + 1
r: Fr.ORDER,
fields: {
Fp,
Fp2,
Fp6,
Fp12,
Fr,
},
// G1 is the order-q subgroup of E1(Fp) : y² = x³ + 4, #E1(Fp) = h1q, where

@@ -928,4 +927,4 @@ // characteristic; z + (z⁴ - z² + 1)(z - 1)²/3

// todo: unroll
const xP = point.multiplyUnsafe(exports.bls12_381.CURVE.x).negate(); // [x]P
const u2P = xP.multiplyUnsafe(exports.bls12_381.CURVE.x); // [u2]P
const xP = point.multiplyUnsafe(exports.bls12_381.params.x).negate(); // [x]P
const u2P = xP.multiplyUnsafe(exports.bls12_381.params.x); // [u2]P
return u2P.equals(phi);

@@ -948,3 +947,3 @@ // https://eprint.iacr.org/2019/814.pdf

// return this.multiplyUnsafe(CURVE.h);
return point.multiplyUnsafe(exports.bls12_381.CURVE.x).add(point); // x*P + P
return point.multiplyUnsafe(exports.bls12_381.params.x).add(point); // x*P + P
},

@@ -956,3 +955,5 @@ mapToCurve: (scalars) => {

fromBytes: (bytes) => {
bytes = bytes.slice();
if (bytes.length === 48) {
// TODO: Fp.bytes
const P = Fp.ORDER;

@@ -965,3 +966,3 @@ const compressedValue = (0, utils_js_1.bytesToNumberBE)(bytes);

const x = Fp.create(compressedValue & Fp.MASK);
const right = Fp.add(Fp.pow(x, _3n), Fp.create(exports.bls12_381.CURVE.G1.b)); // y² = x³ + b
const right = Fp.add(Fp.pow(x, _3n), Fp.create(exports.bls12_381.params.G1b)); // y² = x³ + b
let y = Fp.sqrt(right);

@@ -979,4 +980,4 @@ if (!y)

return exports.bls12_381.G1.ProjectivePoint.ZERO.toAffine();
const x = (0, utils_js_1.bytesToNumberBE)(bytes.slice(0, Fp.BYTES));
const y = (0, utils_js_1.bytesToNumberBE)(bytes.slice(Fp.BYTES));
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) };

@@ -1046,3 +1047,3 @@ }

isTorsionFree: (c, P) => {
return P.multiplyUnsafe(exports.bls12_381.CURVE.x).negate().equals(G2psi(c, P)); // ψ(P) == [u](P)
return P.multiplyUnsafe(exports.bls12_381.params.x).negate().equals(G2psi(c, P)); // ψ(P) == [u](P)
// Older version: https://eprint.iacr.org/2019/814.pdf

@@ -1057,3 +1058,3 @@ // Ψ²(P) => Ψ³(P) => [z]Ψ³(P) where z = -x => [z]Ψ³(P) - Ψ²(P) + P == O

clearCofactor: (c, P) => {
const { x } = exports.bls12_381.CURVE;
const x = exports.bls12_381.params.x;
let t1 = P.multiplyUnsafe(x).negate(); // [-x]P

@@ -1072,2 +1073,3 @@ let t2 = G2psi(c, P); // Ψ(P)

fromBytes: (bytes) => {
bytes = bytes.slice();
const m_byte = bytes[0] & 0xe0;

@@ -1083,3 +1085,3 @@ if (m_byte === 0x20 || m_byte === 0x60 || m_byte === 0xe0) {

if (bytes.length === 96 && bitC) {
const { b } = exports.bls12_381.CURVE.G2;
const b = exports.bls12_381.params.G2b;
const P = Fp.ORDER;

@@ -1119,8 +1121,8 @@ bytes[0] = bytes[0] & 0x1f; // clear flags

toBytes: (c, point, isCompressed) => {
const { BYTES: len, ORDER: P } = Fp;
const isZero = point.equals(c.ZERO);
const { x, y } = point.toAffine();
if (isCompressed) {
const P = Fp.ORDER;
if (isZero)
return (0, utils_js_1.concatBytes)(COMPRESSED_ZERO, (0, utils_js_1.numberToBytesBE)(0n, Fp.BYTES));
return (0, utils_js_1.concatBytes)(COMPRESSED_ZERO, (0, utils_js_1.numberToBytesBE)(_0n, len));
const flag = Boolean(y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P);

@@ -1130,10 +1132,10 @@ // set compressed & sign bits (looks like different offsets than for G1/Fp?)

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, Fp.BYTES), (0, utils_js_1.numberToBytesBE)(x.c0, Fp.BYTES));
return (0, utils_js_1.concatBytes)((0, utils_js_1.numberToBytesBE)(x_1, len), (0, utils_js_1.numberToBytesBE)(x.c0, len));
}
else {
if (isZero)
return (0, utils_js_1.concatBytes)(new Uint8Array([0x40]), new Uint8Array(4 * Fp.BYTES - 1)); // bytes[0] |= 1 << 6;
return (0, utils_js_1.concatBytes)(new Uint8Array([0x40]), new Uint8Array(4 * len - 1)); // bytes[0] |= 1 << 6;
const { re: x0, im: x1 } = Fp2.reim(x);
const { re: y0, im: y1 } = Fp2.reim(y);
return (0, utils_js_1.concatBytes)((0, utils_js_1.numberToBytesBE)(x1, Fp.BYTES), (0, utils_js_1.numberToBytesBE)(x0, Fp.BYTES), (0, utils_js_1.numberToBytesBE)(y1, Fp.BYTES), (0, utils_js_1.numberToBytesBE)(y0, Fp.BYTES));
return (0, utils_js_1.concatBytes)((0, utils_js_1.numberToBytesBE)(x1, len), (0, utils_js_1.numberToBytesBE)(x0, len), (0, utils_js_1.numberToBytesBE)(y1, len), (0, utils_js_1.numberToBytesBE)(y0, len));
}

@@ -1143,3 +1145,3 @@ },

// TODO: Optimize, it's very slow because of sqrt.
decode(hex) {
fromHex(hex) {
hex = (0, utils_js_1.ensureBytes)('signatureHex', hex);

@@ -1159,3 +1161,3 @@ const P = Fp.ORDER;

const x = Fp2.create({ c0: x2, c1: x1 });
const y2 = Fp2.add(Fp2.pow(x, _3n), exports.bls12_381.CURVE.G2.b); // y² = x³ + 4
const y2 = Fp2.add(Fp2.pow(x, _3n), exports.bls12_381.params.G2b); // y² = x³ + 4
// The slow part

@@ -1177,20 +1179,14 @@ let y = Fp2.sqrt(y2);

},
encode(point) {
// NOTE: by some reasons it was missed in bls12-381, looks like bug
point.assertValidity();
if (point.equals(exports.bls12_381.G2.ProjectivePoint.ZERO))
return (0, utils_js_1.concatBytes)(COMPRESSED_ZERO, (0, utils_js_1.numberToBytesBE)(0n, Fp.BYTES));
const a = point.toAffine();
const { re: x0, im: x1 } = Fp2.reim(a.x);
const { re: y0, im: y1 } = Fp2.reim(a.y);
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 z2 = x0;
return (0, utils_js_1.concatBytes)((0, utils_js_1.numberToBytesBE)(z1, Fp.BYTES), (0, utils_js_1.numberToBytesBE)(z2, Fp.BYTES));
toRawBytes(point) {
return signatureG2ToRawBytes(point);
},
toHex(point) {
return (0, utils_js_1.bytesToHex)(signatureG2ToRawBytes(point));
},
},
},
// The BLS parameter x for BLS12-381
x: BLS_X,
params: {
x: BLS_X,
r: Fr.ORDER, // order; z⁴ − z² + 1; CURVE.n from other curves
},
htfDefaults,

@@ -1197,0 +1193,0 @@ hash: sha256_1.sha256,

@@ -10,2 +10,11 @@ import { ExtPointType } from './abstract/edwards.js';

export declare const x25519: import("./abstract/montgomery.js").CurveFn;
/**
* Converts ed25519 public key to x25519 public key. Uses formula:
* * `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)`
* * `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))`
* @example
* const aPub = ed25519.getPublicKey(utils.randomPrivateKey());
* x25519.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub))
*/
export declare function edwardsToMontgomery(edwardsPub: Hex): Uint8Array;
declare const hashToCurve: (msg: Uint8Array, options?: htf.htfBasicOpts | undefined) => htf.H2CPoint<bigint>, encodeToCurve: (msg: Uint8Array, options?: htf.htfBasicOpts | undefined) => htf.H2CPoint<bigint>;

@@ -12,0 +21,0 @@ export { hashToCurve, encodeToCurve };

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.hash_to_ristretto255 = exports.RistrettoPoint = exports.encodeToCurve = exports.hashToCurve = exports.x25519 = exports.ed25519ph = exports.ed25519ctx = exports.ed25519 = exports.ED25519_TORSION_SUBGROUP = void 0;
exports.hash_to_ristretto255 = exports.RistrettoPoint = exports.encodeToCurve = exports.hashToCurve = exports.edwardsToMontgomery = exports.x25519 = exports.ed25519ph = exports.ed25519ctx = exports.ed25519 = exports.ED25519_TORSION_SUBGROUP = void 0;
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */

@@ -86,6 +86,6 @@ const sha512_1 = require("@noble/hashes/sha512");

const Fp = (0, modular_js_1.Field)(ED25519_P, undefined, true);
const ED25519_DEF = {
const ed25519Defaults = {
// Param: a
a: BigInt(-1),
// Equal to -121665/121666 over finite field.
// d is equal to -121665/121666 over finite field.
// Negative number is P - number, and division is invert(number, P)

@@ -95,3 +95,3 @@ d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'),

Fp,
// Subgroup order: how many points ed25519 has
// Subgroup order: how many points curve has
// 2n ** 252n + 27742317777372353535851937790883648493n;

@@ -112,3 +112,3 @@ n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'),

};
exports.ed25519 = (0, edwards_js_1.twistedEdwards)(ED25519_DEF);
exports.ed25519 = (0, edwards_js_1.twistedEdwards)(ed25519Defaults);
function ed25519_domain(data, ctx, phflag) {

@@ -119,7 +119,7 @@ if (ctx.length > 255)

}
exports.ed25519ctx = (0, edwards_js_1.twistedEdwards)({ ...ED25519_DEF, domain: ed25519_domain });
exports.ed25519ctx = (0, edwards_js_1.twistedEdwards)({ ...ed25519Defaults, domain: ed25519_domain });
exports.ed25519ph = (0, edwards_js_1.twistedEdwards)({
...ED25519_DEF,
...ed25519Defaults,
domain: ed25519_domain,
preHash: sha512_1.sha512,
prehash: sha512_1.sha512,
});

@@ -141,2 +141,16 @@ exports.x25519 = (0, montgomery_js_1.montgomery)({

});
/**
* Converts ed25519 public key to x25519 public key. Uses formula:
* * `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)`
* * `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))`
* @example
* const aPub = ed25519.getPublicKey(utils.randomPrivateKey());
* x25519.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub))
*/
function edwardsToMontgomery(edwardsPub) {
const { y } = exports.ed25519.ExtendedPoint.fromHex(edwardsPub);
const _1n = BigInt(1);
return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n)));
}
exports.edwardsToMontgomery = edwardsToMontgomery;
// Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator)

@@ -143,0 +157,0 @@ // NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since

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

export declare const x448: import("./abstract/montgomery.js").CurveFn;
/**
* Converts edwards448 public key to x448 public key. Uses formula:
* * `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)`
* * `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))`
* @example
* const aPub = ed448.getPublicKey(utils.randomPrivateKey());
* x448.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub))
*/
export declare function edwardsToMontgomery(edwardsPub: string | Uint8Array): Uint8Array;
declare const hashToCurve: (msg: Uint8Array, options?: htf.htfBasicOpts | undefined) => htf.H2CPoint<bigint>, encodeToCurve: (msg: Uint8Array, options?: htf.htfBasicOpts | undefined) => htf.H2CPoint<bigint>;
export { hashToCurve, encodeToCurve };
//# sourceMappingURL=ed448.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.encodeToCurve = exports.hashToCurve = exports.x448 = exports.ed448ph = exports.ed448 = void 0;
exports.encodeToCurve = exports.hashToCurve = exports.edwardsToMontgomery = exports.x448 = exports.ed448ph = exports.ed448 = void 0;
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */

@@ -104,3 +104,3 @@ const sha3_1 = require("@noble/hashes/sha3");

// NOTE: there is no ed448ctx, since ed448 supports ctx by default
exports.ed448ph = (0, edwards_js_1.twistedEdwards)({ ...ED448_DEF, preHash: shake256_64 });
exports.ed448ph = (0, edwards_js_1.twistedEdwards)({ ...ED448_DEF, prehash: shake256_64 });
exports.x448 = (0, montgomery_js_1.montgomery)({

@@ -120,17 +120,17 @@ a: BigInt(156326),

randomBytes: utils_1.randomBytes,
// The 4-isogeny maps between the Montgomery curve and this Edwards
// curve are:
// (u, v) = (y^2/x^2, (2 - x^2 - y^2)*y/x^3)
// (x, y) = (4*v*(u^2 - 1)/(u^4 - 2*u^2 + 4*v^2 + 1),
// -(u^5 - 2*u^3 - 4*u*v^2 + u)/
// (u^5 - 2*u^2*v^2 - 2*u^3 - 2*v^2 + u))
// xyToU: (p: PointType) => {
// const P = ed448P;
// const { x, y } = p;
// if (x === _0n) throw new Error(`Point with x=0 doesn't have mapping`);
// const invX = invert(x * x, P); // x^2
// const u = mod(y * y * invX, P); // (y^2/x^2)
// return numberToBytesLE(u, 56);
// },
});
/**
* Converts edwards448 public key to x448 public key. Uses formula:
* * `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)`
* * `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))`
* @example
* const aPub = ed448.getPublicKey(utils.randomPrivateKey());
* x448.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub))
*/
function edwardsToMontgomery(edwardsPub) {
const { y } = exports.ed448.ExtendedPoint.fromHex(edwardsPub);
const _1n = BigInt(1);
return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n)));
}
exports.edwardsToMontgomery = edwardsToMontgomery;
// Hash To Curve Elligator2 Map

@@ -137,0 +137,0 @@ const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4); // 1. c1 = (q - 3) / 4 # Integer arithmetic

@@ -5,6 +5,8 @@ import { hashToPrivateScalar } from './modular.js';

import { weierstrassPoints, } from './weierstrass.js';
// prettier-ignore
const _2n = BigInt(2), _3n = BigInt(3);
export function bls(CURVE) {
// Fields looks pretty specific for curve, so for now we need to pass them with opts
const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE;
const BLS_X_LEN = bitLen(CURVE.x);
// Fields are specific for curve, so for now we'll need to pass them with opts
const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE.fields;
const BLS_X_LEN = bitLen(CURVE.params.x);
const groupLen = 32; // TODO: calculate; hardcoded for now

@@ -24,14 +26,14 @@ // Pre-compute coefficients for sparse multiplication

let t1 = Fp2.sqr(Rz); // Rz²
let t2 = Fp2.multiplyByB(Fp2.mul(t1, 3n)); // 3 * T1 * B
let t3 = Fp2.mul(t2, 3n); // 3 * T2
let t2 = Fp2.multiplyByB(Fp2.mul(t1, _3n)); // 3 * T1 * B
let t3 = Fp2.mul(t2, _3n); // 3 * T2
let t4 = Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(Ry, Rz)), t1), t0); // (Ry + Rz)² - T1 - T0
ell_coeff.push([
Fp2.sub(t2, t0),
Fp2.mul(Fp2.sqr(Rx), 3n),
Fp2.mul(Fp2.sqr(Rx), _3n),
Fp2.neg(t4), // -T4
]);
Rx = Fp2.div(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), 2n); // ((T0 - T3) * Rx * Ry) / 2
Ry = Fp2.sub(Fp2.sqr(Fp2.div(Fp2.add(t0, t3), 2n)), Fp2.mul(Fp2.sqr(t2), 3n)); // ((T0 + T3) / 2)² - 3 * T2²
Rx = Fp2.div(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), _2n); // ((T0 - T3) * Rx * Ry) / 2
Ry = Fp2.sub(Fp2.sqr(Fp2.div(Fp2.add(t0, t3), _2n)), Fp2.mul(Fp2.sqr(t2), _3n)); // ((T0 + T3) / 2)² - 3 * T2²
Rz = Fp2.mul(t0, t4); // T0 * T4
if (bitGet(CURVE.x, i)) {
if (bitGet(CURVE.params.x, i)) {
// Addition

@@ -48,3 +50,3 @@ let t0 = Fp2.sub(Ry, Fp2.mul(Qy, Rz)); // Ry - Qy * Rz

let t4 = Fp2.mul(t2, Rx); // T2 * Rx
let t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, 2n)), Fp2.mul(Fp2.sqr(t0), Rz)); // T3 - 2 * T4 + T0² * Rz
let t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, _2n)), Fp2.mul(Fp2.sqr(t0), Rz)); // T3 - 2 * T4 + T0² * Rz
Rx = Fp2.mul(t1, t5); // T1 * T5

@@ -58,3 +60,3 @@ Ry = Fp2.sub(Fp2.mul(Fp2.sub(t4, t5), t0), Fp2.mul(t3, Ry)); // (T4 - T5) * T0 - T3 * Ry

function millerLoop(ell, g1) {
const { x } = CURVE;
const { x } = CURVE.params;
const Px = g1[0];

@@ -78,4 +80,5 @@ const Py = g1[1];

randomPrivateKey: () => {
return Fr.toBytes(hashToPrivateScalar(CURVE.randomBytes(groupLen + 8), CURVE.r));
return Fr.toBytes(hashToPrivateScalar(CURVE.randomBytes(groupLen + 8), CURVE.params.r));
},
calcPairingPrecomputes,
};

@@ -122,3 +125,3 @@ // Point on G1 curve: (x, y)

function normP2(point) {
return point instanceof G2.ProjectivePoint ? point : Signature.decode(point);
return point instanceof G2.ProjectivePoint ? point : Signature.fromHex(point);
}

@@ -141,3 +144,3 @@ function normP2Hash(point, htfOpts) {

return sigPoint;
return Signature.encode(sigPoint);
return Signature.toRawBytes(sigPoint);
}

@@ -179,3 +182,3 @@ // Checks if pairing of public key & hash is equal to pairing of generator & signature.

}
return Signature.encode(aggAffine);
return Signature.toRawBytes(aggAffine);
}

@@ -213,20 +216,26 @@ // https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407

return {
CURVE,
Fr,
Fp,
Fp2,
Fp6,
Fp12,
G1,
G2,
Signature,
millerLoop,
calcPairingPrecomputes,
pairing,
getPublicKey,
sign,
verify,
verifyBatch,
aggregatePublicKeys,
aggregateSignatures,
verifyBatch,
millerLoop,
pairing,
G1,
G2,
Signature,
fields: {
Fr,
Fp,
Fp2,
Fp6,
Fp12,
},
params: {
x: CURVE.params.x,
r: CURVE.params.r,
G1b: CURVE.G1.b,
G2b: CURVE.G2.b,
},
utils,

@@ -233,0 +242,0 @@ };

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

const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _8n = BigInt(8);
// verification rule is either zip215 or rfc8032 / nist186-5. Consult fromHex:
const VERIFY_DEFAULT = { zip215: true };
function validateOpts(curve) {

@@ -30,3 +32,3 @@ const opts = validateBasic(curve);

const CURVE = validateOpts(curveDef);
const { Fp, n: CURVE_ORDER, preHash, hash: cHash, randomBytes, nByteLength, h: cofactor } = CURVE;
const { Fp, n: CURVE_ORDER, prehash: prehash, hash: cHash, randomBytes, nByteLength, h: cofactor, } = CURVE;
const MASK = _2n ** BigInt(nByteLength * 8);

@@ -276,3 +278,3 @@ const modP = Fp.create; // Function overrides

// Uses algo from RFC8032 5.1.3.
static fromHex(hex, strict = true) {
static fromHex(hex, zip215 = false) {
const { d, a } = CURVE;

@@ -290,6 +292,6 @@ const len = Fp.BYTES;

// RFC8032 prohibits >= p, but ZIP215 doesn't
if (strict)
assertInRange(y, Fp.ORDER); // strict=true [1..P-1] (2^255-19-1 for ed25519)
if (zip215)
assertInRange(y, MASK); // zip215=true [1..P-1] (2^255-19-1 for ed25519)
else
assertInRange(y, MASK); // strict=false [1..MASK-1] (2^256-1 for ed25519)
assertInRange(y, Fp.ORDER); // zip215=false [1..MASK-1] (2^256-1 for ed25519)
}

@@ -355,13 +357,13 @@ // Ed25519: x² = (y²-1)/(dy²+1) mod p. Ed448: x² = (y²-1)/(dy²-1) mod p. Generic case:

const msg = ut.concatBytes(...msgs);
return modN_LE(cHash(domain(msg, ensureBytes('context', context), !!preHash)));
return modN_LE(cHash(domain(msg, ensureBytes('context', context), !!prehash)));
}
/** Signs message with privateKey. RFC8032 5.1.6 */
function sign(msg, privKey, context) {
function sign(msg, privKey, options = {}) {
msg = ensureBytes('message', msg);
if (preHash)
msg = preHash(msg); // for ed25519ph etc.
if (prehash)
msg = prehash(msg); // for ed25519ph etc.
const { prefix, scalar, pointBytes } = getExtendedPublicKey(privKey);
const r = hashDomainToScalar(context, prefix, msg); // r = dom2(F, C) || prefix || PH(M)
const r = hashDomainToScalar(options.context, prefix, msg); // r = dom2(F, C) || prefix || PH(M)
const R = G.multiply(r).toRawBytes(); // R = rG
const k = hashDomainToScalar(context, R, pointBytes, msg); // R || A || PH(M)
const k = hashDomainToScalar(options.context, R, pointBytes, msg); // R || A || PH(M)
const s = modN(r + k * scalar); // S = (r + k * s) mod L

@@ -372,12 +374,22 @@ assertGE0(s); // 0 <= s < l

}
function verify(sig, msg, publicKey, context) {
const verifyOpts = VERIFY_DEFAULT;
function verify(sig, msg, publicKey, options = verifyOpts) {
const { context, zip215 } = options;
const len = Fp.BYTES; // Verifies EdDSA signature against message and public key. RFC8032 5.1.7.
sig = ensureBytes('signature', sig, 2 * len); // An extended group equation is checked.
msg = ensureBytes('message', msg); // ZIP215 compliant, which means not fully RFC8032 compliant.
if (preHash)
msg = preHash(msg); // for ed25519ph, etc
const A = Point.fromHex(publicKey, false); // Check for s bounds, hex validity
const R = Point.fromHex(sig.slice(0, len), false); // 0 <= R < 2^256: ZIP215 R can be >= P
msg = ensureBytes('message', msg);
if (prehash)
msg = prehash(msg); // for ed25519ph, etc
const s = ut.bytesToNumberLE(sig.slice(len, 2 * len));
const SB = G.multiplyUnsafe(s); // 0 <= s < l is done inside
// zip215: true is good for consensus-critical apps and allows points < 2^256
// zip215: false follows RFC8032 / NIST186-5 and restricts points to CURVE.p
let A, R, SB;
try {
A = Point.fromHex(publicKey, zip215);
R = Point.fromHex(sig.slice(0, len), zip215);
SB = G.multiplyUnsafe(s); // 0 <= s < l is done inside
}
catch (error) {
return false;
}
const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg);

@@ -384,0 +396,0 @@ const RkA = R.add(A.multiplyUnsafe(k));

@@ -115,7 +115,8 @@ import { mod } from './modular.js';

}
else if (expand === undefined) {
else if (expand === '_internal_pass') {
// for internal tests only
prb = msg;
}
else {
throw new Error('expand must be "xmd", "xof" or undefined');
throw new Error('expand must be "xmd" or "xof"');
}

@@ -122,0 +123,0 @@ const u = new Array(count);

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

let len;
for (len = 0; n > 0n; n >>= _1n, len += 1)
for (len = 0; n > _0n; n >>= _1n, len += 1)
;

@@ -118,3 +118,3 @@ return len;

// Same as !!+Array.from(n.toString(2)).reverse()[pos]
export const bitGet = (n, pos) => (n >> BigInt(pos)) & 1n;
export const bitGet = (n, pos) => (n >> BigInt(pos)) & _1n;
// Sets single bit at position

@@ -121,0 +121,0 @@ export const bitSet = (n, pos, value) => n | ((value ? _1n : _0n) << BigInt(pos));

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

const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut;
const DER = {
export const DER = {
// asn.1 DER encoding utils

@@ -52,5 +52,10 @@ Err: class DERErr extends Error {

throw new E('Invalid signature integer: wrong length');
if (res[0] === 0x00 && res[1] <= 0x7f)
throw new E('Invalid signature integer: trailing length');
// ^ Weird condition: not about length, but about first bytes of number.
// https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag,
// since we always use positive integers here. It must always be empty:
// - add zero byte if exists
// - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding)
if (res[0] & 0b10000000)
throw new E('Invalid signature integer: negative');
if (res[0] === 0x00 && !(res[1] & 0b10000000))
throw new E('Invalid signature integer: unnecessary leading zero');
return { d: b2n(res), l: data.subarray(len + 2) }; // d is data, l is left

@@ -76,3 +81,4 @@ },

hexFromSig(sig) {
const slice = (s) => (Number.parseInt(s[0], 16) >= 8 ? '00' + s : s); // slice DER
// Add leading zero if first byte has negative bit enabled. More details in '_parseInt'
const slice = (s) => (Number.parseInt(s[0], 16) & 0b1000 ? '00' + s : s);
const h = (num) => {

@@ -121,2 +127,8 @@ const hex = num.toString(16);

}
// Validate whether the passed curve params are valid.
// We check if curve equation works for generator point.
// `assertValidity()` won't work: `isTorsionFree()` is not available at this point in bls12-381.
// ProjectivePoint class has not been initialized yet.
if (!Fp.eql(Fp.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx)))
throw new Error('bad generator point: equation left != right');
// Valid group elements reside in range 1..n-1

@@ -505,2 +517,3 @@ function isWithinCurveOrder(num) {

const wnaf = wNAF(Point, CURVE.endo ? Math.ceil(_bits / 2) : _bits);
// Validate if generator point is on curve
return {

@@ -956,3 +969,3 @@ CURVE,

// 17. for i in (c1, c1 - 1, ..., 2):
for (let i = c1; i > 1; i--) {
for (let i = c1; i > _1n; i--) {
let tv5 = _2n ** (i - _2n); // 18. tv5 = i - 2; 19. tv5 = 2^tv5

@@ -959,0 +972,0 @@ let tvv5 = Fp.pow(tv4, tv5); // 20. tv5 = tv4^tv5

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

// Compatible with Algorand, Chia, Dfinity, Ethereum, FIL, Zcash. Matches specs
// [pairing-curves-10](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-10),
// [pairing-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11),
// [bls-sigs-04](https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04),

@@ -30,19 +30,2 @@ // [hash-to-curve-12](https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-12).

// so ensure to reverse byte order if you'll use it with FIL.
//
// ### Resources
// - [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:
// [part 1](https://research.nccgroup.com/2020/07/06/pairing-over-bls12-381-part-1-fields/),
// [part 2](https://research.nccgroup.com/2020/07/13/pairing-over-bls12-381-part-2-curves/),
// [part 3](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/)
//
// ### Differences from @noble/bls12-381 1.4
// - PointG1 -> G1.Point
// - PointG2 -> G2.Point
// - PointG2.fromSignature -> Signature.decode
// - PointG2.toSignature -> Signature.encode
// - Fixed Fp2 ORDER
// - Points now have only two coordinates
import { sha256 } from '@noble/hashes/sha256';

@@ -52,3 +35,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, } from './abstract/utils.js';
import { concatBytes as concatB, ensureBytes, numberToBytesBE, bytesToNumberBE, bitLen, bitSet, bitGet, bitMask, bytesToHex, } from './abstract/utils.js';
// Types

@@ -60,2 +43,3 @@ import { mapToCurveSimpleSWU, } from './abstract/weierstrass.js';

const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);
// prettier-ignore
const _8n = BigInt(8), _16n = BigInt(16);

@@ -799,5 +783,5 @@ // CURVE FIELDS

const G2_SWU = mapToCurveSimpleSWU(Fp2, {
A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(240n) }),
B: Fp2.create({ c0: Fp.create(1012n), c1: Fp.create(1012n) }),
Z: Fp2.create({ c0: Fp.create(-2n), c1: Fp.create(-1n) }), // Z: -(2 + I)
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)) }),
Z: Fp2.create({ c0: Fp.create(BigInt(-2)), c1: Fp.create(BigInt(-1)) }), // Z: -(2 + I)
});

@@ -808,3 +792,3 @@ // Optimized SWU Map - Fp to G1

B: Fp.create(BigInt('0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0')),
Z: Fp.create(11n),
Z: Fp.create(BigInt(11)),
});

@@ -879,3 +863,18 @@ // Endomorphisms (for fast cofactor clearing)

// 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 = Fp.toBytes(bitSet(bitSet(_0n, I_BIT_POS, true), S_BIT_POS, true)); // set compressed & point-at-infinity bits
function signatureG2ToRawBytes(point) {
// NOTE: by some reasons it was missed in bls12-381, looks like bug
point.assertValidity();
const len = Fp.BYTES;
if (point.equals(bls12_381.G2.ProjectivePoint.ZERO))
return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len));
const { x, y } = point.toAffine();
const { re: x0, im: x1 } = Fp2.reim(x);
const { re: y0, im: y1 } = Fp2.reim(y);
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 z2 = x0;
return concatB(numberToBytesBE(z1, len), numberToBytesBE(z2, len));
}
// To verify curve parameters, see pairing-friendly-curves spec:

@@ -893,9 +892,9 @@ // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-09

// Fields
Fr,
Fp,
Fp2,
Fp6,
Fp12,
// order; z⁴ − z² + 1
r: Fr.ORDER,
fields: {
Fp,
Fp2,
Fp6,
Fp12,
Fr,
},
// G1 is the order-q subgroup of E1(Fp) : y² = x³ + 4, #E1(Fp) = h1q, where

@@ -926,4 +925,4 @@ // characteristic; z + (z⁴ - z² + 1)(z - 1)²/3

// todo: unroll
const xP = point.multiplyUnsafe(bls12_381.CURVE.x).negate(); // [x]P
const u2P = xP.multiplyUnsafe(bls12_381.CURVE.x); // [u2]P
const xP = point.multiplyUnsafe(bls12_381.params.x).negate(); // [x]P
const u2P = xP.multiplyUnsafe(bls12_381.params.x); // [u2]P
return u2P.equals(phi);

@@ -946,3 +945,3 @@ // https://eprint.iacr.org/2019/814.pdf

// return this.multiplyUnsafe(CURVE.h);
return point.multiplyUnsafe(bls12_381.CURVE.x).add(point); // x*P + P
return point.multiplyUnsafe(bls12_381.params.x).add(point); // x*P + P
},

@@ -954,3 +953,5 @@ mapToCurve: (scalars) => {

fromBytes: (bytes) => {
bytes = bytes.slice();
if (bytes.length === 48) {
// TODO: Fp.bytes
const P = Fp.ORDER;

@@ -963,3 +964,3 @@ const compressedValue = bytesToNumberBE(bytes);

const x = Fp.create(compressedValue & Fp.MASK);
const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.CURVE.G1.b)); // y² = x³ + b
const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)); // y² = x³ + b
let y = Fp.sqrt(right);

@@ -977,4 +978,4 @@ if (!y)

return bls12_381.G1.ProjectivePoint.ZERO.toAffine();
const x = bytesToNumberBE(bytes.slice(0, Fp.BYTES));
const y = bytesToNumberBE(bytes.slice(Fp.BYTES));
const x = bytesToNumberBE(bytes.subarray(0, Fp.BYTES));
const y = bytesToNumberBE(bytes.subarray(Fp.BYTES));
return { x: Fp.create(x), y: Fp.create(y) };

@@ -1044,3 +1045,3 @@ }

isTorsionFree: (c, P) => {
return P.multiplyUnsafe(bls12_381.CURVE.x).negate().equals(G2psi(c, P)); // ψ(P) == [u](P)
return P.multiplyUnsafe(bls12_381.params.x).negate().equals(G2psi(c, P)); // ψ(P) == [u](P)
// Older version: https://eprint.iacr.org/2019/814.pdf

@@ -1055,3 +1056,3 @@ // Ψ²(P) => Ψ³(P) => [z]Ψ³(P) where z = -x => [z]Ψ³(P) - Ψ²(P) + P == O

clearCofactor: (c, P) => {
const { x } = bls12_381.CURVE;
const x = bls12_381.params.x;
let t1 = P.multiplyUnsafe(x).negate(); // [-x]P

@@ -1070,2 +1071,3 @@ let t2 = G2psi(c, P); // Ψ(P)

fromBytes: (bytes) => {
bytes = bytes.slice();
const m_byte = bytes[0] & 0xe0;

@@ -1081,3 +1083,3 @@ if (m_byte === 0x20 || m_byte === 0x60 || m_byte === 0xe0) {

if (bytes.length === 96 && bitC) {
const { b } = bls12_381.CURVE.G2;
const b = bls12_381.params.G2b;
const P = Fp.ORDER;

@@ -1117,8 +1119,8 @@ bytes[0] = bytes[0] & 0x1f; // clear flags

toBytes: (c, point, isCompressed) => {
const { BYTES: len, ORDER: P } = Fp;
const isZero = point.equals(c.ZERO);
const { x, y } = point.toAffine();
if (isCompressed) {
const P = Fp.ORDER;
if (isZero)
return concatB(COMPRESSED_ZERO, numberToBytesBE(0n, Fp.BYTES));
return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len));
const flag = Boolean(y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P);

@@ -1128,10 +1130,10 @@ // set compressed & sign bits (looks like different offsets than for G1/Fp?)

x_1 = bitSet(x_1, S_BIT_POS, true);
return concatB(numberToBytesBE(x_1, Fp.BYTES), numberToBytesBE(x.c0, Fp.BYTES));
return concatB(numberToBytesBE(x_1, len), numberToBytesBE(x.c0, len));
}
else {
if (isZero)
return concatB(new Uint8Array([0x40]), new Uint8Array(4 * Fp.BYTES - 1)); // bytes[0] |= 1 << 6;
return concatB(new Uint8Array([0x40]), new Uint8Array(4 * len - 1)); // bytes[0] |= 1 << 6;
const { re: x0, im: x1 } = Fp2.reim(x);
const { re: y0, im: y1 } = Fp2.reim(y);
return concatB(numberToBytesBE(x1, Fp.BYTES), numberToBytesBE(x0, Fp.BYTES), numberToBytesBE(y1, Fp.BYTES), numberToBytesBE(y0, Fp.BYTES));
return concatB(numberToBytesBE(x1, len), numberToBytesBE(x0, len), numberToBytesBE(y1, len), numberToBytesBE(y0, len));
}

@@ -1141,3 +1143,3 @@ },

// TODO: Optimize, it's very slow because of sqrt.
decode(hex) {
fromHex(hex) {
hex = ensureBytes('signatureHex', hex);

@@ -1157,3 +1159,3 @@ const P = Fp.ORDER;

const x = Fp2.create({ c0: x2, c1: x1 });
const y2 = Fp2.add(Fp2.pow(x, _3n), bls12_381.CURVE.G2.b); // y² = x³ + 4
const y2 = Fp2.add(Fp2.pow(x, _3n), bls12_381.params.G2b); // y² = x³ + 4
// The slow part

@@ -1175,20 +1177,14 @@ let y = Fp2.sqrt(y2);

},
encode(point) {
// NOTE: by some reasons it was missed in bls12-381, looks like bug
point.assertValidity();
if (point.equals(bls12_381.G2.ProjectivePoint.ZERO))
return concatB(COMPRESSED_ZERO, numberToBytesBE(0n, Fp.BYTES));
const a = point.toAffine();
const { re: x0, im: x1 } = Fp2.reim(a.x);
const { re: y0, im: y1 } = Fp2.reim(a.y);
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 z2 = x0;
return concatB(numberToBytesBE(z1, Fp.BYTES), numberToBytesBE(z2, Fp.BYTES));
toRawBytes(point) {
return signatureG2ToRawBytes(point);
},
toHex(point) {
return bytesToHex(signatureG2ToRawBytes(point));
},
},
},
// The BLS parameter x for BLS12-381
x: BLS_X,
params: {
x: BLS_X,
r: Fr.ORDER, // order; z⁴ − z² + 1; CURVE.n from other curves
},
htfDefaults,

@@ -1195,0 +1191,0 @@ hash: sha256,

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

const Fp = Field(ED25519_P, undefined, true);
const ED25519_DEF = {
const ed25519Defaults = {
// Param: a
a: BigInt(-1),
// Equal to -121665/121666 over finite field.
// d is equal to -121665/121666 over finite field.
// Negative number is P - number, and division is invert(number, P)

@@ -92,3 +92,3 @@ d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'),

Fp,
// Subgroup order: how many points ed25519 has
// Subgroup order: how many points curve has
// 2n ** 252n + 27742317777372353535851937790883648493n;

@@ -109,3 +109,3 @@ n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'),

};
export const ed25519 = twistedEdwards(ED25519_DEF);
export const ed25519 = twistedEdwards(ed25519Defaults);
function ed25519_domain(data, ctx, phflag) {

@@ -116,7 +116,7 @@ if (ctx.length > 255)

}
export const ed25519ctx = twistedEdwards({ ...ED25519_DEF, domain: ed25519_domain });
export const ed25519ctx = twistedEdwards({ ...ed25519Defaults, domain: ed25519_domain });
export const ed25519ph = twistedEdwards({
...ED25519_DEF,
...ed25519Defaults,
domain: ed25519_domain,
preHash: sha512,
prehash: sha512,
});

@@ -138,2 +138,15 @@ export const x25519 = montgomery({

});
/**
* Converts ed25519 public key to x25519 public key. Uses formula:
* * `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)`
* * `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))`
* @example
* const aPub = ed25519.getPublicKey(utils.randomPrivateKey());
* x25519.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub))
*/
export function edwardsToMontgomery(edwardsPub) {
const { y } = ed25519.ExtendedPoint.fromHex(edwardsPub);
const _1n = BigInt(1);
return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n)));
}
// Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator)

@@ -140,0 +153,0 @@ // NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since

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

// NOTE: there is no ed448ctx, since ed448 supports ctx by default
export const ed448ph = twistedEdwards({ ...ED448_DEF, preHash: shake256_64 });
export const ed448ph = twistedEdwards({ ...ED448_DEF, prehash: shake256_64 });
export const x448 = montgomery({

@@ -117,17 +117,16 @@ a: BigInt(156326),

randomBytes,
// The 4-isogeny maps between the Montgomery curve and this Edwards
// curve are:
// (u, v) = (y^2/x^2, (2 - x^2 - y^2)*y/x^3)
// (x, y) = (4*v*(u^2 - 1)/(u^4 - 2*u^2 + 4*v^2 + 1),
// -(u^5 - 2*u^3 - 4*u*v^2 + u)/
// (u^5 - 2*u^2*v^2 - 2*u^3 - 2*v^2 + u))
// xyToU: (p: PointType) => {
// const P = ed448P;
// const { x, y } = p;
// if (x === _0n) throw new Error(`Point with x=0 doesn't have mapping`);
// const invX = invert(x * x, P); // x^2
// const u = mod(y * y * invX, P); // (y^2/x^2)
// return numberToBytesLE(u, 56);
// },
});
/**
* Converts edwards448 public key to x448 public key. Uses formula:
* * `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)`
* * `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))`
* @example
* const aPub = ed448.getPublicKey(utils.randomPrivateKey());
* x448.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub))
*/
export function edwardsToMontgomery(edwardsPub) {
const { y } = ed448.ExtendedPoint.fromHex(edwardsPub);
const _1n = BigInt(1);
return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n)));
}
// Hash To Curve Elligator2 Map

@@ -134,0 +133,0 @@ const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4); // 1. c1 = (q - 3) / 4 # Integer arithmetic

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

import * as htf from './abstract/hash-to-curve.js';
// NIST secp256r1 aka P256
// NIST secp256r1 aka p256
// https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-256
// Field over which we'll do calculations; 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n
const Fp = Field(BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff'));

@@ -19,4 +18,4 @@ const CURVE_A = Fp.create(BigInt('-3'));

});
export const P256 = createCurve({
// Params: a, b
// prettier-ignore
export const p256 = createCurve({
a: CURVE_A,

@@ -27,3 +26,3 @@ b: CURVE_B,

n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'),
// Base point (x, y) aka generator point
// Base (generator) point (x, y)
Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'),

@@ -34,3 +33,3 @@ Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'),

}, sha256);
export const secp256r1 = P256;
export const secp256r1 = p256;
const { hashToCurve, encodeToCurve } = htf.createHasher(secp256r1.ProjectivePoint, (scalars) => mapSWU(scalars[0]), {

@@ -37,0 +36,0 @@ DST: 'P256_XMD:SHA-256_SSWU_RO_',

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

import * as htf from './abstract/hash-to-curve.js';
// NIST secp384r1 aka P384
// NIST secp384r1 aka p384
// https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-384
// Field over which we'll do calculations. 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n
// Field over which we'll do calculations.
// prettier-ignore

@@ -17,17 +17,10 @@ const P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff');

const CURVE_B = BigInt('0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef');
const mapSWU = mapToCurveSimpleSWU(Fp, {
A: CURVE_A,
B: CURVE_B,
Z: Fp.create(BigInt('-12')),
});
// prettier-ignore
export const P384 = createCurve({
// Params: a, b
export const p384 = createCurve({
a: CURVE_A,
b: CURVE_B,
// Field over which we'll do calculations. 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n
Fp,
// Curve order, total count of valid points in the field.
n: BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973'),
// Base point (x, y) aka generator point
// Base (generator) point (x, y)
Gx: BigInt('0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7'),

@@ -38,3 +31,8 @@ Gy: BigInt('0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f'),

}, sha384);
export const secp384r1 = P384;
export const secp384r1 = p384;
const mapSWU = mapToCurveSimpleSWU(Fp, {
A: CURVE_A,
B: CURVE_B,
Z: Fp.create(BigInt('-12')),
});
const { hashToCurve, encodeToCurve } = htf.createHasher(secp384r1.ProjectivePoint, (scalars) => mapSWU(scalars[0]), {

@@ -41,0 +39,0 @@ DST: 'P384_XMD:SHA-384_SSWU_RO_',

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

import * as htf from './abstract/hash-to-curve.js';
// NIST secp521r1 aka P521
// NIST secp521r1 aka p521
// Note that it's 521, which differs from 512 of its hash function.
// https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-521
// Field over which we'll do calculations; 2n**521n - 1n
// Field over which we'll do calculations.
// prettier-ignore
const P = BigInt('0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
const Fp = Field(P);
const CURVE_A = Fp.create(BigInt('-3'));
// prettier-ignore
const CURVE_B = BigInt('0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00');
const mapSWU = mapToCurveSimpleSWU(Fp, {
A: CURVE_A,
B: CURVE_B,
Z: Fp.create(BigInt('-4')),
});
// prettier-ignore
export const P521 = createCurve({
// Params: a, b
a: CURVE_A,
b: CURVE_B,
const CURVE = {
a: Fp.create(BigInt('-3')),
b: BigInt('0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00'),
Fp,
// Curve order, total count of valid points in the field
n: BigInt('0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409'),
// Base point (x, y) aka generator point
Gx: BigInt('0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66'),
Gy: BigInt('0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650'),
h: BigInt(1),
};
// prettier-ignore
export const p521 = createCurve({
a: CURVE.a,
b: CURVE.b,
Fp,
// Curve order, total count of valid points in the field
n: CURVE.n,
Gx: CURVE.Gx,
Gy: CURVE.Gy,
h: CURVE.h,
lowS: false,
allowedPrivateKeyLengths: [130, 131, 132] // P521 keys are variable-length. Normalize to 132b
}, sha512);
export const secp521r1 = P521;
export const secp521r1 = p521;
const mapSWU = mapToCurveSimpleSWU(Fp, {
A: CURVE.a,
B: CURVE.b,
Z: Fp.create(BigInt('-4')),
});
const { hashToCurve, encodeToCurve } = htf.createHasher(secp521r1.ProjectivePoint, (scalars) => mapSWU(scalars[0]), {

@@ -40,0 +44,0 @@ DST: 'P521_XMD:SHA-512_SSWU_RO_',

import * as htf from './abstract/hash-to-curve.js';
export declare const P256: Readonly<{
export declare const p256: Readonly<{
create: (hash: import("./abstract/utils.js").CHash) => import("./abstract/weierstrass.js").CurveFn;

@@ -4,0 +4,0 @@ CURVE: Readonly<{

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.encodeToCurve = exports.hashToCurve = exports.secp256r1 = exports.P256 = void 0;
exports.encodeToCurve = exports.hashToCurve = exports.secp256r1 = exports.p256 = void 0;
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */

@@ -10,5 +10,4 @@ const _shortw_utils_js_1 = require("./_shortw_utils.js");

const htf = require("./abstract/hash-to-curve.js");
// NIST secp256r1 aka P256
// NIST secp256r1 aka p256
// https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-256
// Field over which we'll do calculations; 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n
const Fp = (0, modular_js_1.Field)(BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff'));

@@ -22,4 +21,4 @@ const CURVE_A = Fp.create(BigInt('-3'));

});
exports.P256 = (0, _shortw_utils_js_1.createCurve)({
// Params: a, b
// prettier-ignore
exports.p256 = (0, _shortw_utils_js_1.createCurve)({
a: CURVE_A,

@@ -30,3 +29,3 @@ b: CURVE_B,

n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'),
// Base point (x, y) aka generator point
// Base (generator) point (x, y)
Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'),

@@ -37,3 +36,3 @@ Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'),

}, sha256_1.sha256);
exports.secp256r1 = exports.P256;
exports.secp256r1 = exports.p256;
const { hashToCurve, encodeToCurve } = htf.createHasher(exports.secp256r1.ProjectivePoint, (scalars) => mapSWU(scalars[0]), {

@@ -40,0 +39,0 @@ DST: 'P256_XMD:SHA-256_SSWU_RO_',

import * as htf from './abstract/hash-to-curve.js';
export declare const P384: Readonly<{
export declare const p384: Readonly<{
create: (hash: import("./abstract/utils.js").CHash) => import("./abstract/weierstrass.js").CurveFn;

@@ -4,0 +4,0 @@ CURVE: Readonly<{

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.encodeToCurve = exports.hashToCurve = exports.secp384r1 = exports.P384 = void 0;
exports.encodeToCurve = exports.hashToCurve = exports.secp384r1 = exports.p384 = void 0;
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */

@@ -10,5 +10,5 @@ const _shortw_utils_js_1 = require("./_shortw_utils.js");

const htf = require("./abstract/hash-to-curve.js");
// NIST secp384r1 aka P384
// NIST secp384r1 aka p384
// https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-384
// Field over which we'll do calculations. 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n
// Field over which we'll do calculations.
// prettier-ignore

@@ -20,17 +20,10 @@ const P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff');

const CURVE_B = BigInt('0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef');
const mapSWU = (0, weierstrass_js_1.mapToCurveSimpleSWU)(Fp, {
A: CURVE_A,
B: CURVE_B,
Z: Fp.create(BigInt('-12')),
});
// prettier-ignore
exports.P384 = (0, _shortw_utils_js_1.createCurve)({
// Params: a, b
exports.p384 = (0, _shortw_utils_js_1.createCurve)({
a: CURVE_A,
b: CURVE_B,
// Field over which we'll do calculations. 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n
Fp,
// Curve order, total count of valid points in the field.
n: BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973'),
// Base point (x, y) aka generator point
// Base (generator) point (x, y)
Gx: BigInt('0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7'),

@@ -41,3 +34,8 @@ Gy: BigInt('0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f'),

}, sha512_1.sha384);
exports.secp384r1 = exports.P384;
exports.secp384r1 = exports.p384;
const mapSWU = (0, weierstrass_js_1.mapToCurveSimpleSWU)(Fp, {
A: CURVE_A,
B: CURVE_B,
Z: Fp.create(BigInt('-12')),
});
const { hashToCurve, encodeToCurve } = htf.createHasher(exports.secp384r1.ProjectivePoint, (scalars) => mapSWU(scalars[0]), {

@@ -44,0 +42,0 @@ DST: 'P384_XMD:SHA-384_SSWU_RO_',

import * as htf from './abstract/hash-to-curve.js';
export declare const P521: Readonly<{
export declare const p521: Readonly<{
create: (hash: import("./abstract/utils.js").CHash) => import("./abstract/weierstrass.js").CurveFn;

@@ -4,0 +4,0 @@ CURVE: Readonly<{

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.encodeToCurve = exports.hashToCurve = exports.secp521r1 = exports.P521 = void 0;
exports.encodeToCurve = exports.hashToCurve = exports.secp521r1 = exports.p521 = void 0;
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */

@@ -10,33 +10,37 @@ const _shortw_utils_js_1 = require("./_shortw_utils.js");

const htf = require("./abstract/hash-to-curve.js");
// NIST secp521r1 aka P521
// NIST secp521r1 aka p521
// Note that it's 521, which differs from 512 of its hash function.
// https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-521
// Field over which we'll do calculations; 2n**521n - 1n
// Field over which we'll do calculations.
// prettier-ignore
const P = BigInt('0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
const Fp = (0, modular_js_1.Field)(P);
const CURVE_A = Fp.create(BigInt('-3'));
// prettier-ignore
const CURVE_B = BigInt('0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00');
const mapSWU = (0, weierstrass_js_1.mapToCurveSimpleSWU)(Fp, {
A: CURVE_A,
B: CURVE_B,
Z: Fp.create(BigInt('-4')),
});
// prettier-ignore
exports.P521 = (0, _shortw_utils_js_1.createCurve)({
// Params: a, b
a: CURVE_A,
b: CURVE_B,
const CURVE = {
a: Fp.create(BigInt('-3')),
b: BigInt('0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00'),
Fp,
// Curve order, total count of valid points in the field
n: BigInt('0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409'),
// Base point (x, y) aka generator point
Gx: BigInt('0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66'),
Gy: BigInt('0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650'),
h: BigInt(1),
};
// prettier-ignore
exports.p521 = (0, _shortw_utils_js_1.createCurve)({
a: CURVE.a,
b: CURVE.b,
Fp,
// Curve order, total count of valid points in the field
n: CURVE.n,
Gx: CURVE.Gx,
Gy: CURVE.Gy,
h: CURVE.h,
lowS: false,
allowedPrivateKeyLengths: [130, 131, 132] // P521 keys are variable-length. Normalize to 132b
}, sha512_1.sha512);
exports.secp521r1 = exports.P521;
exports.secp521r1 = exports.p521;
const mapSWU = (0, weierstrass_js_1.mapToCurveSimpleSWU)(Fp, {
A: CURVE.a,
B: CURVE.b,
Z: Fp.create(BigInt('-4')),
});
const { hashToCurve, encodeToCurve } = htf.createHasher(exports.secp521r1.ProjectivePoint, (scalars) => mapSWU(scalars[0]), {

@@ -43,0 +47,0 @@ DST: 'P521_XMD:SHA-512_SSWU_RO_',

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

@@ -34,5 +34,2 @@ "files": [

"devDependencies": {
"@scure/bip32": "~1.2.0",
"@scure/bip39": "~1.2.0",
"@types/node": "18.11.18",
"fast-check": "3.0.0",

@@ -106,6 +103,6 @@ "micro-bmark": "0.3.1",

},
"./bn": {
"types": "./bn.d.ts",
"import": "./esm/bn.js",
"default": "./bn.js"
"./bn254": {
"types": "./bn254.d.ts",
"import": "./esm/bn254.js",
"default": "./bn254.js"
},

@@ -112,0 +109,0 @@ "./ed25519": {

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

- Short Weierstrass, Edwards, Montgomery curves
- ECDSA, EdDSA, Schnorr, BLS signature schemes, ECDH key agreement
- 🔒 [**Audited**](#security) by an independent security firm
- #️⃣ [hash to curve](#abstracthash-to-curve-hashing-strings-to-curve-points)
- 🔻 Tree-shaking-friendly: use only what's necessary, other code won't be included
- 🏎 Ultra-fast, hand-optimized for caveats of JS engines
- 🔍 Unique tests ensure correctness: property-based, cross-library and Wycheproof vectors, fuzzing
- ➰ Short Weierstrass, Edwards, Montgomery curves
- ✍️ ECDSA, EdDSA, Schnorr, BLS signature schemes, ECDH key agreement
- #️⃣ Hash-to-curve
for encoding or hashing an arbitrary string to an elliptic curve point
- 🧜‍♂️ [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash
- 🏎 [Ultra-fast](#speed), hand-optimized for caveats of JS engines
- 🔍 Unique tests ensure correctness with Wycheproof vectors and
[cryptofuzz](https://github.com/guidovranken/cryptofuzz) differential fuzzing
- 🔻 Tree-shaking-friendly: use only what's necessary, other code won't be included
- 🧜‍♂️ Poseidon ZK-friendly hash
Check out [Upgrading](#upgrading) if you've previously used single-feature noble
packages ([secp256k1](https://github.com/paulmillr/noble-secp256k1),
[ed25519](https://github.com/paulmillr/noble-ed25519)).
See [Resources](#resources) for articles and real-world software that uses curves.
packages. See [Resources](#resources) for articles and real-world software that uses curves.

@@ -47,4 +44,4 @@ ### This library belongs to _noble_ crypto

The library is tree-shaking-friendly and does not expose root entry point as
`import * from '@noble/curves'`. Instead, you need to import specific primitives.
The library is tree-shaking-friendly and does NOT expose root entry point as
`import c from '@noble/curves'`. Instead, you need to import specific primitives.
This is done to ensure small size of your apps.

@@ -54,12 +51,15 @@

1. [Implementations](#implementations), utilizing one dependency `@noble/hashes`,
1. [Implementations](#implementations), utilizing one dependency [noble-hashes](https://github.com/paulmillr/noble-hashes),
providing ready-to-use:
- NIST curves secp256r1/P256, secp384r1/P384, secp521r1/P521
- NIST curves secp256r1 / p256, secp384r1 / p384, secp521r1 / p521
- SECG curve secp256k1
- ed25519/curve25519/x25519/ristretto255, edwards448/curve448/x448
- ed25519 / curve25519 / x25519 / ristretto255,
edwards448 / curve448 / x448
implementing
[RFC7748](https://www.rfc-editor.org/rfc/rfc7748) /
[RFC8032](https://www.rfc-editor.org/rfc/rfc8032) /
[FIPS 186-5](https://csrc.nist.gov/publications/detail/fips/186/5/final) /
[ZIP215](https://zips.z.cash/zip-0215) standards
- pairing-friendly curves bls12-381, bn254
- [pasta](https://electriccoin.co/blog/the-pasta-curves-for-halo-2-and-beyond/) curves
2. [Abstract](#abstract-api), zero-dependency EC algorithms

@@ -78,3 +78,3 @@

const sig = secp256k1.sign(msg, priv);
secp256k1.verify(sig, msg, pub) === true;
const isValid = secp256k1.verify(sig, msg, pub) === true;

@@ -97,7 +97,7 @@ // hex strings are also supported besides Uint8Arrays:

import { bls12_381 } from '@noble/curves/bls12-381';
import { bn254 } from '@noble/curves/bn';
import { bn254 } from '@noble/curves/bn254';
import { jubjub } from '@noble/curves/jubjub';
```
Weierstrass curves feature recovering public keys from signatures and ECDH key agreement:
Recovering public keys from weierstrass ECDSA signatures; using ECDH:

@@ -112,3 +112,3 @@ ```ts

secp256k1 has schnorr signature implementation which follows
Schnorr signatures over secp256k1 following
[BIP340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki):

@@ -127,6 +127,15 @@

x25519 ECDH and [ristretto255](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448).
It follows [ZIP215](https://zips.z.cash/zip-0215) and [can be used in consensus-critical applications](https://hdevalence.ca/blog/2020-10-04-its-25519am):
Default `verify` behavior follows [ZIP215](https://zips.z.cash/zip-0215) and
[can be used in consensus-critical applications](https://hdevalence.ca/blog/2020-10-04-its-25519am).
`zip215: false` option switches verification criteria to RFC8032 / FIPS 186-5.
```ts
import { ed25519 } from '@noble/curves/ed25519';
const priv = ed25519.utils.randomPrivateKey();
const pub = ed25519.getPublicKey(priv);
const msg = new TextEncoder().encode('hello');
const sig = ed25519.sign(msg, priv);
ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215
ed25519.verify(sig, msg, pub, { zip215: false }); // RFC8032 / FIPS 186-5

@@ -162,3 +171,3 @@ // Variants from RFC8032: with context, prehashed

Every curve has params:
Every curve has `CURVE` object that contains its parameters, field, and others:

@@ -170,42 +179,2 @@ ```ts

BLS12-381 pairing-friendly Barreto-Lynn-Scott elliptic curve construction allows to
construct [zk-SNARKs](https://z.cash/technology/zksnarks/) at the 128-bit security
and use aggregated, batch-verifiable
[threshold signatures](https://medium.com/snigirev.stepan/bls-signatures-better-than-schnorr-5a7fe30ea716),
using Boneh-Lynn-Shacham signature scheme. Compatible with ETH and others,
just make sure to provide correct DST (domain separation tag argument).
```ts
import { bls12_381 as bls } from '@noble/curves/bls12-381';
const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c';
const message = '64726e3da8';
const publicKey = bls.getPublicKey(privateKey);
const signature = bls.sign(message, privateKey);
const isValid = bls.verify(signature, message, publicKey);
console.log({ publicKey, signature, isValid });
// Sign 1 msg with 3 keys
const privateKeys = [
'18f020b98eb798752a50ed0563b079c125b0db5dd0b1060d1c1b47d4a193e1e4',
'ed69a8c50cf8c9836be3b67c7eeff416612d45ba39a5c099d48fa668bf558c9c',
'16ae669f3be7a2121e17d0c68c05a8f3d6bef21ec0f2315f1d7aec12484e4cf5',
];
const messages = ['d2', '0d98', '05caf3'];
const publicKeys = privateKeys.map(bls.getPublicKey);
const signatures2 = privateKeys.map((p) => bls.sign(message, p));
const aggPubKey2 = bls.aggregatePublicKeys(publicKeys);
const aggSignature2 = bls.aggregateSignatures(signatures2);
const isValid2 = bls.verify(aggSignature2, message, aggPubKey2);
console.log({ signatures2, aggSignature2, isValid2 });
// Sign 3 msgs with 3 keys
const signatures3 = privateKeys.map((p, i) => bls.sign(messages[i], p));
const aggSignature3 = bls.aggregateSignatures(signatures3);
const isValid3 = bls.verifyBatch(aggSignature3, messages, publicKeys);
console.log({ publicKeys, signatures3, aggSignature3, isValid3 });
// bls.pairing(PointG1, PointG2) // pairings
// hash-to-curve examples can be seen below
```
## Abstract API

@@ -226,2 +195,3 @@

- [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)

@@ -255,3 +225,3 @@ - [abstract/poseidon: Poseidon hash](#abstractposeidon-poseidon-hash)

// weierstrassPoints can also be used if you don't need ECDSA, hash, hmac, randomBytes
// Replace weierstrass with weierstrassPoints if you don't need ECDSA, hash, hmac, randomBytes
```

@@ -317,2 +287,4 @@

readonly pz: T;
get x(): bigint;
get y(): bigint;
multiply(scalar: bigint): ProjPointType<T>;

@@ -403,3 +375,3 @@ multiplyUnsafe(scalar: bigint): ProjPointType<T>;

const ed25519 = twistedEdwards({
a: -1n,
a: Fp.create(-1n),
d: Fp.div(-121665n, 121666n), // -121665n/121666n mod p

@@ -463,2 +435,4 @@ Fp: Fp,

readonly et: bigint;
get x(): bigint;
get y(): bigint;
assertValidity(): void;

@@ -471,2 +445,4 @@ multiply(scalar: bigint): ExtPointType;

toAffine(iz?: bigint): AffinePoint<bigint>;
toRawBytes(isCompressed?: boolean): Uint8Array;
toHex(isCompressed?: boolean): string;
}

@@ -509,2 +485,110 @@ // Static methods of Extended Point with coordinates in X, Y, Z, T

### abstract/bls: Barreto-Lynn-Scott curves
The module abstracts BLS (Barreto-Lynn-Scott) pairing-friendly elliptic curve construction.
They allow to construct [zk-SNARKs](https://z.cash/technology/zksnarks/) and
use aggregated, batch-verifiable
[threshold signatures](https://medium.com/snigirev.stepan/bls-signatures-better-than-schnorr-5a7fe30ea716),
using Boneh-Lynn-Shacham signature scheme.
Main methods and properties are:
- `getPublicKey(privateKey)`
- `sign(message, privateKey)`
- `verify(signature, message, publicKey)`
- `aggregatePublicKeys(publicKeys)`
- `aggregateSignatures(signatures)`
- `G1` and `G2` curves containing `CURVE` and `ProjectivePoint`
- `Signature` property with `fromHex`, `toHex` methods
- `fields` containing `Fp`, `Fp2`, `Fp6`, `Fp12`, `Fr`
Right now we only implement BLS12-381 (compatible with ETH and others),
but in theory defining BLS12-377, BLS24 should be straightforward. An example:
```ts
import { bls12_381 as bls } from '@noble/curves/bls12-381';
const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c';
const message = '64726e3da8';
const publicKey = bls.getPublicKey(privateKey);
const signature = bls.sign(message, privateKey);
const isValid = bls.verify(signature, message, publicKey);
console.log({ publicKey, signature, isValid });
// Sign 1 msg with 3 keys
const privateKeys = [
'18f020b98eb798752a50ed0563b079c125b0db5dd0b1060d1c1b47d4a193e1e4',
'ed69a8c50cf8c9836be3b67c7eeff416612d45ba39a5c099d48fa668bf558c9c',
'16ae669f3be7a2121e17d0c68c05a8f3d6bef21ec0f2315f1d7aec12484e4cf5',
];
const messages = ['d2', '0d98', '05caf3'];
const publicKeys = privateKeys.map(bls.getPublicKey);
const signatures2 = privateKeys.map((p) => bls.sign(message, p));
const aggPubKey2 = bls.aggregatePublicKeys(publicKeys);
const aggSignature2 = bls.aggregateSignatures(signatures2);
const isValid2 = bls.verify(aggSignature2, message, aggPubKey2);
console.log({ signatures2, aggSignature2, isValid2 });
// Sign 3 msgs with 3 keys
const signatures3 = privateKeys.map((p, i) => bls.sign(messages[i], p));
const aggSignature3 = bls.aggregateSignatures(signatures3);
const isValid3 = bls.verifyBatch(aggSignature3, messages, publicKeys);
console.log({ publicKeys, signatures3, aggSignature3, isValid3 });
// bls.pairing(PointG1, PointG2) // pairings
// bls.G1.ProjectivePoint.BASE, bls.G2.ProjectivePoint.BASE
// bls.fields.Fp, bls.fields.Fp2, bls.fields.Fp12, bls.fields.Fr
// hash-to-curve examples can be seen below
```
Full types:
```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

@@ -608,7 +692,2 @@

### abstract/bls
The module abstracts BLS (Barreto-Lynn-Scott) primitives. In theory you should be able to write BLS12-377, BLS24,
and others with it.
### abstract/modular: Modular arithmetics utilities

@@ -660,3 +739,5 @@

utils.hexToBytes('deadbeef');
utils.numberToHexUnpadded(123n);
utils.hexToNumber();
utils.bytesToNumberBE(Uint8Array.from([0xde, 0xad, 0xbe, 0xef]));

@@ -666,3 +747,3 @@ utils.bytesToNumberLE(Uint8Array.from([0xde, 0xad, 0xbe, 0xef]));

utils.numberToBytesLE(123n, 64);
utils.numberToHexUnpadded(123n);
utils.concatBytes(Uint8Array.from([0xde, 0xad]), Uint8Array.from([0xbe, 0xef]));

@@ -698,3 +779,3 @@ utils.nLength(255n);

getPublicKey x 5,640 ops/sec @ 177μs/op
sign x 3,909 ops/sec @ 255μs/op
sign x 4,471 ops/sec @ 223μs/op
verify x 780 ops/sec @ 1ms/op

@@ -709,3 +790,3 @@ getSharedSecret x 465 ops/sec @ 2ms/op

getPublicKey x 5,607 ops/sec @ 178μs/op
sign x 3,930 ops/sec @ 254μs/op
sign x 4,583 ops/sec @ 218μs/op
verify x 540 ops/sec @ 1ms/op

@@ -716,3 +797,3 @@

getPublicKey x 2,622 ops/sec @ 381μs/op
sign x 1,913 ops/sec @ 522μs/op
sign x 2,106 ops/sec @ 474μs/op
verify x 222 ops/sec @ 4ms/op

@@ -723,3 +804,3 @@

getPublicKey x 1,371 ops/sec @ 729μs/op
sign x 1,090 ops/sec @ 917μs/op
sign x 1,164 ops/sec @ 858μs/op
verify x 118 ops/sec @ 8ms/op

@@ -763,9 +844,8 @@

hash_to_field x 850,340 ops/sec @ 1μs/op
hashToCurve
├─secp256k1 x 1,850 ops/sec @ 540μs/op
├─P256 x 3,352 ops/sec @ 298μs/op
├─P384 x 1,367 ops/sec @ 731μs/op
├─P521 x 691 ops/sec @ 1ms/op
├─ed25519 x 2,492 ops/sec @ 401μs/op
└─ed448 x 1,045 ops/sec @ 956μs/op
secp256k1 x 2,143 ops/sec @ 466μs/op
P256 x 3,861 ops/sec @ 258μs/op
P384 x 1,526 ops/sec @ 655μs/op
P521 x 748 ops/sec @ 1ms/op
ed25519 x 2,772 ops/sec @ 360μs/op
ed448 x 1,146 ops/sec @ 871μs/op
```

@@ -780,20 +860,2 @@

## Resources
Article about some of library's features: [Learning fast elliptic-curve cryptography](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/)
Projects using the library:
- secp256k1
- [btc-signer](https://github.com/paulmillr/scure-btc-signer), [eth-signer](https://github.com/paulmillr/micro-eth-signer)
- ed25519
- [sol-signer](https://github.com/paulmillr/micro-sol-signer)
- BLS12-381
- Check out `bls12-381.ts` for articles about the curve
- Threshold sigs demo [genthresh.com](https://genthresh.com)
- BBS signatures [github.com/Wind4Greg/BBS-Draft-Checks](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)
- Others
- All curves demo: Elliptic curve calculator [paulmillr.com/noble](https://paulmillr.com/noble)
- [micro-starknet](https://github.com/paulmillr/micro-starknet) for stark-friendly elliptic curve.
## Upgrading

@@ -806,2 +868,4 @@

Upgrading from @noble/secp256k1 2.0 or @noble/ed25519 2.0: no changes, libraries are compatible.
Upgrading from [@noble/secp256k1](https://github.com/paulmillr/noble-secp256k1) 1.7:

@@ -844,2 +908,36 @@

Upgrading from [@noble/bls12-381](https://github.com/paulmillr/noble-bls12-381):
- Methods and classes were renamed:
- PointG1 -> G1.Point, PointG2 -> G2.Point
- PointG2.fromSignature -> Signature.decode, PointG2.toSignature -> Signature.encode
- Fp2 ORDER was corrected
## Resources
Useful articles about the library or its primitives:
- [Learning fast elliptic-curve cryptography](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/)
- Pairings and BLS
- [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:
[part 1](https://research.nccgroup.com/2020/07/06/pairing-over-bls12-381-part-1-fields/),
[part 2](https://research.nccgroup.com/2020/07/13/pairing-over-bls12-381-part-2-curves/),
[part 3](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/)
Real-world software that uses curves:
- [Elliptic Curve Calculator](https://paulmillr.com/noble) online demo: add / multiply points, sign messages
- Signers for web3 projects:
[btc-signer](https://github.com/paulmillr/scure-btc-signer), [eth-signer](https://github.com/paulmillr/micro-eth-signer),
[sol-signer](https://github.com/paulmillr/micro-sol-signer) for Solana
- [scure-bip32](https://github.com/paulmillr/scure-bip32) and separate [bip32](https://github.com/bitcoinjs/bip32) HDkey libraries
- [ed25519-keygen](https://github.com/paulmillr/ed25519-keygen) SSH, PGP, TOR key generation
- [micro-starknet](https://github.com/paulmillr/micro-starknet) stark-friendly elliptic curve algorithms.
- BLS threshold sigs demo [genthresh.com](https://genthresh.com)
- BLS BBS signatures [github.com/Wind4Greg/BBS-Draft-Checks](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)
## License

@@ -846,0 +944,0 @@

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

// prettier-ignore
const _2n = BigInt(2), _3n = BigInt(3);
export type SignatureCoder<Fp2> = {
decode(hex: Hex): ProjPointType<Fp2>;
encode(point: ProjPointType<Fp2>): Uint8Array;
fromHex(hex: Hex): ProjPointType<Fp2>;
toRawBytes(point: ProjPointType<Fp2>): Uint8Array;
toHex(point: ProjPointType<Fp2>): string;
};
export type CurveType<Fp, Fp2, Fp6, Fp12> = {
r: bigint;
G1: Omit<CurvePointsType<Fp>, 'n'> & {

@@ -44,16 +47,21 @@ mapToCurve: htf.MapToCurve<Fp>;

};
x: bigint;
Fp: IField<Fp>;
Fr: IField<bigint>;
Fp2: IField<Fp2> & {
reim: (num: Fp2) => { re: bigint; im: bigint };
multiplyByB: (num: Fp2) => Fp2;
frobeniusMap(num: Fp2, power: number): Fp2;
fields: {
Fp: IField<Fp>;
Fr: IField<bigint>;
Fp2: IField<Fp2> & {
reim: (num: Fp2) => { re: bigint; im: bigint };
multiplyByB: (num: Fp2) => Fp2;
frobeniusMap(num: Fp2, power: number): Fp2;
};
Fp6: IField<Fp6>;
Fp12: IField<Fp12> & {
frobeniusMap(num: Fp12, power: number): Fp12;
multiplyBy014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12;
conjugate(num: Fp12): Fp12;
finalExponentiate(num: Fp12): Fp12;
};
};
Fp6: IField<Fp6>;
Fp12: IField<Fp12> & {
frobeniusMap(num: Fp12, power: number): Fp12;
multiplyBy014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12;
conjugate(num: Fp12): Fp12;
finalExponentiate(num: Fp12): Fp12;
params: {
x: bigint;
r: bigint;
};

@@ -66,14 +74,2 @@ htfDefaults: htf.Opts;

export type CurveFn<Fp, Fp2, Fp6, Fp12> = {
CURVE: CurveType<Fp, Fp2, Fp6, Fp12>;
Fr: IField<bigint>;
Fp: IField<Fp>;
Fp2: IField<Fp2>;
Fp6: IField<Fp6>;
Fp12: IField<Fp12>;
G1: CurvePointsRes<Fp> & ReturnType<typeof htf.createHasher<Fp>>;
G2: CurvePointsRes<Fp2> & ReturnType<typeof htf.createHasher<Fp2>>;
Signature: SignatureCoder<Fp2>;
millerLoop: (ell: [Fp2, Fp2, Fp2][], g1: [Fp, Fp]) => Fp12;
calcPairingPrecomputes: (p: AffinePoint<Fp2>) => [Fp2, Fp2, Fp2][];
pairing: (P: ProjPointType<Fp>, Q: ProjPointType<Fp2>, withFinalExponent?: boolean) => Fp12;
getPublicKey: (privateKey: PrivKey) => Uint8Array;

@@ -89,2 +85,7 @@ sign: {

) => boolean;
verifyBatch: (
signature: Hex | ProjPointType<Fp2>,
messages: (Hex | ProjPointType<Fp2>)[],
publicKeys: (Hex | ProjPointType<Fp>)[]
) => boolean;
aggregatePublicKeys: {

@@ -98,9 +99,23 @@ (publicKeys: Hex[]): Uint8Array;

};
verifyBatch: (
signature: Hex | ProjPointType<Fp2>,
messages: (Hex | ProjPointType<Fp2>)[],
publicKeys: (Hex | ProjPointType<Fp>)[]
) => boolean;
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][];
};

@@ -112,5 +127,5 @@ };

): CurveFn<Fp, Fp2, Fp6, Fp12> {
// Fields looks pretty specific for curve, so for now we need to pass them with opts
const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE;
const BLS_X_LEN = bitLen(CURVE.x);
// Fields are specific for curve, so for now we'll need to pass them with opts
const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE.fields;
const BLS_X_LEN = bitLen(CURVE.params.x);
const groupLen = 32; // TODO: calculate; hardcoded for now

@@ -131,14 +146,14 @@

let t1 = Fp2.sqr(Rz); // Rz²
let t2 = Fp2.multiplyByB(Fp2.mul(t1, 3n)); // 3 * T1 * B
let t3 = Fp2.mul(t2, 3n); // 3 * T2
let t2 = Fp2.multiplyByB(Fp2.mul(t1, _3n)); // 3 * T1 * B
let t3 = Fp2.mul(t2, _3n); // 3 * T2
let t4 = Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(Ry, Rz)), t1), t0); // (Ry + Rz)² - T1 - T0
ell_coeff.push([
Fp2.sub(t2, t0), // T2 - T0
Fp2.mul(Fp2.sqr(Rx), 3n), // 3 * Rx²
Fp2.mul(Fp2.sqr(Rx), _3n), // 3 * Rx²
Fp2.neg(t4), // -T4
]);
Rx = Fp2.div(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), 2n); // ((T0 - T3) * Rx * Ry) / 2
Ry = Fp2.sub(Fp2.sqr(Fp2.div(Fp2.add(t0, t3), 2n)), Fp2.mul(Fp2.sqr(t2), 3n)); // ((T0 + T3) / 2)² - 3 * T2²
Rx = Fp2.div(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), _2n); // ((T0 - T3) * Rx * Ry) / 2
Ry = Fp2.sub(Fp2.sqr(Fp2.div(Fp2.add(t0, t3), _2n)), Fp2.mul(Fp2.sqr(t2), _3n)); // ((T0 + T3) / 2)² - 3 * T2²
Rz = Fp2.mul(t0, t4); // T0 * T4
if (bitGet(CURVE.x, i)) {
if (bitGet(CURVE.params.x, i)) {
// Addition

@@ -155,3 +170,3 @@ let t0 = Fp2.sub(Ry, Fp2.mul(Qy, Rz)); // Ry - Qy * Rz

let t4 = Fp2.mul(t2, Rx); // T2 * Rx
let t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, 2n)), Fp2.mul(Fp2.sqr(t0), Rz)); // T3 - 2 * T4 + T0² * Rz
let t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, _2n)), Fp2.mul(Fp2.sqr(t0), Rz)); // T3 - 2 * T4 + T0² * Rz
Rx = Fp2.mul(t1, t5); // T1 * T5

@@ -166,3 +181,3 @@ Ry = Fp2.sub(Fp2.mul(Fp2.sub(t4, t5), t0), Fp2.mul(t3, Ry)); // (T4 - T5) * T0 - T3 * Ry

function millerLoop(ell: [Fp2, Fp2, Fp2][], g1: [Fp, Fp]): Fp12 {
const { x } = CURVE;
const { x } = CURVE.params;
const Px = g1[0];

@@ -186,4 +201,5 @@ const Py = g1[1];

randomPrivateKey: (): Uint8Array => {
return Fr.toBytes(hashToPrivateScalar(CURVE.randomBytes(groupLen + 8), CURVE.r));
return Fr.toBytes(hashToPrivateScalar(CURVE.randomBytes(groupLen + 8), CURVE.params.r));
},
calcPairingPrecomputes,
};

@@ -249,3 +265,3 @@

function normP2(point: G2Hex): G2 {
return point instanceof G2.ProjectivePoint ? point : Signature.decode(point);
return point instanceof G2.ProjectivePoint ? point : Signature.fromHex(point);
}

@@ -273,3 +289,3 @@ function normP2Hash(point: G2Hex, htfOpts?: htf.htfBasicOpts): G2 {

if (message instanceof G2.ProjectivePoint) return sigPoint;
return Signature.encode(sigPoint);
return Signature.toRawBytes(sigPoint);
}

@@ -324,3 +340,3 @@

}
return Signature.encode(aggAffine);
return Signature.toRawBytes(aggAffine);
}

@@ -369,22 +385,28 @@

return {
CURVE,
Fr,
Fp,
Fp2,
Fp6,
Fp12,
G1,
G2,
Signature,
millerLoop,
calcPairingPrecomputes,
pairing,
getPublicKey,
sign,
verify,
verifyBatch,
aggregatePublicKeys,
aggregateSignatures,
verifyBatch,
millerLoop,
pairing,
G1,
G2,
Signature,
fields: {
Fr,
Fp,
Fp2,
Fp6,
Fp12,
},
params: {
x: CURVE.params.x,
r: CURVE.params.r,
G1b: CURVE.G1.b,
G2b: CURVE.G2.b,
},
utils,
};
}

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

uvRatio?: (u: bigint, v: bigint) => { isValid: boolean; value: bigint }; // Ratio √(u/v)
preHash?: FHash; // RFC 8032 pre-hashing of messages to sign() / verify()
prehash?: FHash; // RFC 8032 pre-hashing of messages to sign() / verify()
mapToCurve?: (scalar: bigint[]) => AffinePoint<bigint>; // for hash-to-curve standard
};
// verification rule is either zip215 or rfc8032 / nist186-5. Consult fromHex:
const VERIFY_DEFAULT = { zip215: true };
function validateOpts(curve: CurveType) {

@@ -94,3 +97,11 @@ const opts = validateBasic(curve);

const CURVE = validateOpts(curveDef) as ReturnType<typeof validateOpts>;
const { Fp, n: CURVE_ORDER, preHash, hash: cHash, randomBytes, nByteLength, h: cofactor } = CURVE;
const {
Fp,
n: CURVE_ORDER,
prehash: prehash,
hash: cHash,
randomBytes,
nByteLength,
h: cofactor,
} = CURVE;
const MASK = _2n ** BigInt(nByteLength * 8);

@@ -349,3 +360,3 @@ const modP = Fp.create; // Function overrides

// Uses algo from RFC8032 5.1.3.
static fromHex(hex: Hex, strict = true): Point {
static fromHex(hex: Hex, zip215 = false): Point {
const { d, a } = CURVE;

@@ -362,4 +373,4 @@ const len = Fp.BYTES;

// RFC8032 prohibits >= p, but ZIP215 doesn't
if (strict) assertInRange(y, Fp.ORDER); // strict=true [1..P-1] (2^255-19-1 for ed25519)
else assertInRange(y, MASK); // strict=false [1..MASK-1] (2^256-1 for ed25519)
if (zip215) assertInRange(y, MASK); // zip215=true [1..P-1] (2^255-19-1 for ed25519)
else assertInRange(y, Fp.ORDER); // zip215=false [1..MASK-1] (2^256-1 for ed25519)
}

@@ -426,13 +437,13 @@

const msg = ut.concatBytes(...msgs);
return modN_LE(cHash(domain(msg, ensureBytes('context', context), !!preHash)));
return modN_LE(cHash(domain(msg, ensureBytes('context', context), !!prehash)));
}
/** Signs message with privateKey. RFC8032 5.1.6 */
function sign(msg: Hex, privKey: Hex, context?: Hex): Uint8Array {
function sign(msg: Hex, privKey: Hex, options: { context?: Hex } = {}): Uint8Array {
msg = ensureBytes('message', msg);
if (preHash) msg = preHash(msg); // for ed25519ph etc.
if (prehash) msg = prehash(msg); // for ed25519ph etc.
const { prefix, scalar, pointBytes } = getExtendedPublicKey(privKey);
const r = hashDomainToScalar(context, prefix, msg); // r = dom2(F, C) || prefix || PH(M)
const r = hashDomainToScalar(options.context, prefix, msg); // r = dom2(F, C) || prefix || PH(M)
const R = G.multiply(r).toRawBytes(); // R = rG
const k = hashDomainToScalar(context, R, pointBytes, msg); // R || A || PH(M)
const k = hashDomainToScalar(options.context, R, pointBytes, msg); // R || A || PH(M)
const s = modN(r + k * scalar); // S = (r + k * s) mod L

@@ -444,11 +455,22 @@ assertGE0(s); // 0 <= s < l

function verify(sig: Hex, msg: Hex, publicKey: Hex, context?: Hex): boolean {
const verifyOpts: { context?: Hex; zip215?: boolean } = VERIFY_DEFAULT;
function verify(sig: Hex, msg: Hex, publicKey: Hex, options = verifyOpts): boolean {
const { context, zip215 } = options;
const len = Fp.BYTES; // Verifies EdDSA signature against message and public key. RFC8032 5.1.7.
sig = ensureBytes('signature', sig, 2 * len); // An extended group equation is checked.
msg = ensureBytes('message', msg); // ZIP215 compliant, which means not fully RFC8032 compliant.
if (preHash) msg = preHash(msg); // for ed25519ph, etc
const A = Point.fromHex(publicKey, false); // Check for s bounds, hex validity
const R = Point.fromHex(sig.slice(0, len), false); // 0 <= R < 2^256: ZIP215 R can be >= P
msg = ensureBytes('message', msg);
if (prehash) msg = prehash(msg); // for ed25519ph, etc
const s = ut.bytesToNumberLE(sig.slice(len, 2 * len));
const SB = G.multiplyUnsafe(s); // 0 <= s < l is done inside
// zip215: true is good for consensus-critical apps and allows points < 2^256
// zip215: false follows RFC8032 / NIST186-5 and restricts points to CURVE.p
let A, R, SB;
try {
A = Point.fromHex(publicKey, zip215);
R = Point.fromHex(sig.slice(0, len), zip215);
SB = G.multiplyUnsafe(s); // 0 <= s < l is done inside
} catch (error) {
return false;
}
const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg);

@@ -455,0 +477,0 @@ const RkA = R.add(A.multiplyUnsafe(k));

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

k: number;
expand?: 'xmd' | 'xof';
expand: 'xmd' | 'xof';
hash: CHash;

@@ -149,6 +149,7 @@ };

prb = expand_message_xof(msg, DST, len_in_bytes, k, hash);
} else if (expand === undefined) {
} else if (expand === '_internal_pass') {
// for internal tests only
prb = msg;
} else {
throw new Error('expand must be "xmd", "xof" or undefined');
throw new Error('expand must be "xmd" or "xof"');
}

@@ -155,0 +156,0 @@ const u = new Array(count);

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

let len;
for (len = 0; n > 0n; n >>= _1n, len += 1);
for (len = 0; n > _0n; n >>= _1n, len += 1);
return len;

@@ -132,3 +132,3 @@ }

// Same as !!+Array.from(n.toString(2)).reverse()[pos]
export const bitGet = (n: bigint, pos: number) => (n >> BigInt(pos)) & 1n;
export const bitGet = (n: bigint, pos: number) => (n >> BigInt(pos)) & _1n;
// Sets single bit at position

@@ -135,0 +135,0 @@ export const bitSet = (n: bigint, pos: number, value: boolean) =>

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

const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut;
const DER = {
export const DER = {
// asn.1 DER encoding utils

@@ -148,5 +148,9 @@ Err: class DERErr extends Error {

if (!len || res.length !== len) throw new E('Invalid signature integer: wrong length');
if (res[0] === 0x00 && res[1] <= 0x7f)
throw new E('Invalid signature integer: trailing length');
// ^ Weird condition: not about length, but about first bytes of number.
// https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag,
// since we always use positive integers here. It must always be empty:
// - add zero byte if exists
// - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding)
if (res[0] & 0b10000000) throw new E('Invalid signature integer: negative');
if (res[0] === 0x00 && !(res[1] & 0b10000000))
throw new E('Invalid signature integer: unnecessary leading zero');
return { d: b2n(res), l: data.subarray(len + 2) }; // d is data, l is left

@@ -168,3 +172,4 @@ },

hexFromSig(sig: { r: bigint; s: bigint }): string {
const slice = (s: string): string => (Number.parseInt(s[0], 16) >= 8 ? '00' + s : s); // slice DER
// Add leading zero if first byte has negative bit enabled. More details in '_parseInt'
const slice = (s: string): string => (Number.parseInt(s[0], 16) & 0b1000 ? '00' + s : s);
const h = (num: number | bigint) => {

@@ -219,2 +224,8 @@ const hex = num.toString(16);

}
// Validate whether the passed curve params are valid.
// We check if curve equation works for generator point.
// `assertValidity()` won't work: `isTorsionFree()` is not available at this point in bls12-381.
// ProjectivePoint class has not been initialized yet.
if (!Fp.eql(Fp.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx)))
throw new Error('bad generator point: equation left != right');

@@ -598,3 +609,3 @@ // Valid group elements reside in range 1..n-1

const wnaf = wNAF(Point, CURVE.endo ? Math.ceil(_bits / 2) : _bits);
// Validate if generator point is on curve
return {

@@ -1115,3 +1126,3 @@ CURVE,

// 17. for i in (c1, c1 - 1, ..., 2):
for (let i = c1; i > 1; i--) {
for (let i = c1; i > _1n; i--) {
let tv5 = _2n ** (i - _2n); // 18. tv5 = i - 2; 19. tv5 = 2^tv5

@@ -1118,0 +1129,0 @@ let tvv5 = Fp.pow(tv4, tv5); // 20. tv5 = tv4^tv5

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

// Compatible with Algorand, Chia, Dfinity, Ethereum, FIL, Zcash. Matches specs
// [pairing-curves-10](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-10),
// [pairing-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11),
// [bls-sigs-04](https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04),

@@ -31,20 +31,2 @@ // [hash-to-curve-12](https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-12).

// so ensure to reverse byte order if you'll use it with FIL.
//
// ### Resources
// - [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:
// [part 1](https://research.nccgroup.com/2020/07/06/pairing-over-bls12-381-part-1-fields/),
// [part 2](https://research.nccgroup.com/2020/07/13/pairing-over-bls12-381-part-2-curves/),
// [part 3](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/)
//
// ### Differences from @noble/bls12-381 1.4
// - PointG1 -> G1.Point
// - PointG2 -> G2.Point
// - PointG2.fromSignature -> Signature.decode
// - PointG2.toSignature -> Signature.encode
// - Fixed Fp2 ORDER
// - Points now have only two coordinates
import { sha256 } from '@noble/hashes/sha256';

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

bitMask,
bytesToHex,
} from './abstract/utils.js';

@@ -78,4 +61,4 @@ // Types

const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);
const _8n = BigInt(8),
_16n = BigInt(16);
// prettier-ignore
const _8n = BigInt(8), _16n = BigInt(16);

@@ -957,5 +940,5 @@ // CURVE FIELDS

const G2_SWU = mapToCurveSimpleSWU(Fp2, {
A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(240n) }), // A' = 240 * I
B: Fp2.create({ c0: Fp.create(1012n), c1: Fp.create(1012n) }), // B' = 1012 * (1 + I)
Z: Fp2.create({ c0: Fp.create(-2n), c1: Fp.create(-1n) }), // Z: -(2 + I)
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)
});

@@ -974,3 +957,3 @@ // Optimized SWU Map - Fp to G1

),
Z: Fp.create(11n),
Z: Fp.create(BigInt(11)),
});

@@ -1051,4 +1034,20 @@

// 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 = Fp.toBytes(bitSet(bitSet(_0n, I_BIT_POS, true), S_BIT_POS, true)); // set compressed & point-at-infinity bits
function signatureG2ToRawBytes(point: ProjPointType<Fp2>) {
// NOTE: by some reasons it was missed in bls12-381, looks like bug
point.assertValidity();
const len = Fp.BYTES;
if (point.equals(bls12_381.G2.ProjectivePoint.ZERO))
return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len));
const { x, y } = point.toAffine();
const { re: x0, im: x1 } = Fp2.reim(x);
const { re: y0, im: y1 } = Fp2.reim(y);
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 z2 = x0;
return concatB(numberToBytesBE(z1, len), numberToBytesBE(z2, len));
}
// To verify curve parameters, see pairing-friendly-curves spec:

@@ -1066,9 +1065,9 @@ // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-09

// Fields
Fr,
Fp,
Fp2,
Fp6,
Fp12,
// order; z⁴ − z² + 1
r: Fr.ORDER, // Same as N in other curves
fields: {
Fp,
Fp2,
Fp6,
Fp12,
Fr,
},
// G1 is the order-q subgroup of E1(Fp) : y² = x³ + 4, #E1(Fp) = h1q, where

@@ -1106,4 +1105,4 @@ // characteristic; z + (z⁴ - z² + 1)(z - 1)²/3

// todo: unroll
const xP = point.multiplyUnsafe(bls12_381.CURVE.x).negate(); // [x]P
const u2P = xP.multiplyUnsafe(bls12_381.CURVE.x); // [u2]P
const xP = point.multiplyUnsafe(bls12_381.params.x).negate(); // [x]P
const u2P = xP.multiplyUnsafe(bls12_381.params.x); // [u2]P
return u2P.equals(phi);

@@ -1127,3 +1126,3 @@

// return this.multiplyUnsafe(CURVE.h);
return point.multiplyUnsafe(bls12_381.CURVE.x).add(point); // x*P + P
return point.multiplyUnsafe(bls12_381.params.x).add(point); // x*P + P
},

@@ -1135,3 +1134,5 @@ mapToCurve: (scalars: bigint[]) => {

fromBytes: (bytes: Uint8Array): AffinePoint<Fp> => {
bytes = bytes.slice();
if (bytes.length === 48) {
// TODO: Fp.bytes
const P = Fp.ORDER;

@@ -1143,3 +1144,3 @@ const compressedValue = bytesToNumberBE(bytes);

const x = Fp.create(compressedValue & Fp.MASK);
const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.CURVE.G1.b)); // y² = x³ + b
const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)); // y² = x³ + b
let y = Fp.sqrt(right);

@@ -1153,4 +1154,4 @@ if (!y) throw new Error('Invalid compressed G1 point');

if ((bytes[0] & (1 << 6)) !== 0) return bls12_381.G1.ProjectivePoint.ZERO.toAffine();
const x = bytesToNumberBE(bytes.slice(0, Fp.BYTES));
const y = bytesToNumberBE(bytes.slice(Fp.BYTES));
const x = bytesToNumberBE(bytes.subarray(0, Fp.BYTES));
const y = bytesToNumberBE(bytes.subarray(Fp.BYTES));
return { x: Fp.create(x), y: Fp.create(y) };

@@ -1228,3 +1229,3 @@ } else {

isTorsionFree: (c, P): boolean => {
return P.multiplyUnsafe(bls12_381.CURVE.x).negate().equals(G2psi(c, P)); // ψ(P) == [u](P)
return P.multiplyUnsafe(bls12_381.params.x).negate().equals(G2psi(c, P)); // ψ(P) == [u](P)
// Older version: https://eprint.iacr.org/2019/814.pdf

@@ -1239,3 +1240,3 @@ // Ψ²(P) => Ψ³(P) => [z]Ψ³(P) where z = -x => [z]Ψ³(P) - Ψ²(P) + P == O

clearCofactor: (c, P) => {
const { x } = bls12_381.CURVE;
const x = bls12_381.params.x;
let t1 = P.multiplyUnsafe(x).negate(); // [-x]P

@@ -1254,2 +1255,3 @@ let t2 = G2psi(c, P); // Ψ(P)

fromBytes: (bytes: Uint8Array): AffinePoint<Fp2> => {
bytes = bytes.slice();
const m_byte = bytes[0] & 0xe0;

@@ -1265,3 +1267,3 @@ if (m_byte === 0x20 || m_byte === 0x60 || m_byte === 0xe0) {

if (bytes.length === 96 && bitC) {
const { b } = bls12_381.CURVE.G2;
const b = bls12_381.params.G2b;
const P = Fp.ORDER;

@@ -1300,7 +1302,7 @@

toBytes: (c, point, isCompressed) => {
const { BYTES: len, ORDER: P } = Fp;
const isZero = point.equals(c.ZERO);
const { x, y } = point.toAffine();
if (isCompressed) {
const P = Fp.ORDER;
if (isZero) return concatB(COMPRESSED_ZERO, numberToBytesBE(0n, Fp.BYTES));
if (isZero) return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len));
const flag = Boolean(y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P);

@@ -1310,12 +1312,12 @@ // set compressed & sign bits (looks like different offsets than for G1/Fp?)

x_1 = bitSet(x_1, S_BIT_POS, true);
return concatB(numberToBytesBE(x_1, Fp.BYTES), numberToBytesBE(x.c0, Fp.BYTES));
return concatB(numberToBytesBE(x_1, len), numberToBytesBE(x.c0, len));
} else {
if (isZero) return concatB(new Uint8Array([0x40]), new Uint8Array(4 * Fp.BYTES - 1)); // bytes[0] |= 1 << 6;
if (isZero) return concatB(new Uint8Array([0x40]), new Uint8Array(4 * len - 1)); // bytes[0] |= 1 << 6;
const { re: x0, im: x1 } = Fp2.reim(x);
const { re: y0, im: y1 } = Fp2.reim(y);
return concatB(
numberToBytesBE(x1, Fp.BYTES),
numberToBytesBE(x0, Fp.BYTES),
numberToBytesBE(y1, Fp.BYTES),
numberToBytesBE(y0, Fp.BYTES)
numberToBytesBE(x1, len),
numberToBytesBE(x0, len),
numberToBytesBE(y1, len),
numberToBytesBE(y0, len)
);

@@ -1326,3 +1328,3 @@ }

// TODO: Optimize, it's very slow because of sqrt.
decode(hex: Hex): ProjPointType<Fp2> {
fromHex(hex: Hex): ProjPointType<Fp2> {
hex = ensureBytes('signatureHex', hex);

@@ -1342,3 +1344,3 @@ const P = Fp.ORDER;

const x = Fp2.create({ c0: x2, c1: x1 });
const y2 = Fp2.add(Fp2.pow(x, _3n), bls12_381.CURVE.G2.b); // y² = x³ + 4
const y2 = Fp2.add(Fp2.pow(x, _3n), bls12_381.params.G2b); // y² = x³ + 4
// The slow part

@@ -1359,20 +1361,14 @@ let y = Fp2.sqrt(y2);

},
encode(point: ProjPointType<Fp2>) {
// NOTE: by some reasons it was missed in bls12-381, looks like bug
point.assertValidity();
if (point.equals(bls12_381.G2.ProjectivePoint.ZERO))
return concatB(COMPRESSED_ZERO, numberToBytesBE(0n, Fp.BYTES));
const a = point.toAffine();
const { re: x0, im: x1 } = Fp2.reim(a.x);
const { re: y0, im: y1 } = Fp2.reim(a.y);
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 z2 = x0;
return concatB(numberToBytesBE(z1, Fp.BYTES), numberToBytesBE(z2, Fp.BYTES));
toRawBytes(point: ProjPointType<Fp2>) {
return signatureG2ToRawBytes(point);
},
toHex(point: ProjPointType<Fp2>) {
return bytesToHex(signatureG2ToRawBytes(point));
},
},
},
// The BLS parameter x for BLS12-381
x: BLS_X,
params: {
x: BLS_X, // The BLS parameter x for BLS12-381
r: Fr.ORDER, // order; z⁴ − z² + 1; CURVE.n from other curves
},
htfDefaults,

@@ -1379,0 +1375,0 @@ hash: sha256,

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

const ED25519_DEF = {
const ed25519Defaults = {
// Param: a
a: BigInt(-1),
// Equal to -121665/121666 over finite field.
a: BigInt(-1), // Fp.create(-1) is proper; our way still works and is faster
// d is equal to -121665/121666 over finite field.
// Negative number is P - number, and division is invert(number, P)

@@ -107,3 +107,3 @@ d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'),

Fp,
// Subgroup order: how many points ed25519 has
// Subgroup order: how many points curve has
// 2n ** 252n + 27742317777372353535851937790883648493n;

@@ -125,3 +125,3 @@ n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'),

export const ed25519 = twistedEdwards(ED25519_DEF);
export const ed25519 = twistedEdwards(ed25519Defaults);
function ed25519_domain(data: Uint8Array, ctx: Uint8Array, phflag: boolean) {

@@ -136,7 +136,7 @@ if (ctx.length > 255) throw new Error('Context is too big');

}
export const ed25519ctx = twistedEdwards({ ...ED25519_DEF, domain: ed25519_domain });
export const ed25519ctx = twistedEdwards({ ...ed25519Defaults, domain: ed25519_domain });
export const ed25519ph = twistedEdwards({
...ED25519_DEF,
...ed25519Defaults,
domain: ed25519_domain,
preHash: sha512,
prehash: sha512,
});

@@ -160,2 +160,16 @@

/**
* Converts ed25519 public key to x25519 public key. Uses formula:
* * `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)`
* * `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))`
* @example
* const aPub = ed25519.getPublicKey(utils.randomPrivateKey());
* x25519.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub))
*/
export function edwardsToMontgomery(edwardsPub: Hex): Uint8Array {
const { y } = ed25519.ExtendedPoint.fromHex(edwardsPub);
const _1n = BigInt(1);
return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n)));
}
// Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator)

@@ -162,0 +176,0 @@ // NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since

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

// NOTE: there is no ed448ctx, since ed448 supports ctx by default
export const ed448ph = twistedEdwards({ ...ED448_DEF, preHash: shake256_64 });
export const ed448ph = twistedEdwards({ ...ED448_DEF, prehash: shake256_64 });

@@ -140,18 +140,18 @@ export const x448 = montgomery({

randomBytes,
// The 4-isogeny maps between the Montgomery curve and this Edwards
// curve are:
// (u, v) = (y^2/x^2, (2 - x^2 - y^2)*y/x^3)
// (x, y) = (4*v*(u^2 - 1)/(u^4 - 2*u^2 + 4*v^2 + 1),
// -(u^5 - 2*u^3 - 4*u*v^2 + u)/
// (u^5 - 2*u^2*v^2 - 2*u^3 - 2*v^2 + u))
// xyToU: (p: PointType) => {
// const P = ed448P;
// const { x, y } = p;
// if (x === _0n) throw new Error(`Point with x=0 doesn't have mapping`);
// const invX = invert(x * x, P); // x^2
// const u = mod(y * y * invX, P); // (y^2/x^2)
// return numberToBytesLE(u, 56);
// },
});
/**
* Converts edwards448 public key to x448 public key. Uses formula:
* * `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)`
* * `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))`
* @example
* const aPub = ed448.getPublicKey(utils.randomPrivateKey());
* x448.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub))
*/
export function edwardsToMontgomery(edwardsPub: string | Uint8Array): Uint8Array {
const { y } = ed448.ExtendedPoint.fromHex(edwardsPub);
const _1n = BigInt(1);
return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n)));
}
// Hash To Curve Elligator2 Map

@@ -158,0 +158,0 @@ const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4); // 1. c1 = (q - 3) / 4 # Integer arithmetic

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

// NIST secp256r1 aka P256
// NIST secp256r1 aka p256
// https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-256
// Field over which we'll do calculations; 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n
const Fp = Field(BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff'));

@@ -23,19 +22,16 @@ const CURVE_A = Fp.create(BigInt('-3'));

export const P256 = createCurve(
{
// Params: a, b
a: CURVE_A,
b: CURVE_B,
Fp,
// Curve order, total count of valid points in the field
n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'),
// Base point (x, y) aka generator point
Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'),
Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'),
h: BigInt(1),
lowS: false,
} as const,
sha256
);
export const secp256r1 = P256;
// prettier-ignore
export const p256 = createCurve({
a: CURVE_A, // Equation params: a, b
b: CURVE_B,
Fp, // Field: 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n
// Curve order, total count of valid points in the field
n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'),
// Base (generator) point (x, y)
Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'),
Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'),
h: BigInt(1),
lowS: false,
} as const, sha256);
export const secp256r1 = p256;

@@ -42,0 +38,0 @@ const { hashToCurve, encodeToCurve } = htf.createHasher(

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

// NIST secp384r1 aka P384
// NIST secp384r1 aka p384
// https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-384
// Field over which we'll do calculations. 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n
// Field over which we'll do calculations.
// prettier-ignore

@@ -20,2 +20,17 @@ const P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff');

// prettier-ignore
export const p384 = createCurve({
a: CURVE_A, // Equation params: a, b
b: CURVE_B,
Fp, // Field: 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n
// Curve order, total count of valid points in the field.
n: BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973'),
// Base (generator) point (x, y)
Gx: BigInt('0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7'),
Gy: BigInt('0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f'),
h: BigInt(1),
lowS: false,
} as const, sha384);
export const secp384r1 = p384;
const mapSWU = mapToCurveSimpleSWU(Fp, {

@@ -27,21 +42,2 @@ A: CURVE_A,

// prettier-ignore
export const P384 = createCurve({
// Params: a, b
a: CURVE_A,
b: CURVE_B,
// Field over which we'll do calculations. 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n
Fp,
// Curve order, total count of valid points in the field.
n: BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973'),
// Base point (x, y) aka generator point
Gx: BigInt('0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7'),
Gy: BigInt('0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f'),
h: BigInt(1),
lowS: false,
} as const,
sha384
);
export const secp384r1 = P384;
const { hashToCurve, encodeToCurve } = htf.createHasher(

@@ -48,0 +44,0 @@ secp384r1.ProjectivePoint,

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

// NIST secp521r1 aka P521
// NIST secp521r1 aka p521
// Note that it's 521, which differs from 512 of its hash function.
// https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-521
// Field over which we'll do calculations; 2n**521n - 1n
// Field over which we'll do calculations.
// prettier-ignore

@@ -18,29 +18,41 @@ const P = BigInt('0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');

const CURVE_A = Fp.create(BigInt('-3'));
// prettier-ignore
const CURVE_B = BigInt('0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00');
const CURVE = {
a: Fp.create(BigInt('-3')),
b: BigInt(
'0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00'
),
Fp,
n: BigInt(
'0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409'
),
Gx: BigInt(
'0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66'
),
Gy: BigInt(
'0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650'
),
h: BigInt(1),
};
const mapSWU = mapToCurveSimpleSWU(Fp, {
A: CURVE_A,
B: CURVE_B,
Z: Fp.create(BigInt('-4')),
});
// prettier-ignore
export const P521 = createCurve({
// Params: a, b
a: CURVE_A,
b: CURVE_B,
Fp,
export const p521 = createCurve({
a: CURVE.a, // Equation params: a, b
b: CURVE.b,
Fp, // Field: 2n**521n - 1n
// Curve order, total count of valid points in the field
n: BigInt('0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409'),
// Base point (x, y) aka generator point
Gx: BigInt('0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66'),
Gy: BigInt('0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650'),
h: BigInt(1),
n: CURVE.n,
Gx: CURVE.Gx, // Base point (x, y) aka generator point
Gy: CURVE.Gy,
h: CURVE.h,
lowS: false,
allowedPrivateKeyLengths: [130, 131, 132] // P521 keys are variable-length. Normalize to 132b
} as const, sha512);
export const secp521r1 = P521;
export const secp521r1 = p521;
const mapSWU = mapToCurveSimpleSWU(Fp, {
A: CURVE.a,
B: CURVE.b,
Z: Fp.create(BigInt('-4')),
});
const { hashToCurve, encodeToCurve } = htf.createHasher(

@@ -47,0 +59,0 @@ secp521r1.ProjectivePoint,

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