修改后台权限
This commit is contained in:
190
node_modules/@noble/curves/esm/abstract/bls.d.ts
generated
vendored
Normal file
190
node_modules/@noble/curves/esm/abstract/bls.d.ts
generated
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
/**
|
||||
* BLS != BLS.
|
||||
* The file implements BLS (Boneh-Lynn-Shacham) signatures.
|
||||
* Used in both BLS (Barreto-Lynn-Scott) and BN (Barreto-Naehrig)
|
||||
* families of pairing-friendly curves.
|
||||
* Consists of two curves: G1 and G2:
|
||||
* - G1 is a subgroup of (x, y) E(Fq) over y² = x³ + 4.
|
||||
* - G2 is a subgroup of ((x₁, x₂+i), (y₁, y₂+i)) E(Fq²) over y² = x³ + 4(1 + i) where i is √-1
|
||||
* - Gt, created by bilinear (ate) pairing e(G1, G2), consists of p-th roots of unity in
|
||||
* Fq^k where k is embedding degree. Only degree 12 is currently supported, 24 is not.
|
||||
* Pairing is used to aggregate and verify signatures.
|
||||
* There are two modes of operation:
|
||||
* - Long signatures: X-byte keys + 2X-byte sigs (G1 keys + G2 sigs).
|
||||
* - Short signatures: 2X-byte keys + X-byte sigs (G2 keys + G1 sigs).
|
||||
* @module
|
||||
**/
|
||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||
import { type CHash, type Hex, type PrivKey } from '../utils.ts';
|
||||
import { type H2CHasher, type H2CHashOpts, type H2COpts, type htfBasicOpts, type MapToCurve } from './hash-to-curve.ts';
|
||||
import { type IField } from './modular.ts';
|
||||
import type { Fp12, Fp12Bls, Fp2, Fp2Bls, Fp6Bls } from './tower.ts';
|
||||
import { type CurvePointsRes, type CurvePointsType, type WeierstrassPoint, type WeierstrassPointCons } from './weierstrass.ts';
|
||||
type Fp = bigint;
|
||||
export type TwistType = 'multiplicative' | 'divisive';
|
||||
export type ShortSignatureCoder<Fp> = {
|
||||
fromBytes(bytes: Uint8Array): WeierstrassPoint<Fp>;
|
||||
fromHex(hex: Hex): WeierstrassPoint<Fp>;
|
||||
toBytes(point: WeierstrassPoint<Fp>): Uint8Array;
|
||||
toHex(point: WeierstrassPoint<Fp>): string;
|
||||
/** @deprecated use `toBytes` */
|
||||
toRawBytes(point: WeierstrassPoint<Fp>): Uint8Array;
|
||||
};
|
||||
export type SignatureCoder<Fp> = {
|
||||
fromBytes(bytes: Uint8Array): WeierstrassPoint<Fp>;
|
||||
fromHex(hex: Hex): WeierstrassPoint<Fp>;
|
||||
toBytes(point: WeierstrassPoint<Fp>): Uint8Array;
|
||||
toHex(point: WeierstrassPoint<Fp>): string;
|
||||
/** @deprecated use `toBytes` */
|
||||
toRawBytes(point: WeierstrassPoint<Fp>): Uint8Array;
|
||||
};
|
||||
export type BlsFields = {
|
||||
Fp: IField<Fp>;
|
||||
Fr: IField<bigint>;
|
||||
Fp2: Fp2Bls;
|
||||
Fp6: Fp6Bls;
|
||||
Fp12: Fp12Bls;
|
||||
};
|
||||
export type PostPrecomputePointAddFn = (Rx: Fp2, Ry: Fp2, Rz: Fp2, Qx: Fp2, Qy: Fp2) => {
|
||||
Rx: Fp2;
|
||||
Ry: Fp2;
|
||||
Rz: Fp2;
|
||||
};
|
||||
export type PostPrecomputeFn = (Rx: Fp2, Ry: Fp2, Rz: Fp2, Qx: Fp2, Qy: Fp2, pointAdd: PostPrecomputePointAddFn) => void;
|
||||
export type BlsPairing = {
|
||||
Fp12: Fp12Bls;
|
||||
calcPairingPrecomputes: (p: WeierstrassPoint<Fp2>) => Precompute;
|
||||
millerLoopBatch: (pairs: [Precompute, Fp, Fp][]) => Fp12;
|
||||
pairing: (P: WeierstrassPoint<Fp>, Q: WeierstrassPoint<Fp2>, withFinalExponent?: boolean) => Fp12;
|
||||
pairingBatch: (pairs: {
|
||||
g1: WeierstrassPoint<Fp>;
|
||||
g2: WeierstrassPoint<Fp2>;
|
||||
}[], withFinalExponent?: boolean) => Fp12;
|
||||
};
|
||||
export type BlsPairingParams = {
|
||||
ateLoopSize: bigint;
|
||||
xNegative: boolean;
|
||||
twistType: TwistType;
|
||||
postPrecompute?: PostPrecomputeFn;
|
||||
};
|
||||
export type CurveType = {
|
||||
G1: CurvePointsType<Fp> & {
|
||||
ShortSignature: SignatureCoder<Fp>;
|
||||
mapToCurve: MapToCurve<Fp>;
|
||||
htfDefaults: H2COpts;
|
||||
};
|
||||
G2: CurvePointsType<Fp2> & {
|
||||
Signature: SignatureCoder<Fp2>;
|
||||
mapToCurve: MapToCurve<Fp2>;
|
||||
htfDefaults: H2COpts;
|
||||
};
|
||||
fields: BlsFields;
|
||||
params: {
|
||||
ateLoopSize: BlsPairingParams['ateLoopSize'];
|
||||
xNegative: BlsPairingParams['xNegative'];
|
||||
r: bigint;
|
||||
twistType: BlsPairingParams['twistType'];
|
||||
};
|
||||
htfDefaults: H2COpts;
|
||||
hash: CHash;
|
||||
randomBytes?: (bytesLength?: number) => Uint8Array;
|
||||
postPrecompute?: PostPrecomputeFn;
|
||||
};
|
||||
type PrecomputeSingle = [Fp2, Fp2, Fp2][];
|
||||
type Precompute = PrecomputeSingle[];
|
||||
/**
|
||||
* BLS consists of two curves: G1 and G2:
|
||||
* - G1 is a subgroup of (x, y) E(Fq) over y² = x³ + 4.
|
||||
* - G2 is a subgroup of ((x₁, x₂+i), (y₁, y₂+i)) E(Fq²) over y² = x³ + 4(1 + i) where i is √-1
|
||||
*/
|
||||
export interface BLSCurvePair {
|
||||
longSignatures: BLSSigs<bigint, Fp2>;
|
||||
shortSignatures: BLSSigs<Fp2, bigint>;
|
||||
millerLoopBatch: BlsPairing['millerLoopBatch'];
|
||||
pairing: BlsPairing['pairing'];
|
||||
pairingBatch: BlsPairing['pairingBatch'];
|
||||
G1: {
|
||||
Point: WeierstrassPointCons<bigint>;
|
||||
} & H2CHasher<Fp>;
|
||||
G2: {
|
||||
Point: WeierstrassPointCons<Fp2>;
|
||||
} & H2CHasher<Fp2>;
|
||||
fields: {
|
||||
Fp: IField<Fp>;
|
||||
Fp2: Fp2Bls;
|
||||
Fp6: Fp6Bls;
|
||||
Fp12: Fp12Bls;
|
||||
Fr: IField<bigint>;
|
||||
};
|
||||
utils: {
|
||||
randomSecretKey: () => Uint8Array;
|
||||
/** @deprecated use randomSecretKey */
|
||||
randomPrivateKey: () => Uint8Array;
|
||||
calcPairingPrecomputes: BlsPairing['calcPairingPrecomputes'];
|
||||
};
|
||||
}
|
||||
export type CurveFn = BLSCurvePair & {
|
||||
/** @deprecated use `longSignatures.getPublicKey` */
|
||||
getPublicKey: (secretKey: PrivKey) => Uint8Array;
|
||||
/** @deprecated use `shortSignatures.getPublicKey` */
|
||||
getPublicKeyForShortSignatures: (secretKey: PrivKey) => Uint8Array;
|
||||
/** @deprecated use `longSignatures.sign` */
|
||||
sign: {
|
||||
(message: Hex, secretKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array;
|
||||
(message: WeierstrassPoint<Fp2>, secretKey: PrivKey, htfOpts?: htfBasicOpts): WeierstrassPoint<Fp2>;
|
||||
};
|
||||
/** @deprecated use `shortSignatures.sign` */
|
||||
signShortSignature: {
|
||||
(message: Hex, secretKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array;
|
||||
(message: WeierstrassPoint<Fp>, secretKey: PrivKey, htfOpts?: htfBasicOpts): WeierstrassPoint<Fp>;
|
||||
};
|
||||
/** @deprecated use `longSignatures.verify` */
|
||||
verify: (signature: Hex | WeierstrassPoint<Fp2>, message: Hex | WeierstrassPoint<Fp2>, publicKey: Hex | WeierstrassPoint<Fp>, htfOpts?: htfBasicOpts) => boolean;
|
||||
/** @deprecated use `shortSignatures.verify` */
|
||||
verifyShortSignature: (signature: Hex | WeierstrassPoint<Fp>, message: Hex | WeierstrassPoint<Fp>, publicKey: Hex | WeierstrassPoint<Fp2>, htfOpts?: htfBasicOpts) => boolean;
|
||||
verifyBatch: (signature: Hex | WeierstrassPoint<Fp2>, messages: (Hex | WeierstrassPoint<Fp2>)[], publicKeys: (Hex | WeierstrassPoint<Fp>)[], htfOpts?: htfBasicOpts) => boolean;
|
||||
/** @deprecated use `longSignatures.aggregatePublicKeys` */
|
||||
aggregatePublicKeys: {
|
||||
(publicKeys: Hex[]): Uint8Array;
|
||||
(publicKeys: WeierstrassPoint<Fp>[]): WeierstrassPoint<Fp>;
|
||||
};
|
||||
/** @deprecated use `longSignatures.aggregateSignatures` */
|
||||
aggregateSignatures: {
|
||||
(signatures: Hex[]): Uint8Array;
|
||||
(signatures: WeierstrassPoint<Fp2>[]): WeierstrassPoint<Fp2>;
|
||||
};
|
||||
/** @deprecated use `shortSignatures.aggregateSignatures` */
|
||||
aggregateShortSignatures: {
|
||||
(signatures: Hex[]): Uint8Array;
|
||||
(signatures: WeierstrassPoint<Fp>[]): WeierstrassPoint<Fp>;
|
||||
};
|
||||
G1: CurvePointsRes<Fp> & H2CHasher<Fp>;
|
||||
G2: CurvePointsRes<Fp2> & H2CHasher<Fp2>;
|
||||
/** @deprecated use `longSignatures.Signature` */
|
||||
Signature: SignatureCoder<Fp2>;
|
||||
/** @deprecated use `shortSignatures.Signature` */
|
||||
ShortSignature: ShortSignatureCoder<Fp>;
|
||||
params: {
|
||||
ateLoopSize: bigint;
|
||||
r: bigint;
|
||||
twistType: TwistType;
|
||||
/** @deprecated */
|
||||
G1b: bigint;
|
||||
/** @deprecated */
|
||||
G2b: Fp2;
|
||||
};
|
||||
};
|
||||
type BLSInput = Hex | Uint8Array;
|
||||
export interface BLSSigs<P, S> {
|
||||
getPublicKey(secretKey: PrivKey): WeierstrassPoint<P>;
|
||||
sign(hashedMessage: WeierstrassPoint<S>, secretKey: PrivKey): WeierstrassPoint<S>;
|
||||
verify(signature: WeierstrassPoint<S> | BLSInput, message: WeierstrassPoint<S>, publicKey: WeierstrassPoint<P> | BLSInput): boolean;
|
||||
verifyBatch: (signature: WeierstrassPoint<S> | BLSInput, messages: WeierstrassPoint<S>[], publicKeys: (WeierstrassPoint<P> | BLSInput)[]) => boolean;
|
||||
aggregatePublicKeys(publicKeys: (WeierstrassPoint<P> | BLSInput)[]): WeierstrassPoint<P>;
|
||||
aggregateSignatures(signatures: (WeierstrassPoint<S> | BLSInput)[]): WeierstrassPoint<S>;
|
||||
hash(message: Uint8Array, DST?: string | Uint8Array, hashOpts?: H2CHashOpts): WeierstrassPoint<S>;
|
||||
Signature: SignatureCoder<S>;
|
||||
}
|
||||
export declare function bls(CURVE: CurveType): CurveFn;
|
||||
export {};
|
||||
//# sourceMappingURL=bls.d.ts.map
|
||||
1
node_modules/@noble/curves/esm/abstract/bls.d.ts.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/bls.d.ts.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
408
node_modules/@noble/curves/esm/abstract/bls.js
generated
vendored
Normal file
408
node_modules/@noble/curves/esm/abstract/bls.js
generated
vendored
Normal file
@@ -0,0 +1,408 @@
|
||||
/**
|
||||
* BLS != BLS.
|
||||
* The file implements BLS (Boneh-Lynn-Shacham) signatures.
|
||||
* Used in both BLS (Barreto-Lynn-Scott) and BN (Barreto-Naehrig)
|
||||
* families of pairing-friendly curves.
|
||||
* Consists of two curves: G1 and G2:
|
||||
* - G1 is a subgroup of (x, y) E(Fq) over y² = x³ + 4.
|
||||
* - G2 is a subgroup of ((x₁, x₂+i), (y₁, y₂+i)) E(Fq²) over y² = x³ + 4(1 + i) where i is √-1
|
||||
* - Gt, created by bilinear (ate) pairing e(G1, G2), consists of p-th roots of unity in
|
||||
* Fq^k where k is embedding degree. Only degree 12 is currently supported, 24 is not.
|
||||
* Pairing is used to aggregate and verify signatures.
|
||||
* There are two modes of operation:
|
||||
* - Long signatures: X-byte keys + 2X-byte sigs (G1 keys + G2 sigs).
|
||||
* - Short signatures: 2X-byte keys + X-byte sigs (G2 keys + G1 sigs).
|
||||
* @module
|
||||
**/
|
||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||
import { abytes, ensureBytes, memoized, randomBytes, } from "../utils.js";
|
||||
import { normalizeZ } from "./curve.js";
|
||||
import { createHasher, } from "./hash-to-curve.js";
|
||||
import { getMinHashLength, mapHashToField } from "./modular.js";
|
||||
import { _normFnElement, weierstrassPoints, } from "./weierstrass.js";
|
||||
// prettier-ignore
|
||||
const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
|
||||
// Not used with BLS12-381 (no sequential `11` in X). Useful for other curves.
|
||||
function NAfDecomposition(a) {
|
||||
const res = [];
|
||||
// a>1 because of marker bit
|
||||
for (; a > _1n; a >>= _1n) {
|
||||
if ((a & _1n) === _0n)
|
||||
res.unshift(0);
|
||||
else if ((a & _3n) === _3n) {
|
||||
res.unshift(-1);
|
||||
a += _1n;
|
||||
}
|
||||
else
|
||||
res.unshift(1);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
function aNonEmpty(arr) {
|
||||
if (!Array.isArray(arr) || arr.length === 0)
|
||||
throw new Error('expected non-empty array');
|
||||
}
|
||||
// This should be enough for bn254, no need to export full stuff?
|
||||
function createBlsPairing(fields, G1, G2, params) {
|
||||
const { Fp2, Fp12 } = fields;
|
||||
const { twistType, ateLoopSize, xNegative, postPrecompute } = params;
|
||||
// Applies sparse multiplication as line function
|
||||
let lineFunction;
|
||||
if (twistType === 'multiplicative') {
|
||||
lineFunction = (c0, c1, c2, f, Px, Py) => Fp12.mul014(f, c0, Fp2.mul(c1, Px), Fp2.mul(c2, Py));
|
||||
}
|
||||
else if (twistType === 'divisive') {
|
||||
// NOTE: it should be [c0, c1, c2], but we use different order here to reduce complexity of
|
||||
// precompute calculations.
|
||||
lineFunction = (c0, c1, c2, f, Px, Py) => Fp12.mul034(f, Fp2.mul(c2, Py), Fp2.mul(c1, Px), c0);
|
||||
}
|
||||
else
|
||||
throw new Error('bls: unknown twist type');
|
||||
const Fp2div2 = Fp2.div(Fp2.ONE, Fp2.mul(Fp2.ONE, _2n));
|
||||
function pointDouble(ell, Rx, Ry, Rz) {
|
||||
const t0 = Fp2.sqr(Ry); // Ry²
|
||||
const t1 = Fp2.sqr(Rz); // Rz²
|
||||
const t2 = Fp2.mulByB(Fp2.mul(t1, _3n)); // 3 * T1 * B
|
||||
const t3 = Fp2.mul(t2, _3n); // 3 * T2
|
||||
const t4 = Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(Ry, Rz)), t1), t0); // (Ry + Rz)² - T1 - T0
|
||||
const c0 = Fp2.sub(t2, t0); // T2 - T0 (i)
|
||||
const c1 = Fp2.mul(Fp2.sqr(Rx), _3n); // 3 * Rx²
|
||||
const c2 = Fp2.neg(t4); // -T4 (-h)
|
||||
ell.push([c0, c1, c2]);
|
||||
Rx = Fp2.mul(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), Fp2div2); // ((T0 - T3) * Rx * Ry) / 2
|
||||
Ry = Fp2.sub(Fp2.sqr(Fp2.mul(Fp2.add(t0, t3), Fp2div2)), Fp2.mul(Fp2.sqr(t2), _3n)); // ((T0 + T3) / 2)² - 3 * T2²
|
||||
Rz = Fp2.mul(t0, t4); // T0 * T4
|
||||
return { Rx, Ry, Rz };
|
||||
}
|
||||
function pointAdd(ell, Rx, Ry, Rz, Qx, Qy) {
|
||||
// Addition
|
||||
const t0 = Fp2.sub(Ry, Fp2.mul(Qy, Rz)); // Ry - Qy * Rz
|
||||
const t1 = Fp2.sub(Rx, Fp2.mul(Qx, Rz)); // Rx - Qx * Rz
|
||||
const c0 = Fp2.sub(Fp2.mul(t0, Qx), Fp2.mul(t1, Qy)); // T0 * Qx - T1 * Qy == Ry * Qx - Rx * Qy
|
||||
const c1 = Fp2.neg(t0); // -T0 == Qy * Rz - Ry
|
||||
const c2 = t1; // == Rx - Qx * Rz
|
||||
ell.push([c0, c1, c2]);
|
||||
const t2 = Fp2.sqr(t1); // T1²
|
||||
const t3 = Fp2.mul(t2, t1); // T2 * T1
|
||||
const t4 = Fp2.mul(t2, Rx); // T2 * Rx
|
||||
const 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
|
||||
Ry = Fp2.sub(Fp2.mul(Fp2.sub(t4, t5), t0), Fp2.mul(t3, Ry)); // (T4 - T5) * T0 - T3 * Ry
|
||||
Rz = Fp2.mul(Rz, t3); // Rz * T3
|
||||
return { Rx, Ry, Rz };
|
||||
}
|
||||
// Pre-compute coefficients for sparse multiplication
|
||||
// Point addition and point double calculations is reused for coefficients
|
||||
// pointAdd happens only if bit set, so wNAF is reasonable. Unfortunately we cannot combine
|
||||
// add + double in windowed precomputes here, otherwise it would be single op (since X is static)
|
||||
const ATE_NAF = NAfDecomposition(ateLoopSize);
|
||||
const calcPairingPrecomputes = memoized((point) => {
|
||||
const p = point;
|
||||
const { x, y } = p.toAffine();
|
||||
// prettier-ignore
|
||||
const Qx = x, Qy = y, negQy = Fp2.neg(y);
|
||||
// prettier-ignore
|
||||
let Rx = Qx, Ry = Qy, Rz = Fp2.ONE;
|
||||
const ell = [];
|
||||
for (const bit of ATE_NAF) {
|
||||
const cur = [];
|
||||
({ Rx, Ry, Rz } = pointDouble(cur, Rx, Ry, Rz));
|
||||
if (bit)
|
||||
({ Rx, Ry, Rz } = pointAdd(cur, Rx, Ry, Rz, Qx, bit === -1 ? negQy : Qy));
|
||||
ell.push(cur);
|
||||
}
|
||||
if (postPrecompute) {
|
||||
const last = ell[ell.length - 1];
|
||||
postPrecompute(Rx, Ry, Rz, Qx, Qy, pointAdd.bind(null, last));
|
||||
}
|
||||
return ell;
|
||||
});
|
||||
function millerLoopBatch(pairs, withFinalExponent = false) {
|
||||
let f12 = Fp12.ONE;
|
||||
if (pairs.length) {
|
||||
const ellLen = pairs[0][0].length;
|
||||
for (let i = 0; i < ellLen; i++) {
|
||||
f12 = Fp12.sqr(f12); // This allows us to do sqr only one time for all pairings
|
||||
// NOTE: we apply multiple pairings in parallel here
|
||||
for (const [ell, Px, Py] of pairs) {
|
||||
for (const [c0, c1, c2] of ell[i])
|
||||
f12 = lineFunction(c0, c1, c2, f12, Px, Py);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (xNegative)
|
||||
f12 = Fp12.conjugate(f12);
|
||||
return withFinalExponent ? Fp12.finalExponentiate(f12) : f12;
|
||||
}
|
||||
// Calculates product of multiple pairings
|
||||
// This up to x2 faster than just `map(({g1, g2})=>pairing({g1,g2}))`
|
||||
function pairingBatch(pairs, withFinalExponent = true) {
|
||||
const res = [];
|
||||
// Cache precomputed toAffine for all points
|
||||
normalizeZ(G1, pairs.map(({ g1 }) => g1));
|
||||
normalizeZ(G2, pairs.map(({ g2 }) => g2));
|
||||
for (const { g1, g2 } of pairs) {
|
||||
if (g1.is0() || g2.is0())
|
||||
throw new Error('pairing is not available for ZERO point');
|
||||
// This uses toAffine inside
|
||||
g1.assertValidity();
|
||||
g2.assertValidity();
|
||||
const Qa = g1.toAffine();
|
||||
res.push([calcPairingPrecomputes(g2), Qa.x, Qa.y]);
|
||||
}
|
||||
return millerLoopBatch(res, withFinalExponent);
|
||||
}
|
||||
// Calculates bilinear pairing
|
||||
function pairing(Q, P, withFinalExponent = true) {
|
||||
return pairingBatch([{ g1: Q, g2: P }], withFinalExponent);
|
||||
}
|
||||
return {
|
||||
Fp12, // NOTE: we re-export Fp12 here because pairing results are Fp12!
|
||||
millerLoopBatch,
|
||||
pairing,
|
||||
pairingBatch,
|
||||
calcPairingPrecomputes,
|
||||
};
|
||||
}
|
||||
function createBlsSig(blsPairing, PubCurve, SigCurve, SignatureCoder, isSigG1) {
|
||||
const { Fp12, pairingBatch } = blsPairing;
|
||||
function normPub(point) {
|
||||
return point instanceof PubCurve.Point ? point : PubCurve.Point.fromHex(point);
|
||||
}
|
||||
function normSig(point) {
|
||||
return point instanceof SigCurve.Point ? point : SigCurve.Point.fromHex(point);
|
||||
}
|
||||
function amsg(m) {
|
||||
if (!(m instanceof SigCurve.Point))
|
||||
throw new Error(`expected valid message hashed to ${!isSigG1 ? 'G2' : 'G1'} curve`);
|
||||
return m;
|
||||
}
|
||||
// What matters here is what point pairing API accepts as G1 or G2, not actual size or names
|
||||
const pair = !isSigG1
|
||||
? (a, b) => ({ g1: a, g2: b })
|
||||
: (a, b) => ({ g1: b, g2: a });
|
||||
return {
|
||||
// P = pk x G
|
||||
getPublicKey(secretKey) {
|
||||
// TODO: replace with
|
||||
// const sec = PubCurve.Point.Fn.fromBytes(secretKey);
|
||||
const sec = _normFnElement(PubCurve.Point.Fn, secretKey);
|
||||
return PubCurve.Point.BASE.multiply(sec);
|
||||
},
|
||||
// S = pk x H(m)
|
||||
sign(message, secretKey, unusedArg) {
|
||||
if (unusedArg != null)
|
||||
throw new Error('sign() expects 2 arguments');
|
||||
// TODO: replace with
|
||||
// PubCurve.Point.Fn.fromBytes(secretKey)
|
||||
const sec = _normFnElement(PubCurve.Point.Fn, secretKey);
|
||||
amsg(message).assertValidity();
|
||||
return message.multiply(sec);
|
||||
},
|
||||
// Checks if pairing of public key & hash is equal to pairing of generator & signature.
|
||||
// e(P, H(m)) == e(G, S)
|
||||
// e(S, G) == e(H(m), P)
|
||||
verify(signature, message, publicKey, unusedArg) {
|
||||
if (unusedArg != null)
|
||||
throw new Error('verify() expects 3 arguments');
|
||||
signature = normSig(signature);
|
||||
publicKey = normPub(publicKey);
|
||||
const P = publicKey.negate();
|
||||
const G = PubCurve.Point.BASE;
|
||||
const Hm = amsg(message);
|
||||
const S = signature;
|
||||
// This code was changed in 1.9.x:
|
||||
// Before it was G.negate() in G2, now it's always pubKey.negate
|
||||
// e(P, -Q)===e(-P, Q)==e(P, Q)^-1. Negate can be done anywhere (as long it is done once per pair).
|
||||
// We just moving sign, but since pairing is multiplicative, we doing X * X^-1 = 1
|
||||
const exp = pairingBatch([pair(P, Hm), pair(G, S)]);
|
||||
return Fp12.eql(exp, Fp12.ONE);
|
||||
},
|
||||
// https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407
|
||||
// e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))
|
||||
// TODO: maybe `{message: G2Hex, publicKey: G1Hex}[]` instead?
|
||||
verifyBatch(signature, messages, publicKeys) {
|
||||
aNonEmpty(messages);
|
||||
if (publicKeys.length !== messages.length)
|
||||
throw new Error('amount of public keys and messages should be equal');
|
||||
const sig = normSig(signature);
|
||||
const nMessages = messages;
|
||||
const nPublicKeys = publicKeys.map(normPub);
|
||||
// NOTE: this works only for exact same object
|
||||
const messagePubKeyMap = new Map();
|
||||
for (let i = 0; i < nPublicKeys.length; i++) {
|
||||
const pub = nPublicKeys[i];
|
||||
const msg = nMessages[i];
|
||||
let keys = messagePubKeyMap.get(msg);
|
||||
if (keys === undefined) {
|
||||
keys = [];
|
||||
messagePubKeyMap.set(msg, keys);
|
||||
}
|
||||
keys.push(pub);
|
||||
}
|
||||
const paired = [];
|
||||
const G = PubCurve.Point.BASE;
|
||||
try {
|
||||
for (const [msg, keys] of messagePubKeyMap) {
|
||||
const groupPublicKey = keys.reduce((acc, msg) => acc.add(msg));
|
||||
paired.push(pair(groupPublicKey, msg));
|
||||
}
|
||||
paired.push(pair(G.negate(), sig));
|
||||
return Fp12.eql(pairingBatch(paired), Fp12.ONE);
|
||||
}
|
||||
catch {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
// Adds a bunch of public key points together.
|
||||
// pk1 + pk2 + pk3 = pkA
|
||||
aggregatePublicKeys(publicKeys) {
|
||||
aNonEmpty(publicKeys);
|
||||
publicKeys = publicKeys.map((pub) => normPub(pub));
|
||||
const agg = publicKeys.reduce((sum, p) => sum.add(p), PubCurve.Point.ZERO);
|
||||
agg.assertValidity();
|
||||
return agg;
|
||||
},
|
||||
// Adds a bunch of signature points together.
|
||||
// pk1 + pk2 + pk3 = pkA
|
||||
aggregateSignatures(signatures) {
|
||||
aNonEmpty(signatures);
|
||||
signatures = signatures.map((sig) => normSig(sig));
|
||||
const agg = signatures.reduce((sum, s) => sum.add(s), SigCurve.Point.ZERO);
|
||||
agg.assertValidity();
|
||||
return agg;
|
||||
},
|
||||
hash(messageBytes, DST) {
|
||||
abytes(messageBytes);
|
||||
const opts = DST ? { DST } : undefined;
|
||||
return SigCurve.hashToCurve(messageBytes, opts);
|
||||
},
|
||||
Signature: SignatureCoder,
|
||||
};
|
||||
}
|
||||
// G1_Point: ProjConstructor<bigint>, G2_Point: ProjConstructor<Fp2>,
|
||||
export function bls(CURVE) {
|
||||
// Fields are specific for curve, so for now we'll need to pass them with opts
|
||||
const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE.fields;
|
||||
// Point on G1 curve: (x, y)
|
||||
const G1_ = weierstrassPoints(CURVE.G1);
|
||||
const G1 = Object.assign(G1_, createHasher(G1_.Point, CURVE.G1.mapToCurve, {
|
||||
...CURVE.htfDefaults,
|
||||
...CURVE.G1.htfDefaults,
|
||||
}));
|
||||
// Point on G2 curve (complex numbers): (x₁, x₂+i), (y₁, y₂+i)
|
||||
const G2_ = weierstrassPoints(CURVE.G2);
|
||||
const G2 = Object.assign(G2_, createHasher(G2_.Point, CURVE.G2.mapToCurve, {
|
||||
...CURVE.htfDefaults,
|
||||
...CURVE.G2.htfDefaults,
|
||||
}));
|
||||
const pairingRes = createBlsPairing(CURVE.fields, G1.Point, G2.Point, {
|
||||
...CURVE.params,
|
||||
postPrecompute: CURVE.postPrecompute,
|
||||
});
|
||||
const { millerLoopBatch, pairing, pairingBatch, calcPairingPrecomputes } = pairingRes;
|
||||
const longSignatures = createBlsSig(pairingRes, G1, G2, CURVE.G2.Signature, false);
|
||||
const shortSignatures = createBlsSig(pairingRes, G2, G1, CURVE.G1.ShortSignature, true);
|
||||
const rand = CURVE.randomBytes || randomBytes;
|
||||
const randomSecretKey = () => {
|
||||
const length = getMinHashLength(Fr.ORDER);
|
||||
return mapHashToField(rand(length), Fr.ORDER);
|
||||
};
|
||||
const utils = {
|
||||
randomSecretKey,
|
||||
randomPrivateKey: randomSecretKey,
|
||||
calcPairingPrecomputes,
|
||||
};
|
||||
const { ShortSignature } = CURVE.G1;
|
||||
const { Signature } = CURVE.G2;
|
||||
function normP1Hash(point, htfOpts) {
|
||||
return point instanceof G1.Point
|
||||
? point
|
||||
: shortSignatures.hash(ensureBytes('point', point), htfOpts?.DST);
|
||||
}
|
||||
function normP2Hash(point, htfOpts) {
|
||||
return point instanceof G2.Point
|
||||
? point
|
||||
: longSignatures.hash(ensureBytes('point', point), htfOpts?.DST);
|
||||
}
|
||||
function getPublicKey(privateKey) {
|
||||
return longSignatures.getPublicKey(privateKey).toBytes(true);
|
||||
}
|
||||
function getPublicKeyForShortSignatures(privateKey) {
|
||||
return shortSignatures.getPublicKey(privateKey).toBytes(true);
|
||||
}
|
||||
function sign(message, privateKey, htfOpts) {
|
||||
const Hm = normP2Hash(message, htfOpts);
|
||||
const S = longSignatures.sign(Hm, privateKey);
|
||||
return message instanceof G2.Point ? S : Signature.toBytes(S);
|
||||
}
|
||||
function signShortSignature(message, privateKey, htfOpts) {
|
||||
const Hm = normP1Hash(message, htfOpts);
|
||||
const S = shortSignatures.sign(Hm, privateKey);
|
||||
return message instanceof G1.Point ? S : ShortSignature.toBytes(S);
|
||||
}
|
||||
function verify(signature, message, publicKey, htfOpts) {
|
||||
const Hm = normP2Hash(message, htfOpts);
|
||||
return longSignatures.verify(signature, Hm, publicKey);
|
||||
}
|
||||
function verifyShortSignature(signature, message, publicKey, htfOpts) {
|
||||
const Hm = normP1Hash(message, htfOpts);
|
||||
return shortSignatures.verify(signature, Hm, publicKey);
|
||||
}
|
||||
function aggregatePublicKeys(publicKeys) {
|
||||
const agg = longSignatures.aggregatePublicKeys(publicKeys);
|
||||
return publicKeys[0] instanceof G1.Point ? agg : agg.toBytes(true);
|
||||
}
|
||||
function aggregateSignatures(signatures) {
|
||||
const agg = longSignatures.aggregateSignatures(signatures);
|
||||
return signatures[0] instanceof G2.Point ? agg : Signature.toBytes(agg);
|
||||
}
|
||||
function aggregateShortSignatures(signatures) {
|
||||
const agg = shortSignatures.aggregateSignatures(signatures);
|
||||
return signatures[0] instanceof G1.Point ? agg : ShortSignature.toBytes(agg);
|
||||
}
|
||||
function verifyBatch(signature, messages, publicKeys, htfOpts) {
|
||||
const Hm = messages.map((m) => normP2Hash(m, htfOpts));
|
||||
return longSignatures.verifyBatch(signature, Hm, publicKeys);
|
||||
}
|
||||
G1.Point.BASE.precompute(4);
|
||||
return {
|
||||
longSignatures,
|
||||
shortSignatures,
|
||||
millerLoopBatch,
|
||||
pairing,
|
||||
pairingBatch,
|
||||
verifyBatch,
|
||||
fields: {
|
||||
Fr,
|
||||
Fp,
|
||||
Fp2,
|
||||
Fp6,
|
||||
Fp12,
|
||||
},
|
||||
params: {
|
||||
ateLoopSize: CURVE.params.ateLoopSize,
|
||||
twistType: CURVE.params.twistType,
|
||||
// deprecated
|
||||
r: CURVE.params.r,
|
||||
G1b: CURVE.G1.b,
|
||||
G2b: CURVE.G2.b,
|
||||
},
|
||||
utils,
|
||||
// deprecated
|
||||
getPublicKey,
|
||||
getPublicKeyForShortSignatures,
|
||||
sign,
|
||||
signShortSignature,
|
||||
verify,
|
||||
verifyShortSignature,
|
||||
aggregatePublicKeys,
|
||||
aggregateSignatures,
|
||||
aggregateShortSignatures,
|
||||
G1,
|
||||
G2,
|
||||
Signature,
|
||||
ShortSignature,
|
||||
};
|
||||
}
|
||||
//# sourceMappingURL=bls.js.map
|
||||
1
node_modules/@noble/curves/esm/abstract/bls.js.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/bls.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
231
node_modules/@noble/curves/esm/abstract/curve.d.ts
generated
vendored
Normal file
231
node_modules/@noble/curves/esm/abstract/curve.d.ts
generated
vendored
Normal file
@@ -0,0 +1,231 @@
|
||||
import { type IField } from './modular.ts';
|
||||
export type AffinePoint<T> = {
|
||||
x: T;
|
||||
y: T;
|
||||
} & {
|
||||
Z?: never;
|
||||
};
|
||||
export interface Group<T extends Group<T>> {
|
||||
double(): T;
|
||||
negate(): T;
|
||||
add(other: T): T;
|
||||
subtract(other: T): T;
|
||||
equals(other: T): boolean;
|
||||
multiply(scalar: bigint): T;
|
||||
toAffine?(invertedZ?: any): AffinePoint<any>;
|
||||
}
|
||||
/** Base interface for all elliptic curve Points. */
|
||||
export interface CurvePoint<F, P extends CurvePoint<F, P>> extends Group<P> {
|
||||
/** Affine x coordinate. Different from projective / extended X coordinate. */
|
||||
x: F;
|
||||
/** Affine y coordinate. Different from projective / extended Y coordinate. */
|
||||
y: F;
|
||||
Z?: F;
|
||||
double(): P;
|
||||
negate(): P;
|
||||
add(other: P): P;
|
||||
subtract(other: P): P;
|
||||
equals(other: P): boolean;
|
||||
multiply(scalar: bigint): P;
|
||||
assertValidity(): void;
|
||||
clearCofactor(): P;
|
||||
is0(): boolean;
|
||||
isTorsionFree(): boolean;
|
||||
isSmallOrder(): boolean;
|
||||
multiplyUnsafe(scalar: bigint): P;
|
||||
/**
|
||||
* Massively speeds up `p.multiply(n)` by using precompute tables (caching). See {@link wNAF}.
|
||||
* @param isLazy calculate cache now. Default (true) ensures it's deferred to first `multiply()`
|
||||
*/
|
||||
precompute(windowSize?: number, isLazy?: boolean): P;
|
||||
/** Converts point to 2D xy affine coordinates */
|
||||
toAffine(invertedZ?: F): AffinePoint<F>;
|
||||
toBytes(): Uint8Array;
|
||||
toHex(): string;
|
||||
}
|
||||
/** Base interface for all elliptic curve Point constructors. */
|
||||
export interface CurvePointCons<P extends CurvePoint<any, P>> {
|
||||
[Symbol.hasInstance]: (item: unknown) => boolean;
|
||||
BASE: P;
|
||||
ZERO: P;
|
||||
/** Field for basic curve math */
|
||||
Fp: IField<P_F<P>>;
|
||||
/** Scalar field, for scalars in multiply and others */
|
||||
Fn: IField<bigint>;
|
||||
/** Creates point from x, y. Does NOT validate if the point is valid. Use `.assertValidity()`. */
|
||||
fromAffine(p: AffinePoint<P_F<P>>): P;
|
||||
fromBytes(bytes: Uint8Array): P;
|
||||
fromHex(hex: Uint8Array | string): P;
|
||||
}
|
||||
/** Returns Fp type from Point (P_F<P> == P.F) */
|
||||
export type P_F<P extends CurvePoint<any, P>> = P extends CurvePoint<infer F, P> ? F : never;
|
||||
/** Returns Fp type from PointCons (PC_F<PC> == PC.P.F) */
|
||||
export type PC_F<PC extends CurvePointCons<CurvePoint<any, any>>> = PC['Fp']['ZERO'];
|
||||
/** Returns Point type from PointCons (PC_P<PC> == PC.P) */
|
||||
export type PC_P<PC extends CurvePointCons<CurvePoint<any, any>>> = PC['ZERO'];
|
||||
export type PC_ANY = CurvePointCons<CurvePoint<any, CurvePoint<any, CurvePoint<any, CurvePoint<any, CurvePoint<any, CurvePoint<any, CurvePoint<any, CurvePoint<any, CurvePoint<any, CurvePoint<any, any>>>>>>>>>>>;
|
||||
export interface CurveLengths {
|
||||
secretKey?: number;
|
||||
publicKey?: number;
|
||||
publicKeyUncompressed?: number;
|
||||
publicKeyHasPrefix?: boolean;
|
||||
signature?: number;
|
||||
seed?: number;
|
||||
}
|
||||
export type GroupConstructor<T> = {
|
||||
BASE: T;
|
||||
ZERO: T;
|
||||
};
|
||||
/** @deprecated */
|
||||
export type ExtendedGroupConstructor<T> = GroupConstructor<T> & {
|
||||
Fp: IField<any>;
|
||||
Fn: IField<bigint>;
|
||||
fromAffine(ap: AffinePoint<any>): T;
|
||||
};
|
||||
export type Mapper<T> = (i: T[]) => T[];
|
||||
export declare function negateCt<T extends {
|
||||
negate: () => T;
|
||||
}>(condition: boolean, item: T): T;
|
||||
/**
|
||||
* Takes a bunch of Projective Points but executes only one
|
||||
* inversion on all of them. Inversion is very slow operation,
|
||||
* so this improves performance massively.
|
||||
* Optimization: converts a list of projective points to a list of identical points with Z=1.
|
||||
*/
|
||||
export declare function normalizeZ<P extends CurvePoint<any, P>, PC extends CurvePointCons<P>>(c: PC, points: P[]): P[];
|
||||
/** Internal wNAF opts for specific W and scalarBits */
|
||||
export type WOpts = {
|
||||
windows: number;
|
||||
windowSize: number;
|
||||
mask: bigint;
|
||||
maxNumber: number;
|
||||
shiftBy: bigint;
|
||||
};
|
||||
/**
|
||||
* Elliptic curve multiplication of Point by scalar. Fragile.
|
||||
* Table generation takes **30MB of ram and 10ms on high-end CPU**,
|
||||
* but may take much longer on slow devices. Actual generation will happen on
|
||||
* first call of `multiply()`. By default, `BASE` point is precomputed.
|
||||
*
|
||||
* Scalars should always be less than curve order: this should be checked inside of a curve itself.
|
||||
* Creates precomputation tables for fast multiplication:
|
||||
* - private scalar is split by fixed size windows of W bits
|
||||
* - every window point is collected from window's table & added to accumulator
|
||||
* - since windows are different, same point inside tables won't be accessed more than once per calc
|
||||
* - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar)
|
||||
* - +1 window is neccessary for wNAF
|
||||
* - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication
|
||||
*
|
||||
* @todo Research returning 2d JS array of windows, instead of a single window.
|
||||
* This would allow windows to be in different memory locations
|
||||
*/
|
||||
export declare class wNAF<PC extends PC_ANY> {
|
||||
private readonly BASE;
|
||||
private readonly ZERO;
|
||||
private readonly Fn;
|
||||
readonly bits: number;
|
||||
constructor(Point: PC, bits: number);
|
||||
_unsafeLadder(elm: PC_P<PC>, n: bigint, p?: PC_P<PC>): PC_P<PC>;
|
||||
/**
|
||||
* Creates a wNAF precomputation window. Used for caching.
|
||||
* Default window size is set by `utils.precompute()` and is equal to 8.
|
||||
* Number of precomputed points depends on the curve size:
|
||||
* 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:
|
||||
* - 𝑊 is the window size
|
||||
* - 𝑛 is the bitlength of the curve order.
|
||||
* For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.
|
||||
* @param point Point instance
|
||||
* @param W window size
|
||||
* @returns precomputed point tables flattened to a single array
|
||||
*/
|
||||
private precomputeWindow;
|
||||
/**
|
||||
* Implements ec multiplication using precomputed tables and w-ary non-adjacent form.
|
||||
* More compact implementation:
|
||||
* https://github.com/paulmillr/noble-secp256k1/blob/47cb1669b6e506ad66b35fe7d76132ae97465da2/index.ts#L502-L541
|
||||
* @returns real and fake (for const-time) points
|
||||
*/
|
||||
private wNAF;
|
||||
/**
|
||||
* Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form.
|
||||
* @param acc accumulator point to add result of multiplication
|
||||
* @returns point
|
||||
*/
|
||||
private wNAFUnsafe;
|
||||
private getPrecomputes;
|
||||
cached(point: PC_P<PC>, scalar: bigint, transform?: Mapper<PC_P<PC>>): {
|
||||
p: PC_P<PC>;
|
||||
f: PC_P<PC>;
|
||||
};
|
||||
unsafe(point: PC_P<PC>, scalar: bigint, transform?: Mapper<PC_P<PC>>, prev?: PC_P<PC>): PC_P<PC>;
|
||||
createCache(P: PC_P<PC>, W: number): void;
|
||||
hasCache(elm: PC_P<PC>): boolean;
|
||||
}
|
||||
/**
|
||||
* Endomorphism-specific multiplication for Koblitz curves.
|
||||
* Cost: 128 dbl, 0-256 adds.
|
||||
*/
|
||||
export declare function mulEndoUnsafe<P extends CurvePoint<any, P>, PC extends CurvePointCons<P>>(Point: PC, point: P, k1: bigint, k2: bigint): {
|
||||
p1: P;
|
||||
p2: P;
|
||||
};
|
||||
/**
|
||||
* Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...).
|
||||
* 30x faster vs naive addition on L=4096, 10x faster than precomputes.
|
||||
* For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL.
|
||||
* Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0.
|
||||
* @param c Curve Point constructor
|
||||
* @param fieldN field over CURVE.N - important that it's not over CURVE.P
|
||||
* @param points array of L curve points
|
||||
* @param scalars array of L scalars (aka secret keys / bigints)
|
||||
*/
|
||||
export declare function pippenger<P extends CurvePoint<any, P>, PC extends CurvePointCons<P>>(c: PC, fieldN: IField<bigint>, points: P[], scalars: bigint[]): P;
|
||||
/**
|
||||
* Precomputed multi-scalar multiplication (MSM, Pa + Qb + Rc + ...).
|
||||
* @param c Curve Point constructor
|
||||
* @param fieldN field over CURVE.N - important that it's not over CURVE.P
|
||||
* @param points array of L curve points
|
||||
* @returns function which multiplies points with scaars
|
||||
*/
|
||||
export declare function precomputeMSMUnsafe<P extends CurvePoint<any, P>, PC extends CurvePointCons<P>>(c: PC, fieldN: IField<bigint>, points: P[], windowSize: number): (scalars: bigint[]) => P;
|
||||
/**
|
||||
* Generic BasicCurve interface: works even for polynomial fields (BLS): P, n, h would be ok.
|
||||
* Though generator can be different (Fp2 / Fp6 for BLS).
|
||||
*/
|
||||
export type BasicCurve<T> = {
|
||||
Fp: IField<T>;
|
||||
n: bigint;
|
||||
nBitLength?: number;
|
||||
nByteLength?: number;
|
||||
h: bigint;
|
||||
hEff?: bigint;
|
||||
Gx: T;
|
||||
Gy: T;
|
||||
allowInfinityPoint?: boolean;
|
||||
};
|
||||
/** @deprecated */
|
||||
export declare function validateBasic<FP, T>(curve: BasicCurve<FP> & T): Readonly<{
|
||||
readonly nBitLength: number;
|
||||
readonly nByteLength: number;
|
||||
} & BasicCurve<FP> & T & {
|
||||
p: bigint;
|
||||
}>;
|
||||
export type ValidCurveParams<T> = {
|
||||
p: bigint;
|
||||
n: bigint;
|
||||
h: bigint;
|
||||
a: T;
|
||||
b?: T;
|
||||
d?: T;
|
||||
Gx: T;
|
||||
Gy: T;
|
||||
};
|
||||
export type FpFn<T> = {
|
||||
Fp: IField<T>;
|
||||
Fn: IField<bigint>;
|
||||
};
|
||||
/** Validates CURVE opts and creates fields */
|
||||
export declare function _createCurveFields<T>(type: 'weierstrass' | 'edwards', CURVE: ValidCurveParams<T>, curveOpts?: Partial<FpFn<T>>, FpFnLE?: boolean): FpFn<T> & {
|
||||
CURVE: ValidCurveParams<T>;
|
||||
};
|
||||
//# sourceMappingURL=curve.d.ts.map
|
||||
1
node_modules/@noble/curves/esm/abstract/curve.d.ts.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/curve.d.ts.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
465
node_modules/@noble/curves/esm/abstract/curve.js
generated
vendored
Normal file
465
node_modules/@noble/curves/esm/abstract/curve.js
generated
vendored
Normal file
@@ -0,0 +1,465 @@
|
||||
/**
|
||||
* Methods for elliptic curve multiplication by scalars.
|
||||
* Contains wNAF, pippenger.
|
||||
* @module
|
||||
*/
|
||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||
import { bitLen, bitMask, validateObject } from "../utils.js";
|
||||
import { Field, FpInvertBatch, nLength, validateField } from "./modular.js";
|
||||
const _0n = BigInt(0);
|
||||
const _1n = BigInt(1);
|
||||
export function negateCt(condition, item) {
|
||||
const neg = item.negate();
|
||||
return condition ? neg : item;
|
||||
}
|
||||
/**
|
||||
* Takes a bunch of Projective Points but executes only one
|
||||
* inversion on all of them. Inversion is very slow operation,
|
||||
* so this improves performance massively.
|
||||
* Optimization: converts a list of projective points to a list of identical points with Z=1.
|
||||
*/
|
||||
export function normalizeZ(c, points) {
|
||||
const invertedZs = FpInvertBatch(c.Fp, points.map((p) => p.Z));
|
||||
return points.map((p, i) => c.fromAffine(p.toAffine(invertedZs[i])));
|
||||
}
|
||||
function validateW(W, bits) {
|
||||
if (!Number.isSafeInteger(W) || W <= 0 || W > bits)
|
||||
throw new Error('invalid window size, expected [1..' + bits + '], got W=' + W);
|
||||
}
|
||||
function calcWOpts(W, scalarBits) {
|
||||
validateW(W, scalarBits);
|
||||
const windows = Math.ceil(scalarBits / W) + 1; // W=8 33. Not 32, because we skip zero
|
||||
const windowSize = 2 ** (W - 1); // W=8 128. Not 256, because we skip zero
|
||||
const maxNumber = 2 ** W; // W=8 256
|
||||
const mask = bitMask(W); // W=8 255 == mask 0b11111111
|
||||
const shiftBy = BigInt(W); // W=8 8
|
||||
return { windows, windowSize, mask, maxNumber, shiftBy };
|
||||
}
|
||||
function calcOffsets(n, window, wOpts) {
|
||||
const { windowSize, mask, maxNumber, shiftBy } = wOpts;
|
||||
let wbits = Number(n & mask); // extract W bits.
|
||||
let nextN = n >> shiftBy; // shift number by W bits.
|
||||
// What actually happens here:
|
||||
// const highestBit = Number(mask ^ (mask >> 1n));
|
||||
// let wbits2 = wbits - 1; // skip zero
|
||||
// if (wbits2 & highestBit) { wbits2 ^= Number(mask); // (~);
|
||||
// split if bits > max: +224 => 256-32
|
||||
if (wbits > windowSize) {
|
||||
// we skip zero, which means instead of `>= size-1`, we do `> size`
|
||||
wbits -= maxNumber; // -32, can be maxNumber - wbits, but then we need to set isNeg here.
|
||||
nextN += _1n; // +256 (carry)
|
||||
}
|
||||
const offsetStart = window * windowSize;
|
||||
const offset = offsetStart + Math.abs(wbits) - 1; // -1 because we skip zero
|
||||
const isZero = wbits === 0; // is current window slice a 0?
|
||||
const isNeg = wbits < 0; // is current window slice negative?
|
||||
const isNegF = window % 2 !== 0; // fake random statement for noise
|
||||
const offsetF = offsetStart; // fake offset for noise
|
||||
return { nextN, offset, isZero, isNeg, isNegF, offsetF };
|
||||
}
|
||||
function validateMSMPoints(points, c) {
|
||||
if (!Array.isArray(points))
|
||||
throw new Error('array expected');
|
||||
points.forEach((p, i) => {
|
||||
if (!(p instanceof c))
|
||||
throw new Error('invalid point at index ' + i);
|
||||
});
|
||||
}
|
||||
function validateMSMScalars(scalars, field) {
|
||||
if (!Array.isArray(scalars))
|
||||
throw new Error('array of scalars expected');
|
||||
scalars.forEach((s, i) => {
|
||||
if (!field.isValid(s))
|
||||
throw new Error('invalid scalar at index ' + i);
|
||||
});
|
||||
}
|
||||
// Since points in different groups cannot be equal (different object constructor),
|
||||
// we can have single place to store precomputes.
|
||||
// Allows to make points frozen / immutable.
|
||||
const pointPrecomputes = new WeakMap();
|
||||
const pointWindowSizes = new WeakMap();
|
||||
function getW(P) {
|
||||
// To disable precomputes:
|
||||
// return 1;
|
||||
return pointWindowSizes.get(P) || 1;
|
||||
}
|
||||
function assert0(n) {
|
||||
if (n !== _0n)
|
||||
throw new Error('invalid wNAF');
|
||||
}
|
||||
/**
|
||||
* Elliptic curve multiplication of Point by scalar. Fragile.
|
||||
* Table generation takes **30MB of ram and 10ms on high-end CPU**,
|
||||
* but may take much longer on slow devices. Actual generation will happen on
|
||||
* first call of `multiply()`. By default, `BASE` point is precomputed.
|
||||
*
|
||||
* Scalars should always be less than curve order: this should be checked inside of a curve itself.
|
||||
* Creates precomputation tables for fast multiplication:
|
||||
* - private scalar is split by fixed size windows of W bits
|
||||
* - every window point is collected from window's table & added to accumulator
|
||||
* - since windows are different, same point inside tables won't be accessed more than once per calc
|
||||
* - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar)
|
||||
* - +1 window is neccessary for wNAF
|
||||
* - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication
|
||||
*
|
||||
* @todo Research returning 2d JS array of windows, instead of a single window.
|
||||
* This would allow windows to be in different memory locations
|
||||
*/
|
||||
export class wNAF {
|
||||
// Parametrized with a given Point class (not individual point)
|
||||
constructor(Point, bits) {
|
||||
this.BASE = Point.BASE;
|
||||
this.ZERO = Point.ZERO;
|
||||
this.Fn = Point.Fn;
|
||||
this.bits = bits;
|
||||
}
|
||||
// non-const time multiplication ladder
|
||||
_unsafeLadder(elm, n, p = this.ZERO) {
|
||||
let d = elm;
|
||||
while (n > _0n) {
|
||||
if (n & _1n)
|
||||
p = p.add(d);
|
||||
d = d.double();
|
||||
n >>= _1n;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
/**
|
||||
* Creates a wNAF precomputation window. Used for caching.
|
||||
* Default window size is set by `utils.precompute()` and is equal to 8.
|
||||
* Number of precomputed points depends on the curve size:
|
||||
* 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:
|
||||
* - 𝑊 is the window size
|
||||
* - 𝑛 is the bitlength of the curve order.
|
||||
* For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.
|
||||
* @param point Point instance
|
||||
* @param W window size
|
||||
* @returns precomputed point tables flattened to a single array
|
||||
*/
|
||||
precomputeWindow(point, W) {
|
||||
const { windows, windowSize } = calcWOpts(W, this.bits);
|
||||
const points = [];
|
||||
let p = point;
|
||||
let base = p;
|
||||
for (let window = 0; window < windows; window++) {
|
||||
base = p;
|
||||
points.push(base);
|
||||
// i=1, bc we skip 0
|
||||
for (let i = 1; i < windowSize; i++) {
|
||||
base = base.add(p);
|
||||
points.push(base);
|
||||
}
|
||||
p = base.double();
|
||||
}
|
||||
return points;
|
||||
}
|
||||
/**
|
||||
* Implements ec multiplication using precomputed tables and w-ary non-adjacent form.
|
||||
* More compact implementation:
|
||||
* https://github.com/paulmillr/noble-secp256k1/blob/47cb1669b6e506ad66b35fe7d76132ae97465da2/index.ts#L502-L541
|
||||
* @returns real and fake (for const-time) points
|
||||
*/
|
||||
wNAF(W, precomputes, n) {
|
||||
// Scalar should be smaller than field order
|
||||
if (!this.Fn.isValid(n))
|
||||
throw new Error('invalid scalar');
|
||||
// Accumulators
|
||||
let p = this.ZERO;
|
||||
let f = this.BASE;
|
||||
// This code was first written with assumption that 'f' and 'p' will never be infinity point:
|
||||
// since each addition is multiplied by 2 ** W, it cannot cancel each other. However,
|
||||
// there is negate now: it is possible that negated element from low value
|
||||
// would be the same as high element, which will create carry into next window.
|
||||
// It's not obvious how this can fail, but still worth investigating later.
|
||||
const wo = calcWOpts(W, this.bits);
|
||||
for (let window = 0; window < wo.windows; window++) {
|
||||
// (n === _0n) is handled and not early-exited. isEven and offsetF are used for noise
|
||||
const { nextN, offset, isZero, isNeg, isNegF, offsetF } = calcOffsets(n, window, wo);
|
||||
n = nextN;
|
||||
if (isZero) {
|
||||
// bits are 0: add garbage to fake point
|
||||
// Important part for const-time getPublicKey: add random "noise" point to f.
|
||||
f = f.add(negateCt(isNegF, precomputes[offsetF]));
|
||||
}
|
||||
else {
|
||||
// bits are 1: add to result point
|
||||
p = p.add(negateCt(isNeg, precomputes[offset]));
|
||||
}
|
||||
}
|
||||
assert0(n);
|
||||
// Return both real and fake points: JIT won't eliminate f.
|
||||
// At this point there is a way to F be infinity-point even if p is not,
|
||||
// which makes it less const-time: around 1 bigint multiply.
|
||||
return { p, f };
|
||||
}
|
||||
/**
|
||||
* Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form.
|
||||
* @param acc accumulator point to add result of multiplication
|
||||
* @returns point
|
||||
*/
|
||||
wNAFUnsafe(W, precomputes, n, acc = this.ZERO) {
|
||||
const wo = calcWOpts(W, this.bits);
|
||||
for (let window = 0; window < wo.windows; window++) {
|
||||
if (n === _0n)
|
||||
break; // Early-exit, skip 0 value
|
||||
const { nextN, offset, isZero, isNeg } = calcOffsets(n, window, wo);
|
||||
n = nextN;
|
||||
if (isZero) {
|
||||
// Window bits are 0: skip processing.
|
||||
// Move to next window.
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
const item = precomputes[offset];
|
||||
acc = acc.add(isNeg ? item.negate() : item); // Re-using acc allows to save adds in MSM
|
||||
}
|
||||
}
|
||||
assert0(n);
|
||||
return acc;
|
||||
}
|
||||
getPrecomputes(W, point, transform) {
|
||||
// Calculate precomputes on a first run, reuse them after
|
||||
let comp = pointPrecomputes.get(point);
|
||||
if (!comp) {
|
||||
comp = this.precomputeWindow(point, W);
|
||||
if (W !== 1) {
|
||||
// Doing transform outside of if brings 15% perf hit
|
||||
if (typeof transform === 'function')
|
||||
comp = transform(comp);
|
||||
pointPrecomputes.set(point, comp);
|
||||
}
|
||||
}
|
||||
return comp;
|
||||
}
|
||||
cached(point, scalar, transform) {
|
||||
const W = getW(point);
|
||||
return this.wNAF(W, this.getPrecomputes(W, point, transform), scalar);
|
||||
}
|
||||
unsafe(point, scalar, transform, prev) {
|
||||
const W = getW(point);
|
||||
if (W === 1)
|
||||
return this._unsafeLadder(point, scalar, prev); // For W=1 ladder is ~x2 faster
|
||||
return this.wNAFUnsafe(W, this.getPrecomputes(W, point, transform), scalar, prev);
|
||||
}
|
||||
// We calculate precomputes for elliptic curve point multiplication
|
||||
// using windowed method. This specifies window size and
|
||||
// stores precomputed values. Usually only base point would be precomputed.
|
||||
createCache(P, W) {
|
||||
validateW(W, this.bits);
|
||||
pointWindowSizes.set(P, W);
|
||||
pointPrecomputes.delete(P);
|
||||
}
|
||||
hasCache(elm) {
|
||||
return getW(elm) !== 1;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Endomorphism-specific multiplication for Koblitz curves.
|
||||
* Cost: 128 dbl, 0-256 adds.
|
||||
*/
|
||||
export function mulEndoUnsafe(Point, point, k1, k2) {
|
||||
let acc = point;
|
||||
let p1 = Point.ZERO;
|
||||
let p2 = Point.ZERO;
|
||||
while (k1 > _0n || k2 > _0n) {
|
||||
if (k1 & _1n)
|
||||
p1 = p1.add(acc);
|
||||
if (k2 & _1n)
|
||||
p2 = p2.add(acc);
|
||||
acc = acc.double();
|
||||
k1 >>= _1n;
|
||||
k2 >>= _1n;
|
||||
}
|
||||
return { p1, p2 };
|
||||
}
|
||||
/**
|
||||
* Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...).
|
||||
* 30x faster vs naive addition on L=4096, 10x faster than precomputes.
|
||||
* For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL.
|
||||
* Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0.
|
||||
* @param c Curve Point constructor
|
||||
* @param fieldN field over CURVE.N - important that it's not over CURVE.P
|
||||
* @param points array of L curve points
|
||||
* @param scalars array of L scalars (aka secret keys / bigints)
|
||||
*/
|
||||
export function pippenger(c, fieldN, points, scalars) {
|
||||
// If we split scalars by some window (let's say 8 bits), every chunk will only
|
||||
// take 256 buckets even if there are 4096 scalars, also re-uses double.
|
||||
// TODO:
|
||||
// - https://eprint.iacr.org/2024/750.pdf
|
||||
// - https://tches.iacr.org/index.php/TCHES/article/view/10287
|
||||
// 0 is accepted in scalars
|
||||
validateMSMPoints(points, c);
|
||||
validateMSMScalars(scalars, fieldN);
|
||||
const plength = points.length;
|
||||
const slength = scalars.length;
|
||||
if (plength !== slength)
|
||||
throw new Error('arrays of points and scalars must have equal length');
|
||||
// if (plength === 0) throw new Error('array must be of length >= 2');
|
||||
const zero = c.ZERO;
|
||||
const wbits = bitLen(BigInt(plength));
|
||||
let windowSize = 1; // bits
|
||||
if (wbits > 12)
|
||||
windowSize = wbits - 3;
|
||||
else if (wbits > 4)
|
||||
windowSize = wbits - 2;
|
||||
else if (wbits > 0)
|
||||
windowSize = 2;
|
||||
const MASK = bitMask(windowSize);
|
||||
const buckets = new Array(Number(MASK) + 1).fill(zero); // +1 for zero array
|
||||
const lastBits = Math.floor((fieldN.BITS - 1) / windowSize) * windowSize;
|
||||
let sum = zero;
|
||||
for (let i = lastBits; i >= 0; i -= windowSize) {
|
||||
buckets.fill(zero);
|
||||
for (let j = 0; j < slength; j++) {
|
||||
const scalar = scalars[j];
|
||||
const wbits = Number((scalar >> BigInt(i)) & MASK);
|
||||
buckets[wbits] = buckets[wbits].add(points[j]);
|
||||
}
|
||||
let resI = zero; // not using this will do small speed-up, but will lose ct
|
||||
// Skip first bucket, because it is zero
|
||||
for (let j = buckets.length - 1, sumI = zero; j > 0; j--) {
|
||||
sumI = sumI.add(buckets[j]);
|
||||
resI = resI.add(sumI);
|
||||
}
|
||||
sum = sum.add(resI);
|
||||
if (i !== 0)
|
||||
for (let j = 0; j < windowSize; j++)
|
||||
sum = sum.double();
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
/**
|
||||
* Precomputed multi-scalar multiplication (MSM, Pa + Qb + Rc + ...).
|
||||
* @param c Curve Point constructor
|
||||
* @param fieldN field over CURVE.N - important that it's not over CURVE.P
|
||||
* @param points array of L curve points
|
||||
* @returns function which multiplies points with scaars
|
||||
*/
|
||||
export function precomputeMSMUnsafe(c, fieldN, points, windowSize) {
|
||||
/**
|
||||
* Performance Analysis of Window-based Precomputation
|
||||
*
|
||||
* Base Case (256-bit scalar, 8-bit window):
|
||||
* - Standard precomputation requires:
|
||||
* - 31 additions per scalar × 256 scalars = 7,936 ops
|
||||
* - Plus 255 summary additions = 8,191 total ops
|
||||
* Note: Summary additions can be optimized via accumulator
|
||||
*
|
||||
* Chunked Precomputation Analysis:
|
||||
* - Using 32 chunks requires:
|
||||
* - 255 additions per chunk
|
||||
* - 256 doublings
|
||||
* - Total: (255 × 32) + 256 = 8,416 ops
|
||||
*
|
||||
* Memory Usage Comparison:
|
||||
* Window Size | Standard Points | Chunked Points
|
||||
* ------------|-----------------|---------------
|
||||
* 4-bit | 520 | 15
|
||||
* 8-bit | 4,224 | 255
|
||||
* 10-bit | 13,824 | 1,023
|
||||
* 16-bit | 557,056 | 65,535
|
||||
*
|
||||
* Key Advantages:
|
||||
* 1. Enables larger window sizes due to reduced memory overhead
|
||||
* 2. More efficient for smaller scalar counts:
|
||||
* - 16 chunks: (16 × 255) + 256 = 4,336 ops
|
||||
* - ~2x faster than standard 8,191 ops
|
||||
*
|
||||
* Limitations:
|
||||
* - Not suitable for plain precomputes (requires 256 constant doublings)
|
||||
* - Performance degrades with larger scalar counts:
|
||||
* - Optimal for ~256 scalars
|
||||
* - Less efficient for 4096+ scalars (Pippenger preferred)
|
||||
*/
|
||||
validateW(windowSize, fieldN.BITS);
|
||||
validateMSMPoints(points, c);
|
||||
const zero = c.ZERO;
|
||||
const tableSize = 2 ** windowSize - 1; // table size (without zero)
|
||||
const chunks = Math.ceil(fieldN.BITS / windowSize); // chunks of item
|
||||
const MASK = bitMask(windowSize);
|
||||
const tables = points.map((p) => {
|
||||
const res = [];
|
||||
for (let i = 0, acc = p; i < tableSize; i++) {
|
||||
res.push(acc);
|
||||
acc = acc.add(p);
|
||||
}
|
||||
return res;
|
||||
});
|
||||
return (scalars) => {
|
||||
validateMSMScalars(scalars, fieldN);
|
||||
if (scalars.length > points.length)
|
||||
throw new Error('array of scalars must be smaller than array of points');
|
||||
let res = zero;
|
||||
for (let i = 0; i < chunks; i++) {
|
||||
// No need to double if accumulator is still zero.
|
||||
if (res !== zero)
|
||||
for (let j = 0; j < windowSize; j++)
|
||||
res = res.double();
|
||||
const shiftBy = BigInt(chunks * windowSize - (i + 1) * windowSize);
|
||||
for (let j = 0; j < scalars.length; j++) {
|
||||
const n = scalars[j];
|
||||
const curr = Number((n >> shiftBy) & MASK);
|
||||
if (!curr)
|
||||
continue; // skip zero scalars chunks
|
||||
res = res.add(tables[j][curr - 1]);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
};
|
||||
}
|
||||
// TODO: remove
|
||||
/** @deprecated */
|
||||
export function validateBasic(curve) {
|
||||
validateField(curve.Fp);
|
||||
validateObject(curve, {
|
||||
n: 'bigint',
|
||||
h: 'bigint',
|
||||
Gx: 'field',
|
||||
Gy: 'field',
|
||||
}, {
|
||||
nBitLength: 'isSafeInteger',
|
||||
nByteLength: 'isSafeInteger',
|
||||
});
|
||||
// Set defaults
|
||||
return Object.freeze({
|
||||
...nLength(curve.n, curve.nBitLength),
|
||||
...curve,
|
||||
...{ p: curve.Fp.ORDER },
|
||||
});
|
||||
}
|
||||
function createField(order, field, isLE) {
|
||||
if (field) {
|
||||
if (field.ORDER !== order)
|
||||
throw new Error('Field.ORDER must match order: Fp == p, Fn == n');
|
||||
validateField(field);
|
||||
return field;
|
||||
}
|
||||
else {
|
||||
return Field(order, { isLE });
|
||||
}
|
||||
}
|
||||
/** Validates CURVE opts and creates fields */
|
||||
export function _createCurveFields(type, CURVE, curveOpts = {}, FpFnLE) {
|
||||
if (FpFnLE === undefined)
|
||||
FpFnLE = type === 'edwards';
|
||||
if (!CURVE || typeof CURVE !== 'object')
|
||||
throw new Error(`expected valid ${type} CURVE object`);
|
||||
for (const p of ['p', 'n', 'h']) {
|
||||
const val = CURVE[p];
|
||||
if (!(typeof val === 'bigint' && val > _0n))
|
||||
throw new Error(`CURVE.${p} must be positive bigint`);
|
||||
}
|
||||
const Fp = createField(CURVE.p, curveOpts.Fp, FpFnLE);
|
||||
const Fn = createField(CURVE.n, curveOpts.Fn, FpFnLE);
|
||||
const _b = type === 'weierstrass' ? 'b' : 'd';
|
||||
const params = ['Gx', 'Gy', 'a', _b];
|
||||
for (const p of params) {
|
||||
// @ts-ignore
|
||||
if (!Fp.isValid(CURVE[p]))
|
||||
throw new Error(`CURVE.${p} must be valid field element of CURVE.Fp`);
|
||||
}
|
||||
CURVE = Object.freeze(Object.assign({}, CURVE));
|
||||
return { CURVE, Fp, Fn };
|
||||
}
|
||||
//# sourceMappingURL=curve.js.map
|
||||
1
node_modules/@noble/curves/esm/abstract/curve.js.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/curve.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
243
node_modules/@noble/curves/esm/abstract/edwards.d.ts
generated
vendored
Normal file
243
node_modules/@noble/curves/esm/abstract/edwards.d.ts
generated
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
/**
|
||||
* Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y².
|
||||
* For design rationale of types / exports, see weierstrass module documentation.
|
||||
* Untwisted Edwards curves exist, but they aren't used in real-world protocols.
|
||||
* @module
|
||||
*/
|
||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||
import { type FHash, type Hex } from '../utils.ts';
|
||||
import { type AffinePoint, type BasicCurve, type CurveLengths, type CurvePoint, type CurvePointCons } from './curve.ts';
|
||||
import { type IField, type NLength } from './modular.ts';
|
||||
export type UVRatio = (u: bigint, v: bigint) => {
|
||||
isValid: boolean;
|
||||
value: bigint;
|
||||
};
|
||||
/** Instance of Extended Point with coordinates in X, Y, Z, T. */
|
||||
export interface EdwardsPoint extends CurvePoint<bigint, EdwardsPoint> {
|
||||
/** extended X coordinate. Different from affine x. */
|
||||
readonly X: bigint;
|
||||
/** extended Y coordinate. Different from affine y. */
|
||||
readonly Y: bigint;
|
||||
/** extended Z coordinate */
|
||||
readonly Z: bigint;
|
||||
/** extended T coordinate */
|
||||
readonly T: bigint;
|
||||
/** @deprecated use `toBytes` */
|
||||
toRawBytes(): Uint8Array;
|
||||
/** @deprecated use `p.precompute(windowSize)` */
|
||||
_setWindowSize(windowSize: number): void;
|
||||
/** @deprecated use .X */
|
||||
readonly ex: bigint;
|
||||
/** @deprecated use .Y */
|
||||
readonly ey: bigint;
|
||||
/** @deprecated use .Z */
|
||||
readonly ez: bigint;
|
||||
/** @deprecated use .T */
|
||||
readonly et: bigint;
|
||||
}
|
||||
/** Static methods of Extended Point with coordinates in X, Y, Z, T. */
|
||||
export interface EdwardsPointCons extends CurvePointCons<EdwardsPoint> {
|
||||
new (X: bigint, Y: bigint, Z: bigint, T: bigint): EdwardsPoint;
|
||||
CURVE(): EdwardsOpts;
|
||||
fromBytes(bytes: Uint8Array, zip215?: boolean): EdwardsPoint;
|
||||
fromHex(hex: Hex, zip215?: boolean): EdwardsPoint;
|
||||
/** @deprecated use `import { pippenger } from '@noble/curves/abstract/curve.js';` */
|
||||
msm(points: EdwardsPoint[], scalars: bigint[]): EdwardsPoint;
|
||||
}
|
||||
/** @deprecated use EdwardsPoint */
|
||||
export type ExtPointType = EdwardsPoint;
|
||||
/** @deprecated use EdwardsPointCons */
|
||||
export type ExtPointConstructor = EdwardsPointCons;
|
||||
/**
|
||||
* Twisted Edwards curve options.
|
||||
*
|
||||
* * a: formula param
|
||||
* * d: formula param
|
||||
* * p: prime characteristic (order) of finite field, in which arithmetics is done
|
||||
* * n: order of prime subgroup a.k.a total amount of valid curve points
|
||||
* * h: cofactor. h*n is group order; n is subgroup order
|
||||
* * Gx: x coordinate of generator point a.k.a. base point
|
||||
* * Gy: y coordinate of generator point
|
||||
*/
|
||||
export type EdwardsOpts = Readonly<{
|
||||
p: bigint;
|
||||
n: bigint;
|
||||
h: bigint;
|
||||
a: bigint;
|
||||
d: bigint;
|
||||
Gx: bigint;
|
||||
Gy: bigint;
|
||||
}>;
|
||||
/**
|
||||
* Extra curve options for Twisted Edwards.
|
||||
*
|
||||
* * Fp: redefined Field over curve.p
|
||||
* * Fn: redefined Field over curve.n
|
||||
* * uvRatio: helper function for decompression, calculating √(u/v)
|
||||
*/
|
||||
export type EdwardsExtraOpts = Partial<{
|
||||
Fp: IField<bigint>;
|
||||
Fn: IField<bigint>;
|
||||
FpFnLE: boolean;
|
||||
uvRatio: (u: bigint, v: bigint) => {
|
||||
isValid: boolean;
|
||||
value: bigint;
|
||||
};
|
||||
}>;
|
||||
/**
|
||||
* EdDSA (Edwards Digital Signature algorithm) options.
|
||||
*
|
||||
* * hash: hash function used to hash secret keys and messages
|
||||
* * adjustScalarBytes: clears bits to get valid field element
|
||||
* * domain: Used for hashing
|
||||
* * mapToCurve: for hash-to-curve standard
|
||||
* * prehash: RFC 8032 pre-hashing of messages to sign() / verify()
|
||||
* * randomBytes: function generating random bytes, used for randomSecretKey
|
||||
*/
|
||||
export type EdDSAOpts = Partial<{
|
||||
adjustScalarBytes: (bytes: Uint8Array) => Uint8Array;
|
||||
domain: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array;
|
||||
mapToCurve: (scalar: bigint[]) => AffinePoint<bigint>;
|
||||
prehash: FHash;
|
||||
randomBytes: (bytesLength?: number) => Uint8Array;
|
||||
}>;
|
||||
/**
|
||||
* EdDSA (Edwards Digital Signature algorithm) interface.
|
||||
*
|
||||
* Allows to create and verify signatures, create public and secret keys.
|
||||
*/
|
||||
export interface EdDSA {
|
||||
keygen: (seed?: Uint8Array) => {
|
||||
secretKey: Uint8Array;
|
||||
publicKey: Uint8Array;
|
||||
};
|
||||
getPublicKey: (secretKey: Hex) => Uint8Array;
|
||||
sign: (message: Hex, secretKey: Hex, options?: {
|
||||
context?: Hex;
|
||||
}) => Uint8Array;
|
||||
verify: (sig: Hex, message: Hex, publicKey: Hex, options?: {
|
||||
context?: Hex;
|
||||
zip215: boolean;
|
||||
}) => boolean;
|
||||
Point: EdwardsPointCons;
|
||||
utils: {
|
||||
randomSecretKey: (seed?: Uint8Array) => Uint8Array;
|
||||
isValidSecretKey: (secretKey: Uint8Array) => boolean;
|
||||
isValidPublicKey: (publicKey: Uint8Array, zip215?: boolean) => boolean;
|
||||
/**
|
||||
* Converts ed public key to x public key.
|
||||
*
|
||||
* There is NO `fromMontgomery`:
|
||||
* - There are 2 valid ed25519 points for every x25519, with flipped coordinate
|
||||
* - Sometimes there are 0 valid ed25519 points, because x25519 *additionally*
|
||||
* accepts inputs on the quadratic twist, which can't be moved to ed25519
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* const someonesPub = ed25519.getPublicKey(ed25519.utils.randomSecretKey());
|
||||
* const aPriv = x25519.utils.randomSecretKey();
|
||||
* x25519.getSharedSecret(aPriv, ed25519.utils.toMontgomery(someonesPub))
|
||||
* ```
|
||||
*/
|
||||
toMontgomery: (publicKey: Uint8Array) => Uint8Array;
|
||||
/**
|
||||
* Converts ed secret key to x secret key.
|
||||
* @example
|
||||
* ```js
|
||||
* const someonesPub = x25519.getPublicKey(x25519.utils.randomSecretKey());
|
||||
* const aPriv = ed25519.utils.randomSecretKey();
|
||||
* x25519.getSharedSecret(ed25519.utils.toMontgomerySecret(aPriv), someonesPub)
|
||||
* ```
|
||||
*/
|
||||
toMontgomerySecret: (privateKey: Uint8Array) => Uint8Array;
|
||||
getExtendedPublicKey: (key: Hex) => {
|
||||
head: Uint8Array;
|
||||
prefix: Uint8Array;
|
||||
scalar: bigint;
|
||||
point: EdwardsPoint;
|
||||
pointBytes: Uint8Array;
|
||||
};
|
||||
/** @deprecated use `randomSecretKey` */
|
||||
randomPrivateKey: (seed?: Uint8Array) => Uint8Array;
|
||||
/** @deprecated use `point.precompute()` */
|
||||
precompute: (windowSize?: number, point?: EdwardsPoint) => EdwardsPoint;
|
||||
};
|
||||
lengths: CurveLengths;
|
||||
}
|
||||
export declare function edwards(params: EdwardsOpts, extraOpts?: EdwardsExtraOpts): EdwardsPointCons;
|
||||
/**
|
||||
* Base class for prime-order points like Ristretto255 and Decaf448.
|
||||
* These points eliminate cofactor issues by representing equivalence classes
|
||||
* of Edwards curve points.
|
||||
*/
|
||||
export declare abstract class PrimeEdwardsPoint<T extends PrimeEdwardsPoint<T>> implements CurvePoint<bigint, T> {
|
||||
static BASE: PrimeEdwardsPoint<any>;
|
||||
static ZERO: PrimeEdwardsPoint<any>;
|
||||
static Fp: IField<bigint>;
|
||||
static Fn: IField<bigint>;
|
||||
protected readonly ep: EdwardsPoint;
|
||||
constructor(ep: EdwardsPoint);
|
||||
abstract toBytes(): Uint8Array;
|
||||
abstract equals(other: T): boolean;
|
||||
static fromBytes(_bytes: Uint8Array): any;
|
||||
static fromHex(_hex: Hex): any;
|
||||
get x(): bigint;
|
||||
get y(): bigint;
|
||||
clearCofactor(): T;
|
||||
assertValidity(): void;
|
||||
toAffine(invertedZ?: bigint): AffinePoint<bigint>;
|
||||
toHex(): string;
|
||||
toString(): string;
|
||||
isTorsionFree(): boolean;
|
||||
isSmallOrder(): boolean;
|
||||
add(other: T): T;
|
||||
subtract(other: T): T;
|
||||
multiply(scalar: bigint): T;
|
||||
multiplyUnsafe(scalar: bigint): T;
|
||||
double(): T;
|
||||
negate(): T;
|
||||
precompute(windowSize?: number, isLazy?: boolean): T;
|
||||
abstract is0(): boolean;
|
||||
protected abstract assertSame(other: T): void;
|
||||
protected abstract init(ep: EdwardsPoint): T;
|
||||
/** @deprecated use `toBytes` */
|
||||
toRawBytes(): Uint8Array;
|
||||
}
|
||||
/**
|
||||
* Initializes EdDSA signatures over given Edwards curve.
|
||||
*/
|
||||
export declare function eddsa(Point: EdwardsPointCons, cHash: FHash, eddsaOpts?: EdDSAOpts): EdDSA;
|
||||
export type CurveType = BasicCurve<bigint> & {
|
||||
a: bigint;
|
||||
d: bigint;
|
||||
/** @deprecated the property will be removed in next release */
|
||||
hash: FHash;
|
||||
randomBytes?: (bytesLength?: number) => Uint8Array;
|
||||
adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array;
|
||||
domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array;
|
||||
uvRatio?: UVRatio;
|
||||
prehash?: FHash;
|
||||
mapToCurve?: (scalar: bigint[]) => AffinePoint<bigint>;
|
||||
};
|
||||
export type CurveTypeWithLength = Readonly<CurveType & Partial<NLength>>;
|
||||
export type CurveFn = {
|
||||
/** @deprecated the property will be removed in next release */
|
||||
CURVE: CurveType;
|
||||
keygen: EdDSA['keygen'];
|
||||
getPublicKey: EdDSA['getPublicKey'];
|
||||
sign: EdDSA['sign'];
|
||||
verify: EdDSA['verify'];
|
||||
Point: EdwardsPointCons;
|
||||
/** @deprecated use `Point` */
|
||||
ExtendedPoint: EdwardsPointCons;
|
||||
utils: EdDSA['utils'];
|
||||
lengths: CurveLengths;
|
||||
};
|
||||
export type EdComposed = {
|
||||
CURVE: EdwardsOpts;
|
||||
curveOpts: EdwardsExtraOpts;
|
||||
hash: FHash;
|
||||
eddsaOpts: EdDSAOpts;
|
||||
};
|
||||
export declare function twistedEdwards(c: CurveTypeWithLength): CurveFn;
|
||||
//# sourceMappingURL=edwards.d.ts.map
|
||||
1
node_modules/@noble/curves/esm/abstract/edwards.d.ts.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/edwards.d.ts.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
627
node_modules/@noble/curves/esm/abstract/edwards.js
generated
vendored
Normal file
627
node_modules/@noble/curves/esm/abstract/edwards.js
generated
vendored
Normal file
@@ -0,0 +1,627 @@
|
||||
/**
|
||||
* Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y².
|
||||
* For design rationale of types / exports, see weierstrass module documentation.
|
||||
* Untwisted Edwards curves exist, but they aren't used in real-world protocols.
|
||||
* @module
|
||||
*/
|
||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||
import { _validateObject, _abool2 as abool, _abytes2 as abytes, aInRange, bytesToHex, bytesToNumberLE, concatBytes, copyBytes, ensureBytes, isBytes, memoized, notImplemented, randomBytes as randomBytesWeb, } from "../utils.js";
|
||||
import { _createCurveFields, normalizeZ, pippenger, wNAF, } from "./curve.js";
|
||||
import { Field } from "./modular.js";
|
||||
// Be friendly to bad ECMAScript parsers by not using bigint literals
|
||||
// prettier-ignore
|
||||
const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _8n = BigInt(8);
|
||||
function isEdValidXY(Fp, CURVE, x, y) {
|
||||
const x2 = Fp.sqr(x);
|
||||
const y2 = Fp.sqr(y);
|
||||
const left = Fp.add(Fp.mul(CURVE.a, x2), y2);
|
||||
const right = Fp.add(Fp.ONE, Fp.mul(CURVE.d, Fp.mul(x2, y2)));
|
||||
return Fp.eql(left, right);
|
||||
}
|
||||
export function edwards(params, extraOpts = {}) {
|
||||
const validated = _createCurveFields('edwards', params, extraOpts, extraOpts.FpFnLE);
|
||||
const { Fp, Fn } = validated;
|
||||
let CURVE = validated.CURVE;
|
||||
const { h: cofactor } = CURVE;
|
||||
_validateObject(extraOpts, {}, { uvRatio: 'function' });
|
||||
// Important:
|
||||
// There are some places where Fp.BYTES is used instead of nByteLength.
|
||||
// So far, everything has been tested with curves of Fp.BYTES == nByteLength.
|
||||
// TODO: test and find curves which behave otherwise.
|
||||
const MASK = _2n << (BigInt(Fn.BYTES * 8) - _1n);
|
||||
const modP = (n) => Fp.create(n); // Function overrides
|
||||
// sqrt(u/v)
|
||||
const uvRatio = extraOpts.uvRatio ||
|
||||
((u, v) => {
|
||||
try {
|
||||
return { isValid: true, value: Fp.sqrt(Fp.div(u, v)) };
|
||||
}
|
||||
catch (e) {
|
||||
return { isValid: false, value: _0n };
|
||||
}
|
||||
});
|
||||
// Validate whether the passed curve params are valid.
|
||||
// equation ax² + y² = 1 + dx²y² should work for generator point.
|
||||
if (!isEdValidXY(Fp, CURVE, CURVE.Gx, CURVE.Gy))
|
||||
throw new Error('bad curve params: generator point');
|
||||
/**
|
||||
* Asserts coordinate is valid: 0 <= n < MASK.
|
||||
* Coordinates >= Fp.ORDER are allowed for zip215.
|
||||
*/
|
||||
function acoord(title, n, banZero = false) {
|
||||
const min = banZero ? _1n : _0n;
|
||||
aInRange('coordinate ' + title, n, min, MASK);
|
||||
return n;
|
||||
}
|
||||
function aextpoint(other) {
|
||||
if (!(other instanceof Point))
|
||||
throw new Error('ExtendedPoint expected');
|
||||
}
|
||||
// Converts Extended point to default (x, y) coordinates.
|
||||
// Can accept precomputed Z^-1 - for example, from invertBatch.
|
||||
const toAffineMemo = memoized((p, iz) => {
|
||||
const { X, Y, Z } = p;
|
||||
const is0 = p.is0();
|
||||
if (iz == null)
|
||||
iz = is0 ? _8n : Fp.inv(Z); // 8 was chosen arbitrarily
|
||||
const x = modP(X * iz);
|
||||
const y = modP(Y * iz);
|
||||
const zz = Fp.mul(Z, iz);
|
||||
if (is0)
|
||||
return { x: _0n, y: _1n };
|
||||
if (zz !== _1n)
|
||||
throw new Error('invZ was invalid');
|
||||
return { x, y };
|
||||
});
|
||||
const assertValidMemo = memoized((p) => {
|
||||
const { a, d } = CURVE;
|
||||
if (p.is0())
|
||||
throw new Error('bad point: ZERO'); // TODO: optimize, with vars below?
|
||||
// Equation in affine coordinates: ax² + y² = 1 + dx²y²
|
||||
// Equation in projective coordinates (X/Z, Y/Z, Z): (aX² + Y²)Z² = Z⁴ + dX²Y²
|
||||
const { X, Y, Z, T } = p;
|
||||
const X2 = modP(X * X); // X²
|
||||
const Y2 = modP(Y * Y); // Y²
|
||||
const Z2 = modP(Z * Z); // Z²
|
||||
const Z4 = modP(Z2 * Z2); // Z⁴
|
||||
const aX2 = modP(X2 * a); // aX²
|
||||
const left = modP(Z2 * modP(aX2 + Y2)); // (aX² + Y²)Z²
|
||||
const right = modP(Z4 + modP(d * modP(X2 * Y2))); // Z⁴ + dX²Y²
|
||||
if (left !== right)
|
||||
throw new Error('bad point: equation left != right (1)');
|
||||
// In Extended coordinates we also have T, which is x*y=T/Z: check X*Y == Z*T
|
||||
const XY = modP(X * Y);
|
||||
const ZT = modP(Z * T);
|
||||
if (XY !== ZT)
|
||||
throw new Error('bad point: equation left != right (2)');
|
||||
return true;
|
||||
});
|
||||
// Extended Point works in extended coordinates: (X, Y, Z, T) ∋ (x=X/Z, y=Y/Z, T=xy).
|
||||
// https://en.wikipedia.org/wiki/Twisted_Edwards_curve#Extended_coordinates
|
||||
class Point {
|
||||
constructor(X, Y, Z, T) {
|
||||
this.X = acoord('x', X);
|
||||
this.Y = acoord('y', Y);
|
||||
this.Z = acoord('z', Z, true);
|
||||
this.T = acoord('t', T);
|
||||
Object.freeze(this);
|
||||
}
|
||||
static CURVE() {
|
||||
return CURVE;
|
||||
}
|
||||
static fromAffine(p) {
|
||||
if (p instanceof Point)
|
||||
throw new Error('extended point not allowed');
|
||||
const { x, y } = p || {};
|
||||
acoord('x', x);
|
||||
acoord('y', y);
|
||||
return new Point(x, y, _1n, modP(x * y));
|
||||
}
|
||||
// Uses algo from RFC8032 5.1.3.
|
||||
static fromBytes(bytes, zip215 = false) {
|
||||
const len = Fp.BYTES;
|
||||
const { a, d } = CURVE;
|
||||
bytes = copyBytes(abytes(bytes, len, 'point'));
|
||||
abool(zip215, 'zip215');
|
||||
const normed = copyBytes(bytes); // copy again, we'll manipulate it
|
||||
const lastByte = bytes[len - 1]; // select last byte
|
||||
normed[len - 1] = lastByte & ~0x80; // clear last bit
|
||||
const y = bytesToNumberLE(normed);
|
||||
// zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5.
|
||||
// RFC8032 prohibits >= p, but ZIP215 doesn't
|
||||
// zip215=true: 0 <= y < MASK (2^256 for ed25519)
|
||||
// zip215=false: 0 <= y < P (2^255-19 for ed25519)
|
||||
const max = zip215 ? MASK : Fp.ORDER;
|
||||
aInRange('point.y', y, _0n, max);
|
||||
// Ed25519: x² = (y²-1)/(dy²+1) mod p. Ed448: x² = (y²-1)/(dy²-1) mod p. Generic case:
|
||||
// ax²+y²=1+dx²y² => y²-1=dx²y²-ax² => y²-1=x²(dy²-a) => x²=(y²-1)/(dy²-a)
|
||||
const y2 = modP(y * y); // denominator is always non-0 mod p.
|
||||
const u = modP(y2 - _1n); // u = y² - 1
|
||||
const v = modP(d * y2 - a); // v = d y² + 1.
|
||||
let { isValid, value: x } = uvRatio(u, v); // √(u/v)
|
||||
if (!isValid)
|
||||
throw new Error('bad point: invalid y coordinate');
|
||||
const isXOdd = (x & _1n) === _1n; // There are 2 square roots. Use x_0 bit to select proper
|
||||
const isLastByteOdd = (lastByte & 0x80) !== 0; // x_0, last bit
|
||||
if (!zip215 && x === _0n && isLastByteOdd)
|
||||
// if x=0 and x_0 = 1, fail
|
||||
throw new Error('bad point: x=0 and x_0=1');
|
||||
if (isLastByteOdd !== isXOdd)
|
||||
x = modP(-x); // if x_0 != x mod 2, set x = p-x
|
||||
return Point.fromAffine({ x, y });
|
||||
}
|
||||
static fromHex(bytes, zip215 = false) {
|
||||
return Point.fromBytes(ensureBytes('point', bytes), zip215);
|
||||
}
|
||||
get x() {
|
||||
return this.toAffine().x;
|
||||
}
|
||||
get y() {
|
||||
return this.toAffine().y;
|
||||
}
|
||||
precompute(windowSize = 8, isLazy = true) {
|
||||
wnaf.createCache(this, windowSize);
|
||||
if (!isLazy)
|
||||
this.multiply(_2n); // random number
|
||||
return this;
|
||||
}
|
||||
// Useful in fromAffine() - not for fromBytes(), which always created valid points.
|
||||
assertValidity() {
|
||||
assertValidMemo(this);
|
||||
}
|
||||
// Compare one point to another.
|
||||
equals(other) {
|
||||
aextpoint(other);
|
||||
const { X: X1, Y: Y1, Z: Z1 } = this;
|
||||
const { X: X2, Y: Y2, Z: Z2 } = other;
|
||||
const X1Z2 = modP(X1 * Z2);
|
||||
const X2Z1 = modP(X2 * Z1);
|
||||
const Y1Z2 = modP(Y1 * Z2);
|
||||
const Y2Z1 = modP(Y2 * Z1);
|
||||
return X1Z2 === X2Z1 && Y1Z2 === Y2Z1;
|
||||
}
|
||||
is0() {
|
||||
return this.equals(Point.ZERO);
|
||||
}
|
||||
negate() {
|
||||
// Flips point sign to a negative one (-x, y in affine coords)
|
||||
return new Point(modP(-this.X), this.Y, this.Z, modP(-this.T));
|
||||
}
|
||||
// Fast algo for doubling Extended Point.
|
||||
// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd
|
||||
// Cost: 4M + 4S + 1*a + 6add + 1*2.
|
||||
double() {
|
||||
const { a } = CURVE;
|
||||
const { X: X1, Y: Y1, Z: Z1 } = this;
|
||||
const A = modP(X1 * X1); // A = X12
|
||||
const B = modP(Y1 * Y1); // B = Y12
|
||||
const C = modP(_2n * modP(Z1 * Z1)); // C = 2*Z12
|
||||
const D = modP(a * A); // D = a*A
|
||||
const x1y1 = X1 + Y1;
|
||||
const E = modP(modP(x1y1 * x1y1) - A - B); // E = (X1+Y1)2-A-B
|
||||
const G = D + B; // G = D+B
|
||||
const F = G - C; // F = G-C
|
||||
const H = D - B; // H = D-B
|
||||
const X3 = modP(E * F); // X3 = E*F
|
||||
const Y3 = modP(G * H); // Y3 = G*H
|
||||
const T3 = modP(E * H); // T3 = E*H
|
||||
const Z3 = modP(F * G); // Z3 = F*G
|
||||
return new Point(X3, Y3, Z3, T3);
|
||||
}
|
||||
// Fast algo for adding 2 Extended Points.
|
||||
// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
|
||||
// Cost: 9M + 1*a + 1*d + 7add.
|
||||
add(other) {
|
||||
aextpoint(other);
|
||||
const { a, d } = CURVE;
|
||||
const { X: X1, Y: Y1, Z: Z1, T: T1 } = this;
|
||||
const { X: X2, Y: Y2, Z: Z2, T: T2 } = other;
|
||||
const A = modP(X1 * X2); // A = X1*X2
|
||||
const B = modP(Y1 * Y2); // B = Y1*Y2
|
||||
const C = modP(T1 * d * T2); // C = T1*d*T2
|
||||
const D = modP(Z1 * Z2); // D = Z1*Z2
|
||||
const E = modP((X1 + Y1) * (X2 + Y2) - A - B); // E = (X1+Y1)*(X2+Y2)-A-B
|
||||
const F = D - C; // F = D-C
|
||||
const G = D + C; // G = D+C
|
||||
const H = modP(B - a * A); // H = B-a*A
|
||||
const X3 = modP(E * F); // X3 = E*F
|
||||
const Y3 = modP(G * H); // Y3 = G*H
|
||||
const T3 = modP(E * H); // T3 = E*H
|
||||
const Z3 = modP(F * G); // Z3 = F*G
|
||||
return new Point(X3, Y3, Z3, T3);
|
||||
}
|
||||
subtract(other) {
|
||||
return this.add(other.negate());
|
||||
}
|
||||
// Constant-time multiplication.
|
||||
multiply(scalar) {
|
||||
// 1 <= scalar < L
|
||||
if (!Fn.isValidNot0(scalar))
|
||||
throw new Error('invalid scalar: expected 1 <= sc < curve.n');
|
||||
const { p, f } = wnaf.cached(this, scalar, (p) => normalizeZ(Point, p));
|
||||
return normalizeZ(Point, [p, f])[0];
|
||||
}
|
||||
// Non-constant-time multiplication. Uses double-and-add algorithm.
|
||||
// It's faster, but should only be used when you don't care about
|
||||
// an exposed private key e.g. sig verification.
|
||||
// Does NOT allow scalars higher than CURVE.n.
|
||||
// Accepts optional accumulator to merge with multiply (important for sparse scalars)
|
||||
multiplyUnsafe(scalar, acc = Point.ZERO) {
|
||||
// 0 <= scalar < L
|
||||
if (!Fn.isValid(scalar))
|
||||
throw new Error('invalid scalar: expected 0 <= sc < curve.n');
|
||||
if (scalar === _0n)
|
||||
return Point.ZERO;
|
||||
if (this.is0() || scalar === _1n)
|
||||
return this;
|
||||
return wnaf.unsafe(this, scalar, (p) => normalizeZ(Point, p), acc);
|
||||
}
|
||||
// Checks if point is of small order.
|
||||
// If you add something to small order point, you will have "dirty"
|
||||
// point with torsion component.
|
||||
// Multiplies point by cofactor and checks if the result is 0.
|
||||
isSmallOrder() {
|
||||
return this.multiplyUnsafe(cofactor).is0();
|
||||
}
|
||||
// Multiplies point by curve order and checks if the result is 0.
|
||||
// Returns `false` is the point is dirty.
|
||||
isTorsionFree() {
|
||||
return wnaf.unsafe(this, CURVE.n).is0();
|
||||
}
|
||||
// Converts Extended point to default (x, y) coordinates.
|
||||
// Can accept precomputed Z^-1 - for example, from invertBatch.
|
||||
toAffine(invertedZ) {
|
||||
return toAffineMemo(this, invertedZ);
|
||||
}
|
||||
clearCofactor() {
|
||||
if (cofactor === _1n)
|
||||
return this;
|
||||
return this.multiplyUnsafe(cofactor);
|
||||
}
|
||||
toBytes() {
|
||||
const { x, y } = this.toAffine();
|
||||
// Fp.toBytes() allows non-canonical encoding of y (>= p).
|
||||
const bytes = Fp.toBytes(y);
|
||||
// Each y has 2 valid points: (x, y), (x,-y).
|
||||
// When compressing, it's enough to store y and use the last byte to encode sign of x
|
||||
bytes[bytes.length - 1] |= x & _1n ? 0x80 : 0;
|
||||
return bytes;
|
||||
}
|
||||
toHex() {
|
||||
return bytesToHex(this.toBytes());
|
||||
}
|
||||
toString() {
|
||||
return `<Point ${this.is0() ? 'ZERO' : this.toHex()}>`;
|
||||
}
|
||||
// TODO: remove
|
||||
get ex() {
|
||||
return this.X;
|
||||
}
|
||||
get ey() {
|
||||
return this.Y;
|
||||
}
|
||||
get ez() {
|
||||
return this.Z;
|
||||
}
|
||||
get et() {
|
||||
return this.T;
|
||||
}
|
||||
static normalizeZ(points) {
|
||||
return normalizeZ(Point, points);
|
||||
}
|
||||
static msm(points, scalars) {
|
||||
return pippenger(Point, Fn, points, scalars);
|
||||
}
|
||||
_setWindowSize(windowSize) {
|
||||
this.precompute(windowSize);
|
||||
}
|
||||
toRawBytes() {
|
||||
return this.toBytes();
|
||||
}
|
||||
}
|
||||
// base / generator point
|
||||
Point.BASE = new Point(CURVE.Gx, CURVE.Gy, _1n, modP(CURVE.Gx * CURVE.Gy));
|
||||
// zero / infinity / identity point
|
||||
Point.ZERO = new Point(_0n, _1n, _1n, _0n); // 0, 1, 1, 0
|
||||
// math field
|
||||
Point.Fp = Fp;
|
||||
// scalar field
|
||||
Point.Fn = Fn;
|
||||
const wnaf = new wNAF(Point, Fn.BITS);
|
||||
Point.BASE.precompute(8); // Enable precomputes. Slows down first publicKey computation by 20ms.
|
||||
return Point;
|
||||
}
|
||||
/**
|
||||
* Base class for prime-order points like Ristretto255 and Decaf448.
|
||||
* These points eliminate cofactor issues by representing equivalence classes
|
||||
* of Edwards curve points.
|
||||
*/
|
||||
export class PrimeEdwardsPoint {
|
||||
constructor(ep) {
|
||||
this.ep = ep;
|
||||
}
|
||||
// Static methods that must be implemented by subclasses
|
||||
static fromBytes(_bytes) {
|
||||
notImplemented();
|
||||
}
|
||||
static fromHex(_hex) {
|
||||
notImplemented();
|
||||
}
|
||||
get x() {
|
||||
return this.toAffine().x;
|
||||
}
|
||||
get y() {
|
||||
return this.toAffine().y;
|
||||
}
|
||||
// Common implementations
|
||||
clearCofactor() {
|
||||
// no-op for prime-order groups
|
||||
return this;
|
||||
}
|
||||
assertValidity() {
|
||||
this.ep.assertValidity();
|
||||
}
|
||||
toAffine(invertedZ) {
|
||||
return this.ep.toAffine(invertedZ);
|
||||
}
|
||||
toHex() {
|
||||
return bytesToHex(this.toBytes());
|
||||
}
|
||||
toString() {
|
||||
return this.toHex();
|
||||
}
|
||||
isTorsionFree() {
|
||||
return true;
|
||||
}
|
||||
isSmallOrder() {
|
||||
return false;
|
||||
}
|
||||
add(other) {
|
||||
this.assertSame(other);
|
||||
return this.init(this.ep.add(other.ep));
|
||||
}
|
||||
subtract(other) {
|
||||
this.assertSame(other);
|
||||
return this.init(this.ep.subtract(other.ep));
|
||||
}
|
||||
multiply(scalar) {
|
||||
return this.init(this.ep.multiply(scalar));
|
||||
}
|
||||
multiplyUnsafe(scalar) {
|
||||
return this.init(this.ep.multiplyUnsafe(scalar));
|
||||
}
|
||||
double() {
|
||||
return this.init(this.ep.double());
|
||||
}
|
||||
negate() {
|
||||
return this.init(this.ep.negate());
|
||||
}
|
||||
precompute(windowSize, isLazy) {
|
||||
return this.init(this.ep.precompute(windowSize, isLazy));
|
||||
}
|
||||
/** @deprecated use `toBytes` */
|
||||
toRawBytes() {
|
||||
return this.toBytes();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Initializes EdDSA signatures over given Edwards curve.
|
||||
*/
|
||||
export function eddsa(Point, cHash, eddsaOpts = {}) {
|
||||
if (typeof cHash !== 'function')
|
||||
throw new Error('"hash" function param is required');
|
||||
_validateObject(eddsaOpts, {}, {
|
||||
adjustScalarBytes: 'function',
|
||||
randomBytes: 'function',
|
||||
domain: 'function',
|
||||
prehash: 'function',
|
||||
mapToCurve: 'function',
|
||||
});
|
||||
const { prehash } = eddsaOpts;
|
||||
const { BASE, Fp, Fn } = Point;
|
||||
const randomBytes = eddsaOpts.randomBytes || randomBytesWeb;
|
||||
const adjustScalarBytes = eddsaOpts.adjustScalarBytes || ((bytes) => bytes);
|
||||
const domain = eddsaOpts.domain ||
|
||||
((data, ctx, phflag) => {
|
||||
abool(phflag, 'phflag');
|
||||
if (ctx.length || phflag)
|
||||
throw new Error('Contexts/pre-hash are not supported');
|
||||
return data;
|
||||
}); // NOOP
|
||||
// Little-endian SHA512 with modulo n
|
||||
function modN_LE(hash) {
|
||||
return Fn.create(bytesToNumberLE(hash)); // Not Fn.fromBytes: it has length limit
|
||||
}
|
||||
// Get the hashed private scalar per RFC8032 5.1.5
|
||||
function getPrivateScalar(key) {
|
||||
const len = lengths.secretKey;
|
||||
key = ensureBytes('private key', key, len);
|
||||
// Hash private key with curve's hash function to produce uniformingly random input
|
||||
// Check byte lengths: ensure(64, h(ensure(32, key)))
|
||||
const hashed = ensureBytes('hashed private key', cHash(key), 2 * len);
|
||||
const head = adjustScalarBytes(hashed.slice(0, len)); // clear first half bits, produce FE
|
||||
const prefix = hashed.slice(len, 2 * len); // second half is called key prefix (5.1.6)
|
||||
const scalar = modN_LE(head); // The actual private scalar
|
||||
return { head, prefix, scalar };
|
||||
}
|
||||
/** Convenience method that creates public key from scalar. RFC8032 5.1.5 */
|
||||
function getExtendedPublicKey(secretKey) {
|
||||
const { head, prefix, scalar } = getPrivateScalar(secretKey);
|
||||
const point = BASE.multiply(scalar); // Point on Edwards curve aka public key
|
||||
const pointBytes = point.toBytes();
|
||||
return { head, prefix, scalar, point, pointBytes };
|
||||
}
|
||||
/** Calculates EdDSA pub key. RFC8032 5.1.5. */
|
||||
function getPublicKey(secretKey) {
|
||||
return getExtendedPublicKey(secretKey).pointBytes;
|
||||
}
|
||||
// int('LE', SHA512(dom2(F, C) || msgs)) mod N
|
||||
function hashDomainToScalar(context = Uint8Array.of(), ...msgs) {
|
||||
const msg = concatBytes(...msgs);
|
||||
return modN_LE(cHash(domain(msg, ensureBytes('context', context), !!prehash)));
|
||||
}
|
||||
/** Signs message with privateKey. RFC8032 5.1.6 */
|
||||
function sign(msg, secretKey, options = {}) {
|
||||
msg = ensureBytes('message', msg);
|
||||
if (prehash)
|
||||
msg = prehash(msg); // for ed25519ph etc.
|
||||
const { prefix, scalar, pointBytes } = getExtendedPublicKey(secretKey);
|
||||
const r = hashDomainToScalar(options.context, prefix, msg); // r = dom2(F, C) || prefix || PH(M)
|
||||
const R = BASE.multiply(r).toBytes(); // R = rG
|
||||
const k = hashDomainToScalar(options.context, R, pointBytes, msg); // R || A || PH(M)
|
||||
const s = Fn.create(r + k * scalar); // S = (r + k * s) mod L
|
||||
if (!Fn.isValid(s))
|
||||
throw new Error('sign failed: invalid s'); // 0 <= s < L
|
||||
const rs = concatBytes(R, Fn.toBytes(s));
|
||||
return abytes(rs, lengths.signature, 'result');
|
||||
}
|
||||
// verification rule is either zip215 or rfc8032 / nist186-5. Consult fromHex:
|
||||
const verifyOpts = { zip215: true };
|
||||
/**
|
||||
* Verifies EdDSA signature against message and public key. RFC8032 5.1.7.
|
||||
* An extended group equation is checked.
|
||||
*/
|
||||
function verify(sig, msg, publicKey, options = verifyOpts) {
|
||||
const { context, zip215 } = options;
|
||||
const len = lengths.signature;
|
||||
sig = ensureBytes('signature', sig, len);
|
||||
msg = ensureBytes('message', msg);
|
||||
publicKey = ensureBytes('publicKey', publicKey, lengths.publicKey);
|
||||
if (zip215 !== undefined)
|
||||
abool(zip215, 'zip215');
|
||||
if (prehash)
|
||||
msg = prehash(msg); // for ed25519ph, etc
|
||||
const mid = len / 2;
|
||||
const r = sig.subarray(0, mid);
|
||||
const s = bytesToNumberLE(sig.subarray(mid, len));
|
||||
let A, R, SB;
|
||||
try {
|
||||
// zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5.
|
||||
// zip215=true: 0 <= y < MASK (2^256 for ed25519)
|
||||
// zip215=false: 0 <= y < P (2^255-19 for ed25519)
|
||||
A = Point.fromBytes(publicKey, zip215);
|
||||
R = Point.fromBytes(r, zip215);
|
||||
SB = BASE.multiplyUnsafe(s); // 0 <= s < l is done inside
|
||||
}
|
||||
catch (error) {
|
||||
return false;
|
||||
}
|
||||
if (!zip215 && A.isSmallOrder())
|
||||
return false; // zip215 allows public keys of small order
|
||||
const k = hashDomainToScalar(context, R.toBytes(), A.toBytes(), msg);
|
||||
const RkA = R.add(A.multiplyUnsafe(k));
|
||||
// Extended group equation
|
||||
// [8][S]B = [8]R + [8][k]A'
|
||||
return RkA.subtract(SB).clearCofactor().is0();
|
||||
}
|
||||
const _size = Fp.BYTES; // 32 for ed25519, 57 for ed448
|
||||
const lengths = {
|
||||
secretKey: _size,
|
||||
publicKey: _size,
|
||||
signature: 2 * _size,
|
||||
seed: _size,
|
||||
};
|
||||
function randomSecretKey(seed = randomBytes(lengths.seed)) {
|
||||
return abytes(seed, lengths.seed, 'seed');
|
||||
}
|
||||
function keygen(seed) {
|
||||
const secretKey = utils.randomSecretKey(seed);
|
||||
return { secretKey, publicKey: getPublicKey(secretKey) };
|
||||
}
|
||||
function isValidSecretKey(key) {
|
||||
return isBytes(key) && key.length === Fn.BYTES;
|
||||
}
|
||||
function isValidPublicKey(key, zip215) {
|
||||
try {
|
||||
return !!Point.fromBytes(key, zip215);
|
||||
}
|
||||
catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const utils = {
|
||||
getExtendedPublicKey,
|
||||
randomSecretKey,
|
||||
isValidSecretKey,
|
||||
isValidPublicKey,
|
||||
/**
|
||||
* Converts ed public key to x public key. Uses formula:
|
||||
* - ed25519:
|
||||
* - `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)`
|
||||
* - `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))`
|
||||
* - ed448:
|
||||
* - `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)`
|
||||
* - `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))`
|
||||
*/
|
||||
toMontgomery(publicKey) {
|
||||
const { y } = Point.fromBytes(publicKey);
|
||||
const size = lengths.publicKey;
|
||||
const is25519 = size === 32;
|
||||
if (!is25519 && size !== 57)
|
||||
throw new Error('only defined for 25519 and 448');
|
||||
const u = is25519 ? Fp.div(_1n + y, _1n - y) : Fp.div(y - _1n, y + _1n);
|
||||
return Fp.toBytes(u);
|
||||
},
|
||||
toMontgomerySecret(secretKey) {
|
||||
const size = lengths.secretKey;
|
||||
abytes(secretKey, size);
|
||||
const hashed = cHash(secretKey.subarray(0, size));
|
||||
return adjustScalarBytes(hashed).subarray(0, size);
|
||||
},
|
||||
/** @deprecated */
|
||||
randomPrivateKey: randomSecretKey,
|
||||
/** @deprecated */
|
||||
precompute(windowSize = 8, point = Point.BASE) {
|
||||
return point.precompute(windowSize, false);
|
||||
},
|
||||
};
|
||||
return Object.freeze({
|
||||
keygen,
|
||||
getPublicKey,
|
||||
sign,
|
||||
verify,
|
||||
utils,
|
||||
Point,
|
||||
lengths,
|
||||
});
|
||||
}
|
||||
function _eddsa_legacy_opts_to_new(c) {
|
||||
const CURVE = {
|
||||
a: c.a,
|
||||
d: c.d,
|
||||
p: c.Fp.ORDER,
|
||||
n: c.n,
|
||||
h: c.h,
|
||||
Gx: c.Gx,
|
||||
Gy: c.Gy,
|
||||
};
|
||||
const Fp = c.Fp;
|
||||
const Fn = Field(CURVE.n, c.nBitLength, true);
|
||||
const curveOpts = { Fp, Fn, uvRatio: c.uvRatio };
|
||||
const eddsaOpts = {
|
||||
randomBytes: c.randomBytes,
|
||||
adjustScalarBytes: c.adjustScalarBytes,
|
||||
domain: c.domain,
|
||||
prehash: c.prehash,
|
||||
mapToCurve: c.mapToCurve,
|
||||
};
|
||||
return { CURVE, curveOpts, hash: c.hash, eddsaOpts };
|
||||
}
|
||||
function _eddsa_new_output_to_legacy(c, eddsa) {
|
||||
const Point = eddsa.Point;
|
||||
const legacy = Object.assign({}, eddsa, {
|
||||
ExtendedPoint: Point,
|
||||
CURVE: c,
|
||||
nBitLength: Point.Fn.BITS,
|
||||
nByteLength: Point.Fn.BYTES,
|
||||
});
|
||||
return legacy;
|
||||
}
|
||||
// TODO: remove. Use eddsa
|
||||
export function twistedEdwards(c) {
|
||||
const { CURVE, curveOpts, hash, eddsaOpts } = _eddsa_legacy_opts_to_new(c);
|
||||
const Point = edwards(CURVE, curveOpts);
|
||||
const EDDSA = eddsa(Point, hash, eddsaOpts);
|
||||
return _eddsa_new_output_to_legacy(c, EDDSA);
|
||||
}
|
||||
//# sourceMappingURL=edwards.js.map
|
||||
1
node_modules/@noble/curves/esm/abstract/edwards.js.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/edwards.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
122
node_modules/@noble/curves/esm/abstract/fft.d.ts
generated
vendored
Normal file
122
node_modules/@noble/curves/esm/abstract/fft.d.ts
generated
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* Experimental implementation of NTT / FFT (Fast Fourier Transform) over finite fields.
|
||||
* API may change at any time. The code has not been audited. Feature requests are welcome.
|
||||
* @module
|
||||
*/
|
||||
import type { IField } from './modular.ts';
|
||||
export interface MutableArrayLike<T> {
|
||||
[index: number]: T;
|
||||
length: number;
|
||||
slice(start?: number, end?: number): this;
|
||||
[Symbol.iterator](): Iterator<T>;
|
||||
}
|
||||
/** Checks if integer is in form of `1 << X` */
|
||||
export declare function isPowerOfTwo(x: number): boolean;
|
||||
export declare function nextPowerOfTwo(n: number): number;
|
||||
export declare function reverseBits(n: number, bits: number): number;
|
||||
/** Similar to `bitLen(x)-1` but much faster for small integers, like indices */
|
||||
export declare function log2(n: number): number;
|
||||
/**
|
||||
* Moves lowest bit to highest position, which at first step splits
|
||||
* array on even and odd indices, then it applied again to each part,
|
||||
* which is core of fft
|
||||
*/
|
||||
export declare function bitReversalInplace<T extends MutableArrayLike<any>>(values: T): T;
|
||||
export declare function bitReversalPermutation<T>(values: T[]): T[];
|
||||
export type RootsOfUnity = {
|
||||
roots: (bits: number) => bigint[];
|
||||
brp(bits: number): bigint[];
|
||||
inverse(bits: number): bigint[];
|
||||
omega: (bits: number) => bigint;
|
||||
clear: () => void;
|
||||
};
|
||||
/** We limit roots up to 2**31, which is a lot: 2-billion polynomimal should be rare. */
|
||||
export declare function rootsOfUnity(field: IField<bigint>, generator?: bigint): RootsOfUnity;
|
||||
export type Polynomial<T> = MutableArrayLike<T>;
|
||||
/**
|
||||
* Maps great to Field<bigint>, but not to Group (EC points):
|
||||
* - inv from scalar field
|
||||
* - we need multiplyUnsafe here, instead of multiply for speed
|
||||
* - multiplyUnsafe is safe in the context: we do mul(rootsOfUnity), which are public and sparse
|
||||
*/
|
||||
export type FFTOpts<T, R> = {
|
||||
add: (a: T, b: T) => T;
|
||||
sub: (a: T, b: T) => T;
|
||||
mul: (a: T, scalar: R) => T;
|
||||
inv: (a: R) => R;
|
||||
};
|
||||
export type FFTCoreOpts<R> = {
|
||||
N: number;
|
||||
roots: Polynomial<R>;
|
||||
dit: boolean;
|
||||
invertButterflies?: boolean;
|
||||
skipStages?: number;
|
||||
brp?: boolean;
|
||||
};
|
||||
export type FFTCoreLoop<T> = <P extends Polynomial<T>>(values: P) => P;
|
||||
/**
|
||||
* Constructs different flavors of FFT. radix2 implementation of low level mutating API. Flavors:
|
||||
*
|
||||
* - DIT (Decimation-in-Time): Bottom-Up (leaves -> root), Cool-Turkey
|
||||
* - DIF (Decimation-in-Frequency): Top-Down (root -> leaves), Gentleman–Sande
|
||||
*
|
||||
* DIT takes brp input, returns natural output.
|
||||
* DIF takes natural input, returns brp output.
|
||||
*
|
||||
* The output is actually identical. Time / frequence distinction is not meaningful
|
||||
* for Polynomial multiplication in fields.
|
||||
* Which means if protocol supports/needs brp output/inputs, then we can skip this step.
|
||||
*
|
||||
* Cyclic NTT: Rq = Zq[x]/(x^n-1). butterfly_DIT+loop_DIT OR butterfly_DIF+loop_DIT, roots are omega
|
||||
* Negacyclic NTT: Rq = Zq[x]/(x^n+1). butterfly_DIT+loop_DIF, at least for mlkem / mldsa
|
||||
*/
|
||||
export declare const FFTCore: <T, R>(F: FFTOpts<T, R>, coreOpts: FFTCoreOpts<R>) => FFTCoreLoop<T>;
|
||||
export type FFTMethods<T> = {
|
||||
direct<P extends Polynomial<T>>(values: P, brpInput?: boolean, brpOutput?: boolean): P;
|
||||
inverse<P extends Polynomial<T>>(values: P, brpInput?: boolean, brpOutput?: boolean): P;
|
||||
};
|
||||
/**
|
||||
* NTT aka FFT over finite field (NOT over complex numbers).
|
||||
* Naming mirrors other libraries.
|
||||
*/
|
||||
export declare function FFT<T>(roots: RootsOfUnity, opts: FFTOpts<T, bigint>): FFTMethods<T>;
|
||||
export type CreatePolyFn<P extends Polynomial<T>, T> = (len: number, elm?: T) => P;
|
||||
export type PolyFn<P extends Polynomial<T>, T> = {
|
||||
roots: RootsOfUnity;
|
||||
create: CreatePolyFn<P, T>;
|
||||
length?: number;
|
||||
degree: (a: P) => number;
|
||||
extend: (a: P, len: number) => P;
|
||||
add: (a: P, b: P) => P;
|
||||
sub: (a: P, b: P) => P;
|
||||
mul: (a: P, b: P | T) => P;
|
||||
dot: (a: P, b: P) => P;
|
||||
convolve: (a: P, b: P) => P;
|
||||
shift: (p: P, factor: bigint) => P;
|
||||
clone: (a: P) => P;
|
||||
eval: (a: P, basis: P) => T;
|
||||
monomial: {
|
||||
basis: (x: T, n: number) => P;
|
||||
eval: (a: P, x: T) => T;
|
||||
};
|
||||
lagrange: {
|
||||
basis: (x: T, n: number, brp?: boolean) => P;
|
||||
eval: (a: P, x: T, brp?: boolean) => T;
|
||||
};
|
||||
vanishing: (roots: P) => P;
|
||||
};
|
||||
/**
|
||||
* Poly wants a cracker.
|
||||
*
|
||||
* Polynomials are functions like `y=f(x)`, which means when we multiply two polynomials, result is
|
||||
* function `f3(x) = f1(x) * f2(x)`, we don't multiply values. Key takeaways:
|
||||
*
|
||||
* - **Polynomial** is an array of coefficients: `f(x) = sum(coeff[i] * basis[i](x))`
|
||||
* - **Basis** is array of functions
|
||||
* - **Monominal** is Polynomial where `basis[i](x) == x**i` (powers)
|
||||
* - **Array size** is domain size
|
||||
* - **Lattice** is matrix (Polynomial of Polynomials)
|
||||
*/
|
||||
export declare function poly<T>(field: IField<T>, roots: RootsOfUnity, create?: undefined, fft?: FFTMethods<T>, length?: number): PolyFn<T[], T>;
|
||||
export declare function poly<T, P extends Polynomial<T>>(field: IField<T>, roots: RootsOfUnity, create: CreatePolyFn<P, T>, fft?: FFTMethods<T>, length?: number): PolyFn<P, T>;
|
||||
//# sourceMappingURL=fft.d.ts.map
|
||||
1
node_modules/@noble/curves/esm/abstract/fft.d.ts.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/fft.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"fft.d.ts","sourceRoot":"","sources":["../../src/abstract/fft.ts"],"names":[],"mappings":"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"}
|
||||
425
node_modules/@noble/curves/esm/abstract/fft.js
generated
vendored
Normal file
425
node_modules/@noble/curves/esm/abstract/fft.js
generated
vendored
Normal file
@@ -0,0 +1,425 @@
|
||||
function checkU32(n) {
|
||||
// 0xff_ff_ff_ff
|
||||
if (!Number.isSafeInteger(n) || n < 0 || n > 0xffffffff)
|
||||
throw new Error('wrong u32 integer:' + n);
|
||||
return n;
|
||||
}
|
||||
/** Checks if integer is in form of `1 << X` */
|
||||
export function isPowerOfTwo(x) {
|
||||
checkU32(x);
|
||||
return (x & (x - 1)) === 0 && x !== 0;
|
||||
}
|
||||
export function nextPowerOfTwo(n) {
|
||||
checkU32(n);
|
||||
if (n <= 1)
|
||||
return 1;
|
||||
return (1 << (log2(n - 1) + 1)) >>> 0;
|
||||
}
|
||||
export function reverseBits(n, bits) {
|
||||
checkU32(n);
|
||||
let reversed = 0;
|
||||
for (let i = 0; i < bits; i++, n >>>= 1)
|
||||
reversed = (reversed << 1) | (n & 1);
|
||||
return reversed;
|
||||
}
|
||||
/** Similar to `bitLen(x)-1` but much faster for small integers, like indices */
|
||||
export function log2(n) {
|
||||
checkU32(n);
|
||||
return 31 - Math.clz32(n);
|
||||
}
|
||||
/**
|
||||
* Moves lowest bit to highest position, which at first step splits
|
||||
* array on even and odd indices, then it applied again to each part,
|
||||
* which is core of fft
|
||||
*/
|
||||
export function bitReversalInplace(values) {
|
||||
const n = values.length;
|
||||
if (n < 2 || !isPowerOfTwo(n))
|
||||
throw new Error('n must be a power of 2 and greater than 1. Got ' + n);
|
||||
const bits = log2(n);
|
||||
for (let i = 0; i < n; i++) {
|
||||
const j = reverseBits(i, bits);
|
||||
if (i < j) {
|
||||
const tmp = values[i];
|
||||
values[i] = values[j];
|
||||
values[j] = tmp;
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
export function bitReversalPermutation(values) {
|
||||
return bitReversalInplace(values.slice());
|
||||
}
|
||||
const _1n = /** @__PURE__ */ BigInt(1);
|
||||
function findGenerator(field) {
|
||||
let G = BigInt(2);
|
||||
for (; field.eql(field.pow(G, field.ORDER >> _1n), field.ONE); G++)
|
||||
;
|
||||
return G;
|
||||
}
|
||||
/** We limit roots up to 2**31, which is a lot: 2-billion polynomimal should be rare. */
|
||||
export function rootsOfUnity(field, generator) {
|
||||
// Factor field.ORDER-1 as oddFactor * 2^powerOfTwo
|
||||
let oddFactor = field.ORDER - _1n;
|
||||
let powerOfTwo = 0;
|
||||
for (; (oddFactor & _1n) !== _1n; powerOfTwo++, oddFactor >>= _1n)
|
||||
;
|
||||
// Find non quadratic residue
|
||||
let G = generator !== undefined ? BigInt(generator) : findGenerator(field);
|
||||
// Powers of generator
|
||||
const omegas = new Array(powerOfTwo + 1);
|
||||
omegas[powerOfTwo] = field.pow(G, oddFactor);
|
||||
for (let i = powerOfTwo; i > 0; i--)
|
||||
omegas[i - 1] = field.sqr(omegas[i]);
|
||||
// Compute all roots of unity for powers up to maxPower
|
||||
const rootsCache = [];
|
||||
const checkBits = (bits) => {
|
||||
checkU32(bits);
|
||||
if (bits > 31 || bits > powerOfTwo)
|
||||
throw new Error('rootsOfUnity: wrong bits ' + bits + ' powerOfTwo=' + powerOfTwo);
|
||||
return bits;
|
||||
};
|
||||
const precomputeRoots = (maxPower) => {
|
||||
checkBits(maxPower);
|
||||
for (let power = maxPower; power >= 0; power--) {
|
||||
if (rootsCache[power])
|
||||
continue; // Skip if we've already computed roots for this power
|
||||
const rootsAtPower = [];
|
||||
for (let j = 0, cur = field.ONE; j < 2 ** power; j++, cur = field.mul(cur, omegas[power]))
|
||||
rootsAtPower.push(cur);
|
||||
rootsCache[power] = rootsAtPower;
|
||||
}
|
||||
return rootsCache[maxPower];
|
||||
};
|
||||
const brpCache = new Map();
|
||||
const inverseCache = new Map();
|
||||
// NOTE: we use bits instead of power, because power = 2**bits,
|
||||
// but power is not neccesary isPowerOfTwo(power)!
|
||||
return {
|
||||
roots: (bits) => {
|
||||
const b = checkBits(bits);
|
||||
return precomputeRoots(b);
|
||||
},
|
||||
brp(bits) {
|
||||
const b = checkBits(bits);
|
||||
if (brpCache.has(b))
|
||||
return brpCache.get(b);
|
||||
else {
|
||||
const res = bitReversalPermutation(this.roots(b));
|
||||
brpCache.set(b, res);
|
||||
return res;
|
||||
}
|
||||
},
|
||||
inverse(bits) {
|
||||
const b = checkBits(bits);
|
||||
if (inverseCache.has(b))
|
||||
return inverseCache.get(b);
|
||||
else {
|
||||
const res = field.invertBatch(this.roots(b));
|
||||
inverseCache.set(b, res);
|
||||
return res;
|
||||
}
|
||||
},
|
||||
omega: (bits) => omegas[checkBits(bits)],
|
||||
clear: () => {
|
||||
rootsCache.splice(0, rootsCache.length);
|
||||
brpCache.clear();
|
||||
},
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Constructs different flavors of FFT. radix2 implementation of low level mutating API. Flavors:
|
||||
*
|
||||
* - DIT (Decimation-in-Time): Bottom-Up (leaves -> root), Cool-Turkey
|
||||
* - DIF (Decimation-in-Frequency): Top-Down (root -> leaves), Gentleman–Sande
|
||||
*
|
||||
* DIT takes brp input, returns natural output.
|
||||
* DIF takes natural input, returns brp output.
|
||||
*
|
||||
* The output is actually identical. Time / frequence distinction is not meaningful
|
||||
* for Polynomial multiplication in fields.
|
||||
* Which means if protocol supports/needs brp output/inputs, then we can skip this step.
|
||||
*
|
||||
* Cyclic NTT: Rq = Zq[x]/(x^n-1). butterfly_DIT+loop_DIT OR butterfly_DIF+loop_DIT, roots are omega
|
||||
* Negacyclic NTT: Rq = Zq[x]/(x^n+1). butterfly_DIT+loop_DIF, at least for mlkem / mldsa
|
||||
*/
|
||||
export const FFTCore = (F, coreOpts) => {
|
||||
const { N, roots, dit, invertButterflies = false, skipStages = 0, brp = true } = coreOpts;
|
||||
const bits = log2(N);
|
||||
if (!isPowerOfTwo(N))
|
||||
throw new Error('FFT: Polynomial size should be power of two');
|
||||
const isDit = dit !== invertButterflies;
|
||||
isDit;
|
||||
return (values) => {
|
||||
if (values.length !== N)
|
||||
throw new Error('FFT: wrong Polynomial length');
|
||||
if (dit && brp)
|
||||
bitReversalInplace(values);
|
||||
for (let i = 0, g = 1; i < bits - skipStages; i++) {
|
||||
// For each stage s (sub-FFT length m = 2^s)
|
||||
const s = dit ? i + 1 + skipStages : bits - i;
|
||||
const m = 1 << s;
|
||||
const m2 = m >> 1;
|
||||
const stride = N >> s;
|
||||
// Loop over each subarray of length m
|
||||
for (let k = 0; k < N; k += m) {
|
||||
// Loop over each butterfly within the subarray
|
||||
for (let j = 0, grp = g++; j < m2; j++) {
|
||||
const rootPos = invertButterflies ? (dit ? N - grp : grp) : j * stride;
|
||||
const i0 = k + j;
|
||||
const i1 = k + j + m2;
|
||||
const omega = roots[rootPos];
|
||||
const b = values[i1];
|
||||
const a = values[i0];
|
||||
// Inlining gives us 10% perf in kyber vs functions
|
||||
if (isDit) {
|
||||
const t = F.mul(b, omega); // Standard DIT butterfly
|
||||
values[i0] = F.add(a, t);
|
||||
values[i1] = F.sub(a, t);
|
||||
}
|
||||
else if (invertButterflies) {
|
||||
values[i0] = F.add(b, a); // DIT loop + inverted butterflies (Kyber decode)
|
||||
values[i1] = F.mul(F.sub(b, a), omega);
|
||||
}
|
||||
else {
|
||||
values[i0] = F.add(a, b); // Standard DIF butterfly
|
||||
values[i1] = F.mul(F.sub(a, b), omega);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!dit && brp)
|
||||
bitReversalInplace(values);
|
||||
return values;
|
||||
};
|
||||
};
|
||||
/**
|
||||
* NTT aka FFT over finite field (NOT over complex numbers).
|
||||
* Naming mirrors other libraries.
|
||||
*/
|
||||
export function FFT(roots, opts) {
|
||||
const getLoop = (N, roots, brpInput = false, brpOutput = false) => {
|
||||
if (brpInput && brpOutput) {
|
||||
// we cannot optimize this case, but lets support it anyway
|
||||
return (values) => FFTCore(opts, { N, roots, dit: false, brp: false })(bitReversalInplace(values));
|
||||
}
|
||||
if (brpInput)
|
||||
return FFTCore(opts, { N, roots, dit: true, brp: false });
|
||||
if (brpOutput)
|
||||
return FFTCore(opts, { N, roots, dit: false, brp: false });
|
||||
return FFTCore(opts, { N, roots, dit: true, brp: true }); // all natural
|
||||
};
|
||||
return {
|
||||
direct(values, brpInput = false, brpOutput = false) {
|
||||
const N = values.length;
|
||||
if (!isPowerOfTwo(N))
|
||||
throw new Error('FFT: Polynomial size should be power of two');
|
||||
const bits = log2(N);
|
||||
return getLoop(N, roots.roots(bits), brpInput, brpOutput)(values.slice());
|
||||
},
|
||||
inverse(values, brpInput = false, brpOutput = false) {
|
||||
const N = values.length;
|
||||
const bits = log2(N);
|
||||
const res = getLoop(N, roots.inverse(bits), brpInput, brpOutput)(values.slice());
|
||||
const ivm = opts.inv(BigInt(values.length)); // scale
|
||||
// we can get brp output if we use dif instead of dit!
|
||||
for (let i = 0; i < res.length; i++)
|
||||
res[i] = opts.mul(res[i], ivm);
|
||||
// Allows to re-use non-inverted roots, but is VERY fragile
|
||||
// return [res[0]].concat(res.slice(1).reverse());
|
||||
// inverse calculated as pow(-1), which transforms into ω^{-kn} (-> reverses indices)
|
||||
return res;
|
||||
},
|
||||
};
|
||||
}
|
||||
export function poly(field, roots, create, fft, length) {
|
||||
const F = field;
|
||||
const _create = create ||
|
||||
((len, elm) => new Array(len).fill(elm ?? F.ZERO));
|
||||
const isPoly = (x) => Array.isArray(x) || ArrayBuffer.isView(x);
|
||||
const checkLength = (...lst) => {
|
||||
if (!lst.length)
|
||||
return 0;
|
||||
for (const i of lst)
|
||||
if (!isPoly(i))
|
||||
throw new Error('poly: not polynomial: ' + i);
|
||||
const L = lst[0].length;
|
||||
for (let i = 1; i < lst.length; i++)
|
||||
if (lst[i].length !== L)
|
||||
throw new Error(`poly: mismatched lengths ${L} vs ${lst[i].length}`);
|
||||
if (length !== undefined && L !== length)
|
||||
throw new Error(`poly: expected fixed length ${length}, got ${L}`);
|
||||
return L;
|
||||
};
|
||||
function findOmegaIndex(x, n, brp = false) {
|
||||
const bits = log2(n);
|
||||
const omega = brp ? roots.brp(bits) : roots.roots(bits);
|
||||
for (let i = 0; i < n; i++)
|
||||
if (F.eql(x, omega[i]))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
// TODO: mutating versions for mlkem/mldsa
|
||||
return {
|
||||
roots,
|
||||
create: _create,
|
||||
length,
|
||||
extend: (a, len) => {
|
||||
checkLength(a);
|
||||
const out = _create(len, F.ZERO);
|
||||
for (let i = 0; i < a.length; i++)
|
||||
out[i] = a[i];
|
||||
return out;
|
||||
},
|
||||
degree: (a) => {
|
||||
checkLength(a);
|
||||
for (let i = a.length - 1; i >= 0; i--)
|
||||
if (!F.is0(a[i]))
|
||||
return i;
|
||||
return -1;
|
||||
},
|
||||
add: (a, b) => {
|
||||
const len = checkLength(a, b);
|
||||
const out = _create(len);
|
||||
for (let i = 0; i < len; i++)
|
||||
out[i] = F.add(a[i], b[i]);
|
||||
return out;
|
||||
},
|
||||
sub: (a, b) => {
|
||||
const len = checkLength(a, b);
|
||||
const out = _create(len);
|
||||
for (let i = 0; i < len; i++)
|
||||
out[i] = F.sub(a[i], b[i]);
|
||||
return out;
|
||||
},
|
||||
dot: (a, b) => {
|
||||
const len = checkLength(a, b);
|
||||
const out = _create(len);
|
||||
for (let i = 0; i < len; i++)
|
||||
out[i] = F.mul(a[i], b[i]);
|
||||
return out;
|
||||
},
|
||||
mul: (a, b) => {
|
||||
if (isPoly(b)) {
|
||||
const len = checkLength(a, b);
|
||||
if (fft) {
|
||||
const A = fft.direct(a, false, true);
|
||||
const B = fft.direct(b, false, true);
|
||||
for (let i = 0; i < A.length; i++)
|
||||
A[i] = F.mul(A[i], B[i]);
|
||||
return fft.inverse(A, true, false);
|
||||
}
|
||||
else {
|
||||
// NOTE: this is quadratic and mostly for compat tests with FFT
|
||||
const res = _create(len);
|
||||
for (let i = 0; i < len; i++) {
|
||||
for (let j = 0; j < len; j++) {
|
||||
const k = (i + j) % len; // wrap mod length
|
||||
res[k] = F.add(res[k], F.mul(a[i], b[j]));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const out = _create(checkLength(a));
|
||||
for (let i = 0; i < out.length; i++)
|
||||
out[i] = F.mul(a[i], b);
|
||||
return out;
|
||||
}
|
||||
},
|
||||
convolve(a, b) {
|
||||
const len = nextPowerOfTwo(a.length + b.length - 1);
|
||||
return this.mul(this.extend(a, len), this.extend(b, len));
|
||||
},
|
||||
shift(p, factor) {
|
||||
const out = _create(checkLength(p));
|
||||
out[0] = p[0];
|
||||
for (let i = 1, power = F.ONE; i < p.length; i++) {
|
||||
power = F.mul(power, factor);
|
||||
out[i] = F.mul(p[i], power);
|
||||
}
|
||||
return out;
|
||||
},
|
||||
clone: (a) => {
|
||||
checkLength(a);
|
||||
const out = _create(a.length);
|
||||
for (let i = 0; i < a.length; i++)
|
||||
out[i] = a[i];
|
||||
return out;
|
||||
},
|
||||
eval: (a, basis) => {
|
||||
checkLength(a);
|
||||
let acc = F.ZERO;
|
||||
for (let i = 0; i < a.length; i++)
|
||||
acc = F.add(acc, F.mul(a[i], basis[i]));
|
||||
return acc;
|
||||
},
|
||||
monomial: {
|
||||
basis: (x, n) => {
|
||||
const out = _create(n);
|
||||
let pow = F.ONE;
|
||||
for (let i = 0; i < n; i++) {
|
||||
out[i] = pow;
|
||||
pow = F.mul(pow, x);
|
||||
}
|
||||
return out;
|
||||
},
|
||||
eval: (a, x) => {
|
||||
checkLength(a);
|
||||
// Same as eval(a, monomialBasis(x, a.length)), but it is faster this way
|
||||
let acc = F.ZERO;
|
||||
for (let i = a.length - 1; i >= 0; i--)
|
||||
acc = F.add(F.mul(acc, x), a[i]);
|
||||
return acc;
|
||||
},
|
||||
},
|
||||
lagrange: {
|
||||
basis: (x, n, brp = false, weights) => {
|
||||
const bits = log2(n);
|
||||
const cache = weights || brp ? roots.brp(bits) : roots.roots(bits); // [ω⁰, ω¹, ..., ωⁿ⁻¹]
|
||||
const out = _create(n);
|
||||
// Fast Kronecker-δ shortcut
|
||||
const idx = findOmegaIndex(x, n, brp);
|
||||
if (idx !== -1) {
|
||||
out[idx] = F.ONE;
|
||||
return out;
|
||||
}
|
||||
const tm = F.pow(x, BigInt(n));
|
||||
const c = F.mul(F.sub(tm, F.ONE), F.inv(BigInt(n))); // c = (xⁿ - 1)/n
|
||||
const denom = _create(n);
|
||||
for (let i = 0; i < n; i++)
|
||||
denom[i] = F.sub(x, cache[i]);
|
||||
const inv = F.invertBatch(denom);
|
||||
for (let i = 0; i < n; i++)
|
||||
out[i] = F.mul(c, F.mul(cache[i], inv[i]));
|
||||
return out;
|
||||
},
|
||||
eval(a, x, brp = false) {
|
||||
checkLength(a);
|
||||
const idx = findOmegaIndex(x, a.length, brp);
|
||||
if (idx !== -1)
|
||||
return a[idx]; // fast path
|
||||
const L = this.basis(x, a.length, brp); // Lᵢ(x)
|
||||
let acc = F.ZERO;
|
||||
for (let i = 0; i < a.length; i++)
|
||||
if (!F.is0(a[i]))
|
||||
acc = F.add(acc, F.mul(a[i], L[i]));
|
||||
return acc;
|
||||
},
|
||||
},
|
||||
vanishing(roots) {
|
||||
checkLength(roots);
|
||||
const out = _create(roots.length + 1, F.ZERO);
|
||||
out[0] = F.ONE;
|
||||
for (const r of roots) {
|
||||
const neg = F.neg(r);
|
||||
for (let j = out.length - 1; j > 0; j--)
|
||||
out[j] = F.add(F.mul(out[j], neg), out[j - 1]);
|
||||
out[0] = F.mul(out[0], neg);
|
||||
}
|
||||
return out;
|
||||
},
|
||||
};
|
||||
}
|
||||
//# sourceMappingURL=fft.js.map
|
||||
1
node_modules/@noble/curves/esm/abstract/fft.js.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/fft.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
102
node_modules/@noble/curves/esm/abstract/hash-to-curve.d.ts
generated
vendored
Normal file
102
node_modules/@noble/curves/esm/abstract/hash-to-curve.d.ts
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* hash-to-curve from RFC 9380.
|
||||
* Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F.
|
||||
* https://www.rfc-editor.org/rfc/rfc9380
|
||||
* @module
|
||||
*/
|
||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||
import type { CHash } from '../utils.ts';
|
||||
import type { AffinePoint, Group, GroupConstructor } from './curve.ts';
|
||||
import { type IField } from './modular.ts';
|
||||
export type UnicodeOrBytes = string | Uint8Array;
|
||||
/**
|
||||
* * `DST` is a domain separation tag, defined in section 2.2.5
|
||||
* * `p` characteristic of F, where F is a finite field of characteristic p and order q = p^m
|
||||
* * `m` is extension degree (1 for prime fields)
|
||||
* * `k` is the target security target in bits (e.g. 128), from section 5.1
|
||||
* * `expand` is `xmd` (SHA2, SHA3, BLAKE) or `xof` (SHAKE, BLAKE-XOF)
|
||||
* * `hash` conforming to `utils.CHash` interface, with `outputLen` / `blockLen` props
|
||||
*/
|
||||
export type H2COpts = {
|
||||
DST: UnicodeOrBytes;
|
||||
expand: 'xmd' | 'xof';
|
||||
hash: CHash;
|
||||
p: bigint;
|
||||
m: number;
|
||||
k: number;
|
||||
};
|
||||
export type H2CHashOpts = {
|
||||
expand: 'xmd' | 'xof';
|
||||
hash: CHash;
|
||||
};
|
||||
export type Opts = H2COpts;
|
||||
/**
|
||||
* Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits.
|
||||
* [RFC 9380 5.3.1](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.1).
|
||||
*/
|
||||
export declare function expand_message_xmd(msg: Uint8Array, DST: UnicodeOrBytes, lenInBytes: number, H: CHash): Uint8Array;
|
||||
/**
|
||||
* Produces a uniformly random byte string using an extendable-output function (XOF) H.
|
||||
* 1. The collision resistance of H MUST be at least k bits.
|
||||
* 2. H MUST be an XOF that has been proved indifferentiable from
|
||||
* a random oracle under a reasonable cryptographic assumption.
|
||||
* [RFC 9380 5.3.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.2).
|
||||
*/
|
||||
export declare function expand_message_xof(msg: Uint8Array, DST: UnicodeOrBytes, lenInBytes: number, k: number, H: CHash): Uint8Array;
|
||||
/**
|
||||
* Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F.
|
||||
* [RFC 9380 5.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.2).
|
||||
* @param msg a byte string containing the message to hash
|
||||
* @param count the number of elements of F to output
|
||||
* @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above
|
||||
* @returns [u_0, ..., u_(count - 1)], a list of field elements.
|
||||
*/
|
||||
export declare function hash_to_field(msg: Uint8Array, count: number, options: H2COpts): bigint[][];
|
||||
export type XY<T> = (x: T, y: T) => {
|
||||
x: T;
|
||||
y: T;
|
||||
};
|
||||
export type XYRatio<T> = [T[], T[], T[], T[]];
|
||||
export declare function isogenyMap<T, F extends IField<T>>(field: F, map: XYRatio<T>): XY<T>;
|
||||
/** Point interface, which curves must implement to work correctly with the module. */
|
||||
export interface H2CPoint<T> extends Group<H2CPoint<T>> {
|
||||
add(rhs: H2CPoint<T>): H2CPoint<T>;
|
||||
toAffine(iz?: bigint): AffinePoint<T>;
|
||||
clearCofactor(): H2CPoint<T>;
|
||||
assertValidity(): void;
|
||||
}
|
||||
export interface H2CPointConstructor<T> extends GroupConstructor<H2CPoint<T>> {
|
||||
fromAffine(ap: AffinePoint<T>): H2CPoint<T>;
|
||||
}
|
||||
export type MapToCurve<T> = (scalar: bigint[]) => AffinePoint<T>;
|
||||
export type htfBasicOpts = {
|
||||
DST: UnicodeOrBytes;
|
||||
};
|
||||
export type H2CMethod<T> = (msg: Uint8Array, options?: htfBasicOpts) => H2CPoint<T>;
|
||||
export type HTFMethod<T> = H2CMethod<T>;
|
||||
export type MapMethod<T> = (scalars: bigint[]) => H2CPoint<T>;
|
||||
export type H2CHasherBase<T> = {
|
||||
hashToCurve: H2CMethod<T>;
|
||||
hashToScalar: (msg: Uint8Array, options: htfBasicOpts) => bigint;
|
||||
};
|
||||
/**
|
||||
* RFC 9380 methods, with cofactor clearing. See https://www.rfc-editor.org/rfc/rfc9380#section-3.
|
||||
*
|
||||
* * hashToCurve: `map(hash(input))`, encodes RANDOM bytes to curve (WITH hashing)
|
||||
* * encodeToCurve: `map(hash(input))`, encodes NON-UNIFORM bytes to curve (WITH hashing)
|
||||
* * mapToCurve: `map(scalars)`, encodes NON-UNIFORM scalars to curve (NO hashing)
|
||||
*/
|
||||
export type H2CHasher<T> = H2CHasherBase<T> & {
|
||||
encodeToCurve: H2CMethod<T>;
|
||||
mapToCurve: MapMethod<T>;
|
||||
defaults: H2COpts & {
|
||||
encodeDST?: UnicodeOrBytes;
|
||||
};
|
||||
};
|
||||
export type Hasher<T> = H2CHasher<T>;
|
||||
export declare const _DST_scalar: Uint8Array;
|
||||
/** Creates hash-to-curve methods from EC Point and mapToCurve function. See {@link H2CHasher}. */
|
||||
export declare function createHasher<T>(Point: H2CPointConstructor<T>, mapToCurve: MapToCurve<T>, defaults: H2COpts & {
|
||||
encodeDST?: UnicodeOrBytes;
|
||||
}): H2CHasher<T>;
|
||||
//# sourceMappingURL=hash-to-curve.d.ts.map
|
||||
1
node_modules/@noble/curves/esm/abstract/hash-to-curve.d.ts.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/hash-to-curve.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"hash-to-curve.d.ts","sourceRoot":"","sources":["../../src/abstract/hash-to-curve.ts"],"names":[],"mappings":"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"}
|
||||
203
node_modules/@noble/curves/esm/abstract/hash-to-curve.js
generated
vendored
Normal file
203
node_modules/@noble/curves/esm/abstract/hash-to-curve.js
generated
vendored
Normal file
@@ -0,0 +1,203 @@
|
||||
import { _validateObject, abytes, bytesToNumberBE, concatBytes, isBytes, isHash, utf8ToBytes, } from "../utils.js";
|
||||
import { FpInvertBatch, mod } from "./modular.js";
|
||||
// Octet Stream to Integer. "spec" implementation of os2ip is 2.5x slower vs bytesToNumberBE.
|
||||
const os2ip = bytesToNumberBE;
|
||||
// Integer to Octet Stream (numberToBytesBE)
|
||||
function i2osp(value, length) {
|
||||
anum(value);
|
||||
anum(length);
|
||||
if (value < 0 || value >= 1 << (8 * length))
|
||||
throw new Error('invalid I2OSP input: ' + value);
|
||||
const res = Array.from({ length }).fill(0);
|
||||
for (let i = length - 1; i >= 0; i--) {
|
||||
res[i] = value & 0xff;
|
||||
value >>>= 8;
|
||||
}
|
||||
return new Uint8Array(res);
|
||||
}
|
||||
function strxor(a, b) {
|
||||
const arr = new Uint8Array(a.length);
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
arr[i] = a[i] ^ b[i];
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
function anum(item) {
|
||||
if (!Number.isSafeInteger(item))
|
||||
throw new Error('number expected');
|
||||
}
|
||||
function normDST(DST) {
|
||||
if (!isBytes(DST) && typeof DST !== 'string')
|
||||
throw new Error('DST must be Uint8Array or string');
|
||||
return typeof DST === 'string' ? utf8ToBytes(DST) : DST;
|
||||
}
|
||||
/**
|
||||
* Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits.
|
||||
* [RFC 9380 5.3.1](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.1).
|
||||
*/
|
||||
export function expand_message_xmd(msg, DST, lenInBytes, H) {
|
||||
abytes(msg);
|
||||
anum(lenInBytes);
|
||||
DST = normDST(DST);
|
||||
// https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3
|
||||
if (DST.length > 255)
|
||||
DST = H(concatBytes(utf8ToBytes('H2C-OVERSIZE-DST-'), DST));
|
||||
const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H;
|
||||
const ell = Math.ceil(lenInBytes / b_in_bytes);
|
||||
if (lenInBytes > 65535 || ell > 255)
|
||||
throw new Error('expand_message_xmd: invalid lenInBytes');
|
||||
const DST_prime = concatBytes(DST, i2osp(DST.length, 1));
|
||||
const Z_pad = i2osp(0, r_in_bytes);
|
||||
const l_i_b_str = i2osp(lenInBytes, 2); // len_in_bytes_str
|
||||
const b = new Array(ell);
|
||||
const b_0 = H(concatBytes(Z_pad, msg, l_i_b_str, i2osp(0, 1), DST_prime));
|
||||
b[0] = H(concatBytes(b_0, i2osp(1, 1), DST_prime));
|
||||
for (let i = 1; i <= ell; i++) {
|
||||
const args = [strxor(b_0, b[i - 1]), i2osp(i + 1, 1), DST_prime];
|
||||
b[i] = H(concatBytes(...args));
|
||||
}
|
||||
const pseudo_random_bytes = concatBytes(...b);
|
||||
return pseudo_random_bytes.slice(0, lenInBytes);
|
||||
}
|
||||
/**
|
||||
* Produces a uniformly random byte string using an extendable-output function (XOF) H.
|
||||
* 1. The collision resistance of H MUST be at least k bits.
|
||||
* 2. H MUST be an XOF that has been proved indifferentiable from
|
||||
* a random oracle under a reasonable cryptographic assumption.
|
||||
* [RFC 9380 5.3.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.2).
|
||||
*/
|
||||
export function expand_message_xof(msg, DST, lenInBytes, k, H) {
|
||||
abytes(msg);
|
||||
anum(lenInBytes);
|
||||
DST = normDST(DST);
|
||||
// https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3
|
||||
// DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8));
|
||||
if (DST.length > 255) {
|
||||
const dkLen = Math.ceil((2 * k) / 8);
|
||||
DST = H.create({ dkLen }).update(utf8ToBytes('H2C-OVERSIZE-DST-')).update(DST).digest();
|
||||
}
|
||||
if (lenInBytes > 65535 || DST.length > 255)
|
||||
throw new Error('expand_message_xof: invalid lenInBytes');
|
||||
return (H.create({ dkLen: lenInBytes })
|
||||
.update(msg)
|
||||
.update(i2osp(lenInBytes, 2))
|
||||
// 2. DST_prime = DST || I2OSP(len(DST), 1)
|
||||
.update(DST)
|
||||
.update(i2osp(DST.length, 1))
|
||||
.digest());
|
||||
}
|
||||
/**
|
||||
* Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F.
|
||||
* [RFC 9380 5.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.2).
|
||||
* @param msg a byte string containing the message to hash
|
||||
* @param count the number of elements of F to output
|
||||
* @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above
|
||||
* @returns [u_0, ..., u_(count - 1)], a list of field elements.
|
||||
*/
|
||||
export function hash_to_field(msg, count, options) {
|
||||
_validateObject(options, {
|
||||
p: 'bigint',
|
||||
m: 'number',
|
||||
k: 'number',
|
||||
hash: 'function',
|
||||
});
|
||||
const { p, k, m, hash, expand, DST } = options;
|
||||
if (!isHash(options.hash))
|
||||
throw new Error('expected valid hash');
|
||||
abytes(msg);
|
||||
anum(count);
|
||||
const log2p = p.toString(2).length;
|
||||
const L = Math.ceil((log2p + k) / 8); // section 5.1 of ietf draft link above
|
||||
const len_in_bytes = count * m * L;
|
||||
let prb; // pseudo_random_bytes
|
||||
if (expand === 'xmd') {
|
||||
prb = expand_message_xmd(msg, DST, len_in_bytes, hash);
|
||||
}
|
||||
else if (expand === 'xof') {
|
||||
prb = expand_message_xof(msg, DST, len_in_bytes, k, hash);
|
||||
}
|
||||
else if (expand === '_internal_pass') {
|
||||
// for internal tests only
|
||||
prb = msg;
|
||||
}
|
||||
else {
|
||||
throw new Error('expand must be "xmd" or "xof"');
|
||||
}
|
||||
const u = new Array(count);
|
||||
for (let i = 0; i < count; i++) {
|
||||
const e = new Array(m);
|
||||
for (let j = 0; j < m; j++) {
|
||||
const elm_offset = L * (j + i * m);
|
||||
const tv = prb.subarray(elm_offset, elm_offset + L);
|
||||
e[j] = mod(os2ip(tv), p);
|
||||
}
|
||||
u[i] = e;
|
||||
}
|
||||
return u;
|
||||
}
|
||||
export function isogenyMap(field, map) {
|
||||
// Make same order as in spec
|
||||
const coeff = map.map((i) => Array.from(i).reverse());
|
||||
return (x, y) => {
|
||||
const [xn, xd, yn, yd] = coeff.map((val) => val.reduce((acc, i) => field.add(field.mul(acc, x), i)));
|
||||
// 6.6.3
|
||||
// Exceptional cases of iso_map are inputs that cause the denominator of
|
||||
// either rational function to evaluate to zero; such cases MUST return
|
||||
// the identity point on E.
|
||||
const [xd_inv, yd_inv] = FpInvertBatch(field, [xd, yd], true);
|
||||
x = field.mul(xn, xd_inv); // xNum / xDen
|
||||
y = field.mul(y, field.mul(yn, yd_inv)); // y * (yNum / yDev)
|
||||
return { x, y };
|
||||
};
|
||||
}
|
||||
export const _DST_scalar = utf8ToBytes('HashToScalar-');
|
||||
/** Creates hash-to-curve methods from EC Point and mapToCurve function. See {@link H2CHasher}. */
|
||||
export function createHasher(Point, mapToCurve, defaults) {
|
||||
if (typeof mapToCurve !== 'function')
|
||||
throw new Error('mapToCurve() must be defined');
|
||||
function map(num) {
|
||||
return Point.fromAffine(mapToCurve(num));
|
||||
}
|
||||
function clear(initial) {
|
||||
const P = initial.clearCofactor();
|
||||
if (P.equals(Point.ZERO))
|
||||
return Point.ZERO; // zero will throw in assert
|
||||
P.assertValidity();
|
||||
return P;
|
||||
}
|
||||
return {
|
||||
defaults,
|
||||
hashToCurve(msg, options) {
|
||||
const opts = Object.assign({}, defaults, options);
|
||||
const u = hash_to_field(msg, 2, opts);
|
||||
const u0 = map(u[0]);
|
||||
const u1 = map(u[1]);
|
||||
return clear(u0.add(u1));
|
||||
},
|
||||
encodeToCurve(msg, options) {
|
||||
const optsDst = defaults.encodeDST ? { DST: defaults.encodeDST } : {};
|
||||
const opts = Object.assign({}, defaults, optsDst, options);
|
||||
const u = hash_to_field(msg, 1, opts);
|
||||
const u0 = map(u[0]);
|
||||
return clear(u0);
|
||||
},
|
||||
/** See {@link H2CHasher} */
|
||||
mapToCurve(scalars) {
|
||||
if (!Array.isArray(scalars))
|
||||
throw new Error('expected array of bigints');
|
||||
for (const i of scalars)
|
||||
if (typeof i !== 'bigint')
|
||||
throw new Error('expected array of bigints');
|
||||
return clear(map(scalars));
|
||||
},
|
||||
// hash_to_scalar can produce 0: https://www.rfc-editor.org/errata/eid8393
|
||||
// RFC 9380, draft-irtf-cfrg-bbs-signatures-08
|
||||
hashToScalar(msg, options) {
|
||||
// @ts-ignore
|
||||
const N = Point.Fn.ORDER;
|
||||
const opts = Object.assign({}, defaults, { p: N, m: 1, DST: _DST_scalar }, options);
|
||||
return hash_to_field(msg, 1, opts)[0][0];
|
||||
},
|
||||
};
|
||||
}
|
||||
//# sourceMappingURL=hash-to-curve.js.map
|
||||
1
node_modules/@noble/curves/esm/abstract/hash-to-curve.js.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/hash-to-curve.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
171
node_modules/@noble/curves/esm/abstract/modular.d.ts
generated
vendored
Normal file
171
node_modules/@noble/curves/esm/abstract/modular.d.ts
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
export declare function mod(a: bigint, b: bigint): bigint;
|
||||
/**
|
||||
* Efficiently raise num to power and do modular division.
|
||||
* Unsafe in some contexts: uses ladder, so can expose bigint bits.
|
||||
* @example
|
||||
* pow(2n, 6n, 11n) // 64n % 11n == 9n
|
||||
*/
|
||||
export declare function pow(num: bigint, power: bigint, modulo: bigint): bigint;
|
||||
/** Does `x^(2^power)` mod p. `pow2(30, 4)` == `30^(2^4)` */
|
||||
export declare function pow2(x: bigint, power: bigint, modulo: bigint): bigint;
|
||||
/**
|
||||
* Inverses number over modulo.
|
||||
* Implemented using [Euclidean GCD](https://brilliant.org/wiki/extended-euclidean-algorithm/).
|
||||
*/
|
||||
export declare function invert(number: bigint, modulo: bigint): bigint;
|
||||
/**
|
||||
* Tonelli-Shanks square root search algorithm.
|
||||
* 1. https://eprint.iacr.org/2012/685.pdf (page 12)
|
||||
* 2. Square Roots from 1; 24, 51, 10 to Dan Shanks
|
||||
* @param P field order
|
||||
* @returns function that takes field Fp (created from P) and number n
|
||||
*/
|
||||
export declare function tonelliShanks(P: bigint): <T>(Fp: IField<T>, n: T) => T;
|
||||
/**
|
||||
* Square root for a finite field. Will try optimized versions first:
|
||||
*
|
||||
* 1. P ≡ 3 (mod 4)
|
||||
* 2. P ≡ 5 (mod 8)
|
||||
* 3. P ≡ 9 (mod 16)
|
||||
* 4. Tonelli-Shanks algorithm
|
||||
*
|
||||
* Different algorithms can give different roots, it is up to user to decide which one they want.
|
||||
* For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve).
|
||||
*/
|
||||
export declare function FpSqrt(P: bigint): <T>(Fp: IField<T>, n: T) => T;
|
||||
export declare const isNegativeLE: (num: bigint, modulo: bigint) => boolean;
|
||||
/** Field is not always over prime: for example, Fp2 has ORDER(q)=p^m. */
|
||||
export interface IField<T> {
|
||||
ORDER: bigint;
|
||||
isLE: boolean;
|
||||
BYTES: number;
|
||||
BITS: number;
|
||||
MASK: bigint;
|
||||
ZERO: T;
|
||||
ONE: T;
|
||||
create: (num: T) => T;
|
||||
isValid: (num: T) => boolean;
|
||||
is0: (num: T) => boolean;
|
||||
isValidNot0: (num: T) => boolean;
|
||||
neg(num: T): T;
|
||||
inv(num: T): T;
|
||||
sqrt(num: T): T;
|
||||
sqr(num: T): T;
|
||||
eql(lhs: T, rhs: T): boolean;
|
||||
add(lhs: T, rhs: T): T;
|
||||
sub(lhs: T, rhs: T): T;
|
||||
mul(lhs: T, rhs: T | bigint): T;
|
||||
pow(lhs: T, power: bigint): T;
|
||||
div(lhs: T, rhs: T | bigint): T;
|
||||
addN(lhs: T, rhs: T): T;
|
||||
subN(lhs: T, rhs: T): T;
|
||||
mulN(lhs: T, rhs: T | bigint): T;
|
||||
sqrN(num: T): T;
|
||||
isOdd?(num: T): boolean;
|
||||
allowedLengths?: number[];
|
||||
invertBatch: (lst: T[]) => T[];
|
||||
toBytes(num: T): Uint8Array;
|
||||
fromBytes(bytes: Uint8Array, skipValidation?: boolean): T;
|
||||
cmov(a: T, b: T, c: boolean): T;
|
||||
}
|
||||
export declare function validateField<T>(field: IField<T>): IField<T>;
|
||||
/**
|
||||
* Same as `pow` but for Fp: non-constant-time.
|
||||
* Unsafe in some contexts: uses ladder, so can expose bigint bits.
|
||||
*/
|
||||
export declare function FpPow<T>(Fp: IField<T>, num: T, power: bigint): T;
|
||||
/**
|
||||
* Efficiently invert an array of Field elements.
|
||||
* Exception-free. Will return `undefined` for 0 elements.
|
||||
* @param passZero map 0 to 0 (instead of undefined)
|
||||
*/
|
||||
export declare function FpInvertBatch<T>(Fp: IField<T>, nums: T[], passZero?: boolean): T[];
|
||||
export declare function FpDiv<T>(Fp: IField<T>, lhs: T, rhs: T | bigint): T;
|
||||
/**
|
||||
* Legendre symbol.
|
||||
* Legendre constant is used to calculate Legendre symbol (a | p)
|
||||
* which denotes the value of a^((p-1)/2) (mod p).
|
||||
*
|
||||
* * (a | p) ≡ 1 if a is a square (mod p), quadratic residue
|
||||
* * (a | p) ≡ -1 if a is not a square (mod p), quadratic non residue
|
||||
* * (a | p) ≡ 0 if a ≡ 0 (mod p)
|
||||
*/
|
||||
export declare function FpLegendre<T>(Fp: IField<T>, n: T): -1 | 0 | 1;
|
||||
export declare function FpIsSquare<T>(Fp: IField<T>, n: T): boolean;
|
||||
export type NLength = {
|
||||
nByteLength: number;
|
||||
nBitLength: number;
|
||||
};
|
||||
export declare function nLength(n: bigint, nBitLength?: number): NLength;
|
||||
type FpField = IField<bigint> & Required<Pick<IField<bigint>, 'isOdd'>>;
|
||||
type SqrtFn = (n: bigint) => bigint;
|
||||
type FieldOpts = Partial<{
|
||||
sqrt: SqrtFn;
|
||||
isLE: boolean;
|
||||
BITS: number;
|
||||
modFromBytes: boolean;
|
||||
allowedLengths?: readonly number[];
|
||||
}>;
|
||||
/**
|
||||
* Creates a finite field. Major performance optimizations:
|
||||
* * 1. Denormalized operations like mulN instead of mul.
|
||||
* * 2. Identical object shape: never add or remove keys.
|
||||
* * 3. `Object.freeze`.
|
||||
* Fragile: always run a benchmark on a change.
|
||||
* Security note: operations don't check 'isValid' for all elements for performance reasons,
|
||||
* it is caller responsibility to check this.
|
||||
* This is low-level code, please make sure you know what you're doing.
|
||||
*
|
||||
* Note about field properties:
|
||||
* * CHARACTERISTIC p = prime number, number of elements in main subgroup.
|
||||
* * ORDER q = similar to cofactor in curves, may be composite `q = p^m`.
|
||||
*
|
||||
* @param ORDER field order, probably prime, or could be composite
|
||||
* @param bitLen how many bits the field consumes
|
||||
* @param isLE (default: false) if encoding / decoding should be in little-endian
|
||||
* @param redef optional faster redefinitions of sqrt and other methods
|
||||
*/
|
||||
export declare function Field(ORDER: bigint, bitLenOrOpts?: number | FieldOpts, // TODO: use opts only in v2?
|
||||
isLE?: boolean, opts?: {
|
||||
sqrt?: SqrtFn;
|
||||
}): Readonly<FpField>;
|
||||
export declare function FpSqrtOdd<T>(Fp: IField<T>, elm: T): T;
|
||||
export declare function FpSqrtEven<T>(Fp: IField<T>, elm: T): T;
|
||||
/**
|
||||
* "Constant-time" private key generation utility.
|
||||
* Same as mapKeyToField, but accepts less bytes (40 instead of 48 for 32-byte field).
|
||||
* Which makes it slightly more biased, less secure.
|
||||
* @deprecated use `mapKeyToField` instead
|
||||
*/
|
||||
export declare function hashToPrivateScalar(hash: string | Uint8Array, groupOrder: bigint, isLE?: boolean): bigint;
|
||||
/**
|
||||
* Returns total number of bytes consumed by the field element.
|
||||
* For example, 32 bytes for usual 256-bit weierstrass curve.
|
||||
* @param fieldOrder number of field elements, usually CURVE.n
|
||||
* @returns byte length of field
|
||||
*/
|
||||
export declare function getFieldBytesLength(fieldOrder: bigint): number;
|
||||
/**
|
||||
* Returns minimal amount of bytes that can be safely reduced
|
||||
* by field order.
|
||||
* Should be 2^-128 for 128-bit curve such as P256.
|
||||
* @param fieldOrder number of field elements, usually CURVE.n
|
||||
* @returns byte length of target hash
|
||||
*/
|
||||
export declare function getMinHashLength(fieldOrder: bigint): number;
|
||||
/**
|
||||
* "Constant-time" private key generation utility.
|
||||
* Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF
|
||||
* and convert them into private scalar, with the modulo bias being negligible.
|
||||
* Needs at least 48 bytes of input for 32-byte private key.
|
||||
* https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
|
||||
* FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final
|
||||
* RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5
|
||||
* @param hash hash output from SHA3 or a similar function
|
||||
* @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n)
|
||||
* @param isLE interpret hash bytes as LE num
|
||||
* @returns valid private scalar
|
||||
*/
|
||||
export declare function mapHashToField(key: Uint8Array, fieldOrder: bigint, isLE?: boolean): Uint8Array;
|
||||
export {};
|
||||
//# sourceMappingURL=modular.d.ts.map
|
||||
1
node_modules/@noble/curves/esm/abstract/modular.d.ts.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/modular.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"modular.d.ts","sourceRoot":"","sources":["../../src/abstract/modular.ts"],"names":[],"mappings":"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"}
|
||||
530
node_modules/@noble/curves/esm/abstract/modular.js
generated
vendored
Normal file
530
node_modules/@noble/curves/esm/abstract/modular.js
generated
vendored
Normal file
@@ -0,0 +1,530 @@
|
||||
/**
|
||||
* Utils for modular division and fields.
|
||||
* Field over 11 is a finite (Galois) field is integer number operations `mod 11`.
|
||||
* There is no division: it is replaced by modular multiplicative inverse.
|
||||
* @module
|
||||
*/
|
||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||
import { _validateObject, anumber, bitMask, bytesToNumberBE, bytesToNumberLE, ensureBytes, numberToBytesBE, numberToBytesLE, } from "../utils.js";
|
||||
// prettier-ignore
|
||||
const _0n = BigInt(0), _1n = BigInt(1), _2n = /* @__PURE__ */ BigInt(2), _3n = /* @__PURE__ */ BigInt(3);
|
||||
// prettier-ignore
|
||||
const _4n = /* @__PURE__ */ BigInt(4), _5n = /* @__PURE__ */ BigInt(5), _7n = /* @__PURE__ */ BigInt(7);
|
||||
// prettier-ignore
|
||||
const _8n = /* @__PURE__ */ BigInt(8), _9n = /* @__PURE__ */ BigInt(9), _16n = /* @__PURE__ */ BigInt(16);
|
||||
// Calculates a modulo b
|
||||
export function mod(a, b) {
|
||||
const result = a % b;
|
||||
return result >= _0n ? result : b + result;
|
||||
}
|
||||
/**
|
||||
* Efficiently raise num to power and do modular division.
|
||||
* Unsafe in some contexts: uses ladder, so can expose bigint bits.
|
||||
* @example
|
||||
* pow(2n, 6n, 11n) // 64n % 11n == 9n
|
||||
*/
|
||||
export function pow(num, power, modulo) {
|
||||
return FpPow(Field(modulo), num, power);
|
||||
}
|
||||
/** Does `x^(2^power)` mod p. `pow2(30, 4)` == `30^(2^4)` */
|
||||
export function pow2(x, power, modulo) {
|
||||
let res = x;
|
||||
while (power-- > _0n) {
|
||||
res *= res;
|
||||
res %= modulo;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
/**
|
||||
* Inverses number over modulo.
|
||||
* Implemented using [Euclidean GCD](https://brilliant.org/wiki/extended-euclidean-algorithm/).
|
||||
*/
|
||||
export function invert(number, modulo) {
|
||||
if (number === _0n)
|
||||
throw new Error('invert: expected non-zero number');
|
||||
if (modulo <= _0n)
|
||||
throw new Error('invert: expected positive modulus, got ' + modulo);
|
||||
// Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower.
|
||||
let a = mod(number, modulo);
|
||||
let b = modulo;
|
||||
// prettier-ignore
|
||||
let x = _0n, y = _1n, u = _1n, v = _0n;
|
||||
while (a !== _0n) {
|
||||
// JIT applies optimization if those two lines follow each other
|
||||
const q = b / a;
|
||||
const r = b % a;
|
||||
const m = x - u * q;
|
||||
const n = y - v * q;
|
||||
// prettier-ignore
|
||||
b = a, a = r, x = u, y = v, u = m, v = n;
|
||||
}
|
||||
const gcd = b;
|
||||
if (gcd !== _1n)
|
||||
throw new Error('invert: does not exist');
|
||||
return mod(x, modulo);
|
||||
}
|
||||
function assertIsSquare(Fp, root, n) {
|
||||
if (!Fp.eql(Fp.sqr(root), n))
|
||||
throw new Error('Cannot find square root');
|
||||
}
|
||||
// Not all roots are possible! Example which will throw:
|
||||
// const NUM =
|
||||
// n = 72057594037927816n;
|
||||
// Fp = Field(BigInt('0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab'));
|
||||
function sqrt3mod4(Fp, n) {
|
||||
const p1div4 = (Fp.ORDER + _1n) / _4n;
|
||||
const root = Fp.pow(n, p1div4);
|
||||
assertIsSquare(Fp, root, n);
|
||||
return root;
|
||||
}
|
||||
function sqrt5mod8(Fp, n) {
|
||||
const p5div8 = (Fp.ORDER - _5n) / _8n;
|
||||
const n2 = Fp.mul(n, _2n);
|
||||
const v = Fp.pow(n2, p5div8);
|
||||
const nv = Fp.mul(n, v);
|
||||
const i = Fp.mul(Fp.mul(nv, _2n), v);
|
||||
const root = Fp.mul(nv, Fp.sub(i, Fp.ONE));
|
||||
assertIsSquare(Fp, root, n);
|
||||
return root;
|
||||
}
|
||||
// Based on RFC9380, Kong algorithm
|
||||
// prettier-ignore
|
||||
function sqrt9mod16(P) {
|
||||
const Fp_ = Field(P);
|
||||
const tn = tonelliShanks(P);
|
||||
const c1 = tn(Fp_, Fp_.neg(Fp_.ONE)); // 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F
|
||||
const c2 = tn(Fp_, c1); // 2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F
|
||||
const c3 = tn(Fp_, Fp_.neg(c1)); // 3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F
|
||||
const c4 = (P + _7n) / _16n; // 4. c4 = (q + 7) / 16 # Integer arithmetic
|
||||
return (Fp, n) => {
|
||||
let tv1 = Fp.pow(n, c4); // 1. tv1 = x^c4
|
||||
let tv2 = Fp.mul(tv1, c1); // 2. tv2 = c1 * tv1
|
||||
const tv3 = Fp.mul(tv1, c2); // 3. tv3 = c2 * tv1
|
||||
const tv4 = Fp.mul(tv1, c3); // 4. tv4 = c3 * tv1
|
||||
const e1 = Fp.eql(Fp.sqr(tv2), n); // 5. e1 = (tv2^2) == x
|
||||
const e2 = Fp.eql(Fp.sqr(tv3), n); // 6. e2 = (tv3^2) == x
|
||||
tv1 = Fp.cmov(tv1, tv2, e1); // 7. tv1 = CMOV(tv1, tv2, e1) # Select tv2 if (tv2^2) == x
|
||||
tv2 = Fp.cmov(tv4, tv3, e2); // 8. tv2 = CMOV(tv4, tv3, e2) # Select tv3 if (tv3^2) == x
|
||||
const e3 = Fp.eql(Fp.sqr(tv2), n); // 9. e3 = (tv2^2) == x
|
||||
const root = Fp.cmov(tv1, tv2, e3); // 10. z = CMOV(tv1, tv2, e3) # Select sqrt from tv1 & tv2
|
||||
assertIsSquare(Fp, root, n);
|
||||
return root;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Tonelli-Shanks square root search algorithm.
|
||||
* 1. https://eprint.iacr.org/2012/685.pdf (page 12)
|
||||
* 2. Square Roots from 1; 24, 51, 10 to Dan Shanks
|
||||
* @param P field order
|
||||
* @returns function that takes field Fp (created from P) and number n
|
||||
*/
|
||||
export function tonelliShanks(P) {
|
||||
// Initialization (precomputation).
|
||||
// Caching initialization could boost perf by 7%.
|
||||
if (P < _3n)
|
||||
throw new Error('sqrt is not defined for small field');
|
||||
// Factor P - 1 = Q * 2^S, where Q is odd
|
||||
let Q = P - _1n;
|
||||
let S = 0;
|
||||
while (Q % _2n === _0n) {
|
||||
Q /= _2n;
|
||||
S++;
|
||||
}
|
||||
// Find the first quadratic non-residue Z >= 2
|
||||
let Z = _2n;
|
||||
const _Fp = Field(P);
|
||||
while (FpLegendre(_Fp, Z) === 1) {
|
||||
// Basic primality test for P. After x iterations, chance of
|
||||
// not finding quadratic non-residue is 2^x, so 2^1000.
|
||||
if (Z++ > 1000)
|
||||
throw new Error('Cannot find square root: probably non-prime P');
|
||||
}
|
||||
// Fast-path; usually done before Z, but we do "primality test".
|
||||
if (S === 1)
|
||||
return sqrt3mod4;
|
||||
// Slow-path
|
||||
// TODO: test on Fp2 and others
|
||||
let cc = _Fp.pow(Z, Q); // c = z^Q
|
||||
const Q1div2 = (Q + _1n) / _2n;
|
||||
return function tonelliSlow(Fp, n) {
|
||||
if (Fp.is0(n))
|
||||
return n;
|
||||
// Check if n is a quadratic residue using Legendre symbol
|
||||
if (FpLegendre(Fp, n) !== 1)
|
||||
throw new Error('Cannot find square root');
|
||||
// Initialize variables for the main loop
|
||||
let M = S;
|
||||
let c = Fp.mul(Fp.ONE, cc); // c = z^Q, move cc from field _Fp into field Fp
|
||||
let t = Fp.pow(n, Q); // t = n^Q, first guess at the fudge factor
|
||||
let R = Fp.pow(n, Q1div2); // R = n^((Q+1)/2), first guess at the square root
|
||||
// Main loop
|
||||
// while t != 1
|
||||
while (!Fp.eql(t, Fp.ONE)) {
|
||||
if (Fp.is0(t))
|
||||
return Fp.ZERO; // if t=0 return R=0
|
||||
let i = 1;
|
||||
// Find the smallest i >= 1 such that t^(2^i) ≡ 1 (mod P)
|
||||
let t_tmp = Fp.sqr(t); // t^(2^1)
|
||||
while (!Fp.eql(t_tmp, Fp.ONE)) {
|
||||
i++;
|
||||
t_tmp = Fp.sqr(t_tmp); // t^(2^2)...
|
||||
if (i === M)
|
||||
throw new Error('Cannot find square root');
|
||||
}
|
||||
// Calculate the exponent for b: 2^(M - i - 1)
|
||||
const exponent = _1n << BigInt(M - i - 1); // bigint is important
|
||||
const b = Fp.pow(c, exponent); // b = 2^(M - i - 1)
|
||||
// Update variables
|
||||
M = i;
|
||||
c = Fp.sqr(b); // c = b^2
|
||||
t = Fp.mul(t, c); // t = (t * b^2)
|
||||
R = Fp.mul(R, b); // R = R*b
|
||||
}
|
||||
return R;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Square root for a finite field. Will try optimized versions first:
|
||||
*
|
||||
* 1. P ≡ 3 (mod 4)
|
||||
* 2. P ≡ 5 (mod 8)
|
||||
* 3. P ≡ 9 (mod 16)
|
||||
* 4. Tonelli-Shanks algorithm
|
||||
*
|
||||
* Different algorithms can give different roots, it is up to user to decide which one they want.
|
||||
* For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve).
|
||||
*/
|
||||
export function FpSqrt(P) {
|
||||
// P ≡ 3 (mod 4) => √n = n^((P+1)/4)
|
||||
if (P % _4n === _3n)
|
||||
return sqrt3mod4;
|
||||
// P ≡ 5 (mod 8) => Atkin algorithm, page 10 of https://eprint.iacr.org/2012/685.pdf
|
||||
if (P % _8n === _5n)
|
||||
return sqrt5mod8;
|
||||
// P ≡ 9 (mod 16) => Kong algorithm, page 11 of https://eprint.iacr.org/2012/685.pdf (algorithm 4)
|
||||
if (P % _16n === _9n)
|
||||
return sqrt9mod16(P);
|
||||
// Tonelli-Shanks algorithm
|
||||
return tonelliShanks(P);
|
||||
}
|
||||
// Little-endian check for first LE bit (last BE bit);
|
||||
export const isNegativeLE = (num, modulo) => (mod(num, modulo) & _1n) === _1n;
|
||||
// prettier-ignore
|
||||
const FIELD_FIELDS = [
|
||||
'create', 'isValid', 'is0', 'neg', 'inv', 'sqrt', 'sqr',
|
||||
'eql', 'add', 'sub', 'mul', 'pow', 'div',
|
||||
'addN', 'subN', 'mulN', 'sqrN'
|
||||
];
|
||||
export function validateField(field) {
|
||||
const initial = {
|
||||
ORDER: 'bigint',
|
||||
MASK: 'bigint',
|
||||
BYTES: 'number',
|
||||
BITS: 'number',
|
||||
};
|
||||
const opts = FIELD_FIELDS.reduce((map, val) => {
|
||||
map[val] = 'function';
|
||||
return map;
|
||||
}, initial);
|
||||
_validateObject(field, opts);
|
||||
// const max = 16384;
|
||||
// if (field.BYTES < 1 || field.BYTES > max) throw new Error('invalid field');
|
||||
// if (field.BITS < 1 || field.BITS > 8 * max) throw new Error('invalid field');
|
||||
return field;
|
||||
}
|
||||
// Generic field functions
|
||||
/**
|
||||
* Same as `pow` but for Fp: non-constant-time.
|
||||
* Unsafe in some contexts: uses ladder, so can expose bigint bits.
|
||||
*/
|
||||
export function FpPow(Fp, num, power) {
|
||||
if (power < _0n)
|
||||
throw new Error('invalid exponent, negatives unsupported');
|
||||
if (power === _0n)
|
||||
return Fp.ONE;
|
||||
if (power === _1n)
|
||||
return num;
|
||||
let p = Fp.ONE;
|
||||
let d = num;
|
||||
while (power > _0n) {
|
||||
if (power & _1n)
|
||||
p = Fp.mul(p, d);
|
||||
d = Fp.sqr(d);
|
||||
power >>= _1n;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
/**
|
||||
* Efficiently invert an array of Field elements.
|
||||
* Exception-free. Will return `undefined` for 0 elements.
|
||||
* @param passZero map 0 to 0 (instead of undefined)
|
||||
*/
|
||||
export function FpInvertBatch(Fp, nums, passZero = false) {
|
||||
const inverted = new Array(nums.length).fill(passZero ? Fp.ZERO : undefined);
|
||||
// Walk from first to last, multiply them by each other MOD p
|
||||
const multipliedAcc = nums.reduce((acc, num, i) => {
|
||||
if (Fp.is0(num))
|
||||
return acc;
|
||||
inverted[i] = acc;
|
||||
return Fp.mul(acc, num);
|
||||
}, Fp.ONE);
|
||||
// Invert last element
|
||||
const invertedAcc = Fp.inv(multipliedAcc);
|
||||
// Walk from last to first, multiply them by inverted each other MOD p
|
||||
nums.reduceRight((acc, num, i) => {
|
||||
if (Fp.is0(num))
|
||||
return acc;
|
||||
inverted[i] = Fp.mul(acc, inverted[i]);
|
||||
return Fp.mul(acc, num);
|
||||
}, invertedAcc);
|
||||
return inverted;
|
||||
}
|
||||
// TODO: remove
|
||||
export function FpDiv(Fp, lhs, rhs) {
|
||||
return Fp.mul(lhs, typeof rhs === 'bigint' ? invert(rhs, Fp.ORDER) : Fp.inv(rhs));
|
||||
}
|
||||
/**
|
||||
* Legendre symbol.
|
||||
* Legendre constant is used to calculate Legendre symbol (a | p)
|
||||
* which denotes the value of a^((p-1)/2) (mod p).
|
||||
*
|
||||
* * (a | p) ≡ 1 if a is a square (mod p), quadratic residue
|
||||
* * (a | p) ≡ -1 if a is not a square (mod p), quadratic non residue
|
||||
* * (a | p) ≡ 0 if a ≡ 0 (mod p)
|
||||
*/
|
||||
export function FpLegendre(Fp, n) {
|
||||
// We can use 3rd argument as optional cache of this value
|
||||
// but seems unneeded for now. The operation is very fast.
|
||||
const p1mod2 = (Fp.ORDER - _1n) / _2n;
|
||||
const powered = Fp.pow(n, p1mod2);
|
||||
const yes = Fp.eql(powered, Fp.ONE);
|
||||
const zero = Fp.eql(powered, Fp.ZERO);
|
||||
const no = Fp.eql(powered, Fp.neg(Fp.ONE));
|
||||
if (!yes && !zero && !no)
|
||||
throw new Error('invalid Legendre symbol result');
|
||||
return yes ? 1 : zero ? 0 : -1;
|
||||
}
|
||||
// This function returns True whenever the value x is a square in the field F.
|
||||
export function FpIsSquare(Fp, n) {
|
||||
const l = FpLegendre(Fp, n);
|
||||
return l === 1;
|
||||
}
|
||||
// CURVE.n lengths
|
||||
export function nLength(n, nBitLength) {
|
||||
// Bit size, byte size of CURVE.n
|
||||
if (nBitLength !== undefined)
|
||||
anumber(nBitLength);
|
||||
const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length;
|
||||
const nByteLength = Math.ceil(_nBitLength / 8);
|
||||
return { nBitLength: _nBitLength, nByteLength };
|
||||
}
|
||||
/**
|
||||
* Creates a finite field. Major performance optimizations:
|
||||
* * 1. Denormalized operations like mulN instead of mul.
|
||||
* * 2. Identical object shape: never add or remove keys.
|
||||
* * 3. `Object.freeze`.
|
||||
* Fragile: always run a benchmark on a change.
|
||||
* Security note: operations don't check 'isValid' for all elements for performance reasons,
|
||||
* it is caller responsibility to check this.
|
||||
* This is low-level code, please make sure you know what you're doing.
|
||||
*
|
||||
* Note about field properties:
|
||||
* * CHARACTERISTIC p = prime number, number of elements in main subgroup.
|
||||
* * ORDER q = similar to cofactor in curves, may be composite `q = p^m`.
|
||||
*
|
||||
* @param ORDER field order, probably prime, or could be composite
|
||||
* @param bitLen how many bits the field consumes
|
||||
* @param isLE (default: false) if encoding / decoding should be in little-endian
|
||||
* @param redef optional faster redefinitions of sqrt and other methods
|
||||
*/
|
||||
export function Field(ORDER, bitLenOrOpts, // TODO: use opts only in v2?
|
||||
isLE = false, opts = {}) {
|
||||
if (ORDER <= _0n)
|
||||
throw new Error('invalid field: expected ORDER > 0, got ' + ORDER);
|
||||
let _nbitLength = undefined;
|
||||
let _sqrt = undefined;
|
||||
let modFromBytes = false;
|
||||
let allowedLengths = undefined;
|
||||
if (typeof bitLenOrOpts === 'object' && bitLenOrOpts != null) {
|
||||
if (opts.sqrt || isLE)
|
||||
throw new Error('cannot specify opts in two arguments');
|
||||
const _opts = bitLenOrOpts;
|
||||
if (_opts.BITS)
|
||||
_nbitLength = _opts.BITS;
|
||||
if (_opts.sqrt)
|
||||
_sqrt = _opts.sqrt;
|
||||
if (typeof _opts.isLE === 'boolean')
|
||||
isLE = _opts.isLE;
|
||||
if (typeof _opts.modFromBytes === 'boolean')
|
||||
modFromBytes = _opts.modFromBytes;
|
||||
allowedLengths = _opts.allowedLengths;
|
||||
}
|
||||
else {
|
||||
if (typeof bitLenOrOpts === 'number')
|
||||
_nbitLength = bitLenOrOpts;
|
||||
if (opts.sqrt)
|
||||
_sqrt = opts.sqrt;
|
||||
}
|
||||
const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, _nbitLength);
|
||||
if (BYTES > 2048)
|
||||
throw new Error('invalid field: expected ORDER of <= 2048 bytes');
|
||||
let sqrtP; // cached sqrtP
|
||||
const f = Object.freeze({
|
||||
ORDER,
|
||||
isLE,
|
||||
BITS,
|
||||
BYTES,
|
||||
MASK: bitMask(BITS),
|
||||
ZERO: _0n,
|
||||
ONE: _1n,
|
||||
allowedLengths: allowedLengths,
|
||||
create: (num) => mod(num, ORDER),
|
||||
isValid: (num) => {
|
||||
if (typeof num !== 'bigint')
|
||||
throw new Error('invalid field element: expected bigint, got ' + typeof num);
|
||||
return _0n <= num && num < ORDER; // 0 is valid element, but it's not invertible
|
||||
},
|
||||
is0: (num) => num === _0n,
|
||||
// is valid and invertible
|
||||
isValidNot0: (num) => !f.is0(num) && f.isValid(num),
|
||||
isOdd: (num) => (num & _1n) === _1n,
|
||||
neg: (num) => mod(-num, ORDER),
|
||||
eql: (lhs, rhs) => lhs === rhs,
|
||||
sqr: (num) => mod(num * num, ORDER),
|
||||
add: (lhs, rhs) => mod(lhs + rhs, ORDER),
|
||||
sub: (lhs, rhs) => mod(lhs - rhs, ORDER),
|
||||
mul: (lhs, rhs) => mod(lhs * rhs, ORDER),
|
||||
pow: (num, power) => FpPow(f, num, power),
|
||||
div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER),
|
||||
// Same as above, but doesn't normalize
|
||||
sqrN: (num) => num * num,
|
||||
addN: (lhs, rhs) => lhs + rhs,
|
||||
subN: (lhs, rhs) => lhs - rhs,
|
||||
mulN: (lhs, rhs) => lhs * rhs,
|
||||
inv: (num) => invert(num, ORDER),
|
||||
sqrt: _sqrt ||
|
||||
((n) => {
|
||||
if (!sqrtP)
|
||||
sqrtP = FpSqrt(ORDER);
|
||||
return sqrtP(f, n);
|
||||
}),
|
||||
toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)),
|
||||
fromBytes: (bytes, skipValidation = true) => {
|
||||
if (allowedLengths) {
|
||||
if (!allowedLengths.includes(bytes.length) || bytes.length > BYTES) {
|
||||
throw new Error('Field.fromBytes: expected ' + allowedLengths + ' bytes, got ' + bytes.length);
|
||||
}
|
||||
const padded = new Uint8Array(BYTES);
|
||||
// isLE add 0 to right, !isLE to the left.
|
||||
padded.set(bytes, isLE ? 0 : padded.length - bytes.length);
|
||||
bytes = padded;
|
||||
}
|
||||
if (bytes.length !== BYTES)
|
||||
throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length);
|
||||
let scalar = isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes);
|
||||
if (modFromBytes)
|
||||
scalar = mod(scalar, ORDER);
|
||||
if (!skipValidation)
|
||||
if (!f.isValid(scalar))
|
||||
throw new Error('invalid field element: outside of range 0..ORDER');
|
||||
// NOTE: we don't validate scalar here, please use isValid. This done such way because some
|
||||
// protocol may allow non-reduced scalar that reduced later or changed some other way.
|
||||
return scalar;
|
||||
},
|
||||
// TODO: we don't need it here, move out to separate fn
|
||||
invertBatch: (lst) => FpInvertBatch(f, lst),
|
||||
// We can't move this out because Fp6, Fp12 implement it
|
||||
// and it's unclear what to return in there.
|
||||
cmov: (a, b, c) => (c ? b : a),
|
||||
});
|
||||
return Object.freeze(f);
|
||||
}
|
||||
// Generic random scalar, we can do same for other fields if via Fp2.mul(Fp2.ONE, Fp2.random)?
|
||||
// This allows unsafe methods like ignore bias or zero. These unsafe, but often used in different protocols (if deterministic RNG).
|
||||
// which mean we cannot force this via opts.
|
||||
// Not sure what to do with randomBytes, we can accept it inside opts if wanted.
|
||||
// Probably need to export getMinHashLength somewhere?
|
||||
// random(bytes?: Uint8Array, unsafeAllowZero = false, unsafeAllowBias = false) {
|
||||
// const LEN = !unsafeAllowBias ? getMinHashLength(ORDER) : BYTES;
|
||||
// if (bytes === undefined) bytes = randomBytes(LEN); // _opts.randomBytes?
|
||||
// const num = isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes);
|
||||
// // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0
|
||||
// const reduced = unsafeAllowZero ? mod(num, ORDER) : mod(num, ORDER - _1n) + _1n;
|
||||
// return reduced;
|
||||
// },
|
||||
export function FpSqrtOdd(Fp, elm) {
|
||||
if (!Fp.isOdd)
|
||||
throw new Error("Field doesn't have isOdd");
|
||||
const root = Fp.sqrt(elm);
|
||||
return Fp.isOdd(root) ? root : Fp.neg(root);
|
||||
}
|
||||
export function FpSqrtEven(Fp, elm) {
|
||||
if (!Fp.isOdd)
|
||||
throw new Error("Field doesn't have isOdd");
|
||||
const root = Fp.sqrt(elm);
|
||||
return Fp.isOdd(root) ? Fp.neg(root) : root;
|
||||
}
|
||||
/**
|
||||
* "Constant-time" private key generation utility.
|
||||
* Same as mapKeyToField, but accepts less bytes (40 instead of 48 for 32-byte field).
|
||||
* Which makes it slightly more biased, less secure.
|
||||
* @deprecated use `mapKeyToField` instead
|
||||
*/
|
||||
export function hashToPrivateScalar(hash, groupOrder, isLE = false) {
|
||||
hash = ensureBytes('privateHash', hash);
|
||||
const hashLen = hash.length;
|
||||
const minLen = nLength(groupOrder).nByteLength + 8;
|
||||
if (minLen < 24 || hashLen < minLen || hashLen > 1024)
|
||||
throw new Error('hashToPrivateScalar: expected ' + minLen + '-1024 bytes of input, got ' + hashLen);
|
||||
const num = isLE ? bytesToNumberLE(hash) : bytesToNumberBE(hash);
|
||||
return mod(num, groupOrder - _1n) + _1n;
|
||||
}
|
||||
/**
|
||||
* Returns total number of bytes consumed by the field element.
|
||||
* For example, 32 bytes for usual 256-bit weierstrass curve.
|
||||
* @param fieldOrder number of field elements, usually CURVE.n
|
||||
* @returns byte length of field
|
||||
*/
|
||||
export function getFieldBytesLength(fieldOrder) {
|
||||
if (typeof fieldOrder !== 'bigint')
|
||||
throw new Error('field order must be bigint');
|
||||
const bitLength = fieldOrder.toString(2).length;
|
||||
return Math.ceil(bitLength / 8);
|
||||
}
|
||||
/**
|
||||
* Returns minimal amount of bytes that can be safely reduced
|
||||
* by field order.
|
||||
* Should be 2^-128 for 128-bit curve such as P256.
|
||||
* @param fieldOrder number of field elements, usually CURVE.n
|
||||
* @returns byte length of target hash
|
||||
*/
|
||||
export function getMinHashLength(fieldOrder) {
|
||||
const length = getFieldBytesLength(fieldOrder);
|
||||
return length + Math.ceil(length / 2);
|
||||
}
|
||||
/**
|
||||
* "Constant-time" private key generation utility.
|
||||
* Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF
|
||||
* and convert them into private scalar, with the modulo bias being negligible.
|
||||
* Needs at least 48 bytes of input for 32-byte private key.
|
||||
* https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
|
||||
* FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final
|
||||
* RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5
|
||||
* @param hash hash output from SHA3 or a similar function
|
||||
* @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n)
|
||||
* @param isLE interpret hash bytes as LE num
|
||||
* @returns valid private scalar
|
||||
*/
|
||||
export function mapHashToField(key, fieldOrder, isLE = false) {
|
||||
const len = key.length;
|
||||
const fieldLen = getFieldBytesLength(fieldOrder);
|
||||
const minLen = getMinHashLength(fieldOrder);
|
||||
// No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings.
|
||||
if (len < 16 || len < minLen || len > 1024)
|
||||
throw new Error('expected ' + minLen + '-1024 bytes of input, got ' + len);
|
||||
const num = isLE ? bytesToNumberLE(key) : bytesToNumberBE(key);
|
||||
// `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0
|
||||
const reduced = mod(num, fieldOrder - _1n) + _1n;
|
||||
return isLE ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen);
|
||||
}
|
||||
//# sourceMappingURL=modular.js.map
|
||||
1
node_modules/@noble/curves/esm/abstract/modular.js.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/modular.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
30
node_modules/@noble/curves/esm/abstract/montgomery.d.ts
generated
vendored
Normal file
30
node_modules/@noble/curves/esm/abstract/montgomery.d.ts
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
import type { CurveLengths } from './curve.ts';
|
||||
type Hex = string | Uint8Array;
|
||||
export type CurveType = {
|
||||
P: bigint;
|
||||
type: 'x25519' | 'x448';
|
||||
adjustScalarBytes: (bytes: Uint8Array) => Uint8Array;
|
||||
powPminus2: (x: bigint) => bigint;
|
||||
randomBytes?: (bytesLength?: number) => Uint8Array;
|
||||
};
|
||||
export type MontgomeryECDH = {
|
||||
scalarMult: (scalar: Hex, u: Hex) => Uint8Array;
|
||||
scalarMultBase: (scalar: Hex) => Uint8Array;
|
||||
getSharedSecret: (secretKeyA: Hex, publicKeyB: Hex) => Uint8Array;
|
||||
getPublicKey: (secretKey: Hex) => Uint8Array;
|
||||
utils: {
|
||||
randomSecretKey: () => Uint8Array;
|
||||
/** @deprecated use `randomSecretKey` */
|
||||
randomPrivateKey: () => Uint8Array;
|
||||
};
|
||||
GuBytes: Uint8Array;
|
||||
lengths: CurveLengths;
|
||||
keygen: (seed?: Uint8Array) => {
|
||||
secretKey: Uint8Array;
|
||||
publicKey: Uint8Array;
|
||||
};
|
||||
};
|
||||
export type CurveFn = MontgomeryECDH;
|
||||
export declare function montgomery(curveDef: CurveType): MontgomeryECDH;
|
||||
export {};
|
||||
//# sourceMappingURL=montgomery.d.ts.map
|
||||
1
node_modules/@noble/curves/esm/abstract/montgomery.d.ts.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/montgomery.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"montgomery.d.ts","sourceRoot":"","sources":["../../src/abstract/montgomery.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAM/C,KAAK,GAAG,GAAG,MAAM,GAAG,UAAU,CAAC;AAE/B,MAAM,MAAM,SAAS,GAAG;IACtB,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB,iBAAiB,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,UAAU,CAAC;IACrD,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAClC,WAAW,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE,MAAM,KAAK,UAAU,CAAC;CACpD,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,KAAK,UAAU,CAAC;IAChD,cAAc,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,UAAU,CAAC;IAC5C,eAAe,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,KAAK,UAAU,CAAC;IAClE,YAAY,EAAE,CAAC,SAAS,EAAE,GAAG,KAAK,UAAU,CAAC;IAC7C,KAAK,EAAE;QACL,eAAe,EAAE,MAAM,UAAU,CAAC;QAClC,wCAAwC;QACxC,gBAAgB,EAAE,MAAM,UAAU,CAAC;KACpC,CAAC;IACF,OAAO,EAAE,UAAU,CAAC;IACpB,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,UAAU,KAAK;QAAE,SAAS,EAAE,UAAU,CAAC;QAAC,SAAS,EAAE,UAAU,CAAA;KAAE,CAAC;CACjF,CAAC;AACF,MAAM,MAAM,OAAO,GAAG,cAAc,CAAC;AAUrC,wBAAgB,UAAU,CAAC,QAAQ,EAAE,SAAS,GAAG,cAAc,CAyI9D"}
|
||||
157
node_modules/@noble/curves/esm/abstract/montgomery.js
generated
vendored
Normal file
157
node_modules/@noble/curves/esm/abstract/montgomery.js
generated
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* Montgomery curve methods. It's not really whole montgomery curve,
|
||||
* just bunch of very specific methods for X25519 / X448 from
|
||||
* [RFC 7748](https://www.rfc-editor.org/rfc/rfc7748)
|
||||
* @module
|
||||
*/
|
||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||
import { _validateObject, abytes, aInRange, bytesToNumberLE, ensureBytes, numberToBytesLE, randomBytes, } from "../utils.js";
|
||||
import { mod } from "./modular.js";
|
||||
const _0n = BigInt(0);
|
||||
const _1n = BigInt(1);
|
||||
const _2n = BigInt(2);
|
||||
function validateOpts(curve) {
|
||||
_validateObject(curve, {
|
||||
adjustScalarBytes: 'function',
|
||||
powPminus2: 'function',
|
||||
});
|
||||
return Object.freeze({ ...curve });
|
||||
}
|
||||
export function montgomery(curveDef) {
|
||||
const CURVE = validateOpts(curveDef);
|
||||
const { P, type, adjustScalarBytes, powPminus2, randomBytes: rand } = CURVE;
|
||||
const is25519 = type === 'x25519';
|
||||
if (!is25519 && type !== 'x448')
|
||||
throw new Error('invalid type');
|
||||
const randomBytes_ = rand || randomBytes;
|
||||
const montgomeryBits = is25519 ? 255 : 448;
|
||||
const fieldLen = is25519 ? 32 : 56;
|
||||
const Gu = is25519 ? BigInt(9) : BigInt(5);
|
||||
// RFC 7748 #5:
|
||||
// The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519 and
|
||||
// (156326 - 2) / 4 = 39081 for curve448/X448
|
||||
// const a = is25519 ? 156326n : 486662n;
|
||||
const a24 = is25519 ? BigInt(121665) : BigInt(39081);
|
||||
// RFC: x25519 "the resulting integer is of the form 2^254 plus
|
||||
// eight times a value between 0 and 2^251 - 1 (inclusive)"
|
||||
// x448: "2^447 plus four times a value between 0 and 2^445 - 1 (inclusive)"
|
||||
const minScalar = is25519 ? _2n ** BigInt(254) : _2n ** BigInt(447);
|
||||
const maxAdded = is25519
|
||||
? BigInt(8) * _2n ** BigInt(251) - _1n
|
||||
: BigInt(4) * _2n ** BigInt(445) - _1n;
|
||||
const maxScalar = minScalar + maxAdded + _1n; // (inclusive)
|
||||
const modP = (n) => mod(n, P);
|
||||
const GuBytes = encodeU(Gu);
|
||||
function encodeU(u) {
|
||||
return numberToBytesLE(modP(u), fieldLen);
|
||||
}
|
||||
function decodeU(u) {
|
||||
const _u = ensureBytes('u coordinate', u, fieldLen);
|
||||
// RFC: When receiving such an array, implementations of X25519
|
||||
// (but not X448) MUST mask the most significant bit in the final byte.
|
||||
if (is25519)
|
||||
_u[31] &= 127; // 0b0111_1111
|
||||
// RFC: Implementations MUST accept non-canonical values and process them as
|
||||
// if they had been reduced modulo the field prime. The non-canonical
|
||||
// values are 2^255 - 19 through 2^255 - 1 for X25519 and 2^448 - 2^224
|
||||
// - 1 through 2^448 - 1 for X448.
|
||||
return modP(bytesToNumberLE(_u));
|
||||
}
|
||||
function decodeScalar(scalar) {
|
||||
return bytesToNumberLE(adjustScalarBytes(ensureBytes('scalar', scalar, fieldLen)));
|
||||
}
|
||||
function scalarMult(scalar, u) {
|
||||
const pu = montgomeryLadder(decodeU(u), decodeScalar(scalar));
|
||||
// Some public keys are useless, of low-order. Curve author doesn't think
|
||||
// it needs to be validated, but we do it nonetheless.
|
||||
// https://cr.yp.to/ecdh.html#validate
|
||||
if (pu === _0n)
|
||||
throw new Error('invalid private or public key received');
|
||||
return encodeU(pu);
|
||||
}
|
||||
// Computes public key from private. By doing scalar multiplication of base point.
|
||||
function scalarMultBase(scalar) {
|
||||
return scalarMult(scalar, GuBytes);
|
||||
}
|
||||
// cswap from RFC7748 "example code"
|
||||
function cswap(swap, x_2, x_3) {
|
||||
// dummy = mask(swap) AND (x_2 XOR x_3)
|
||||
// Where mask(swap) is the all-1 or all-0 word of the same length as x_2
|
||||
// and x_3, computed, e.g., as mask(swap) = 0 - swap.
|
||||
const dummy = modP(swap * (x_2 - x_3));
|
||||
x_2 = modP(x_2 - dummy); // x_2 = x_2 XOR dummy
|
||||
x_3 = modP(x_3 + dummy); // x_3 = x_3 XOR dummy
|
||||
return { x_2, x_3 };
|
||||
}
|
||||
/**
|
||||
* Montgomery x-only multiplication ladder.
|
||||
* @param pointU u coordinate (x) on Montgomery Curve 25519
|
||||
* @param scalar by which the point would be multiplied
|
||||
* @returns new Point on Montgomery curve
|
||||
*/
|
||||
function montgomeryLadder(u, scalar) {
|
||||
aInRange('u', u, _0n, P);
|
||||
aInRange('scalar', scalar, minScalar, maxScalar);
|
||||
const k = scalar;
|
||||
const x_1 = u;
|
||||
let x_2 = _1n;
|
||||
let z_2 = _0n;
|
||||
let x_3 = u;
|
||||
let z_3 = _1n;
|
||||
let swap = _0n;
|
||||
for (let t = BigInt(montgomeryBits - 1); t >= _0n; t--) {
|
||||
const k_t = (k >> t) & _1n;
|
||||
swap ^= k_t;
|
||||
({ x_2, x_3 } = cswap(swap, x_2, x_3));
|
||||
({ x_2: z_2, x_3: z_3 } = cswap(swap, z_2, z_3));
|
||||
swap = k_t;
|
||||
const A = x_2 + z_2;
|
||||
const AA = modP(A * A);
|
||||
const B = x_2 - z_2;
|
||||
const BB = modP(B * B);
|
||||
const E = AA - BB;
|
||||
const C = x_3 + z_3;
|
||||
const D = x_3 - z_3;
|
||||
const DA = modP(D * A);
|
||||
const CB = modP(C * B);
|
||||
const dacb = DA + CB;
|
||||
const da_cb = DA - CB;
|
||||
x_3 = modP(dacb * dacb);
|
||||
z_3 = modP(x_1 * modP(da_cb * da_cb));
|
||||
x_2 = modP(AA * BB);
|
||||
z_2 = modP(E * (AA + modP(a24 * E)));
|
||||
}
|
||||
({ x_2, x_3 } = cswap(swap, x_2, x_3));
|
||||
({ x_2: z_2, x_3: z_3 } = cswap(swap, z_2, z_3));
|
||||
const z2 = powPminus2(z_2); // `Fp.pow(x, P - _2n)` is much slower equivalent
|
||||
return modP(x_2 * z2); // Return x_2 * (z_2^(p - 2))
|
||||
}
|
||||
const lengths = {
|
||||
secretKey: fieldLen,
|
||||
publicKey: fieldLen,
|
||||
seed: fieldLen,
|
||||
};
|
||||
const randomSecretKey = (seed = randomBytes_(fieldLen)) => {
|
||||
abytes(seed, lengths.seed);
|
||||
return seed;
|
||||
};
|
||||
function keygen(seed) {
|
||||
const secretKey = randomSecretKey(seed);
|
||||
return { secretKey, publicKey: scalarMultBase(secretKey) };
|
||||
}
|
||||
const utils = {
|
||||
randomSecretKey,
|
||||
randomPrivateKey: randomSecretKey,
|
||||
};
|
||||
return {
|
||||
keygen,
|
||||
getSharedSecret: (secretKey, publicKey) => scalarMult(secretKey, publicKey),
|
||||
getPublicKey: (secretKey) => scalarMultBase(secretKey),
|
||||
scalarMult,
|
||||
scalarMultBase,
|
||||
utils,
|
||||
GuBytes: GuBytes.slice(),
|
||||
lengths,
|
||||
};
|
||||
}
|
||||
//# sourceMappingURL=montgomery.js.map
|
||||
1
node_modules/@noble/curves/esm/abstract/montgomery.js.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/montgomery.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
68
node_modules/@noble/curves/esm/abstract/poseidon.d.ts
generated
vendored
Normal file
68
node_modules/@noble/curves/esm/abstract/poseidon.d.ts
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
import { type IField } from './modular.ts';
|
||||
export type PoseidonBasicOpts = {
|
||||
Fp: IField<bigint>;
|
||||
t: number;
|
||||
roundsFull: number;
|
||||
roundsPartial: number;
|
||||
isSboxInverse?: boolean;
|
||||
};
|
||||
export type PoseidonGrainOpts = PoseidonBasicOpts & {
|
||||
sboxPower?: number;
|
||||
};
|
||||
type PoseidonConstants = {
|
||||
mds: bigint[][];
|
||||
roundConstants: bigint[][];
|
||||
};
|
||||
export declare function grainGenConstants(opts: PoseidonGrainOpts, skipMDS?: number): PoseidonConstants;
|
||||
export type PoseidonOpts = PoseidonBasicOpts & PoseidonConstants & {
|
||||
sboxPower?: number;
|
||||
reversePartialPowIdx?: boolean;
|
||||
};
|
||||
export declare function validateOpts(opts: PoseidonOpts): Readonly<{
|
||||
rounds: number;
|
||||
sboxFn: (n: bigint) => bigint;
|
||||
roundConstants: bigint[][];
|
||||
mds: bigint[][];
|
||||
Fp: IField<bigint>;
|
||||
t: number;
|
||||
roundsFull: number;
|
||||
roundsPartial: number;
|
||||
sboxPower?: number;
|
||||
reversePartialPowIdx?: boolean;
|
||||
}>;
|
||||
export declare function splitConstants(rc: bigint[], t: number): bigint[][];
|
||||
export type PoseidonFn = {
|
||||
(values: bigint[]): bigint[];
|
||||
roundConstants: bigint[][];
|
||||
};
|
||||
/** Poseidon NTT-friendly hash. */
|
||||
export declare function poseidon(opts: PoseidonOpts): PoseidonFn;
|
||||
export declare class PoseidonSponge {
|
||||
private Fp;
|
||||
readonly rate: number;
|
||||
readonly capacity: number;
|
||||
readonly hash: PoseidonFn;
|
||||
private state;
|
||||
private pos;
|
||||
private isAbsorbing;
|
||||
constructor(Fp: IField<bigint>, rate: number, capacity: number, hash: PoseidonFn);
|
||||
private process;
|
||||
absorb(input: bigint[]): void;
|
||||
squeeze(count: number): bigint[];
|
||||
clean(): void;
|
||||
clone(): PoseidonSponge;
|
||||
}
|
||||
export type PoseidonSpongeOpts = Omit<PoseidonOpts, 't'> & {
|
||||
rate: number;
|
||||
capacity: number;
|
||||
};
|
||||
/**
|
||||
* The method is not defined in spec, but nevertheless used often.
|
||||
* Check carefully for compatibility: there are many edge cases, like absorbing an empty array.
|
||||
* We cross-test against:
|
||||
* - https://github.com/ProvableHQ/snarkVM/tree/staging/algorithms
|
||||
* - https://github.com/arkworks-rs/crypto-primitives/tree/main
|
||||
*/
|
||||
export declare function poseidonSponge(opts: PoseidonSpongeOpts): () => PoseidonSponge;
|
||||
export {};
|
||||
//# sourceMappingURL=poseidon.d.ts.map
|
||||
1
node_modules/@noble/curves/esm/abstract/poseidon.d.ts.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/poseidon.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"poseidon.d.ts","sourceRoot":"","sources":["../../src/abstract/poseidon.ts"],"names":[],"mappings":"AAUA,OAAO,EAAwB,KAAK,MAAM,EAAiB,MAAM,cAAc,CAAC;AAyBhF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AA0DF,MAAM,MAAM,iBAAiB,GAAG,iBAAiB,GAAG;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,KAAK,iBAAiB,GAAG;IAAE,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC;IAAC,cAAc,EAAE,MAAM,EAAE,EAAE,CAAA;CAAE,CAAC;AAIzE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,EAAE,OAAO,GAAE,MAAU,GAAG,iBAAiB,CAuBjG;AAED,MAAM,MAAM,YAAY,GAAG,iBAAiB,GAC1C,iBAAiB,GAAG;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,CAAC;AAEJ,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,QAAQ,CAAC;IACzD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC9B,cAAc,EAAE,MAAM,EAAE,EAAE,CAAC;IAC3B,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,CAAC,CAwCD;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAalE;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;IAE7B,cAAc,EAAE,MAAM,EAAE,EAAE,CAAC;CAC5B,CAAC;AACF,kCAAkC;AAClC,wBAAgB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,UAAU,CAmCvD;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,EAAE,CAAiB;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,WAAW,CAAQ;gBAEf,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU;IAQhF,OAAO,CAAC,OAAO;IAGf,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAgB7B,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAahC,KAAK,IAAI,IAAI;IAKb,KAAK,IAAI,cAAc;CAMxB;AAED,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC,GAAG;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,cAAc,CAW7E"}
|
||||
296
node_modules/@noble/curves/esm/abstract/poseidon.js
generated
vendored
Normal file
296
node_modules/@noble/curves/esm/abstract/poseidon.js
generated
vendored
Normal file
@@ -0,0 +1,296 @@
|
||||
/**
|
||||
* Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash.
|
||||
*
|
||||
* There are many poseidon variants with different constants.
|
||||
* We don't provide them: you should construct them manually.
|
||||
* Check out [micro-starknet](https://github.com/paulmillr/micro-starknet) package for a proper example.
|
||||
* @module
|
||||
*/
|
||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||
import { _validateObject, bitGet } from "../utils.js";
|
||||
import { FpInvertBatch, FpPow, validateField } from "./modular.js";
|
||||
// Grain LFSR (Linear-Feedback Shift Register): https://eprint.iacr.org/2009/109.pdf
|
||||
function grainLFSR(state) {
|
||||
let pos = 0;
|
||||
if (state.length !== 80)
|
||||
throw new Error('grainLFRS: wrong state length, should be 80 bits');
|
||||
const getBit = () => {
|
||||
const r = (offset) => state[(pos + offset) % 80];
|
||||
const bit = r(62) ^ r(51) ^ r(38) ^ r(23) ^ r(13) ^ r(0);
|
||||
state[pos] = bit;
|
||||
pos = ++pos % 80;
|
||||
return !!bit;
|
||||
};
|
||||
for (let i = 0; i < 160; i++)
|
||||
getBit();
|
||||
return () => {
|
||||
// https://en.wikipedia.org/wiki/Shrinking_generator
|
||||
while (true) {
|
||||
const b1 = getBit();
|
||||
const b2 = getBit();
|
||||
if (!b1)
|
||||
continue;
|
||||
return b2;
|
||||
}
|
||||
};
|
||||
}
|
||||
function assertValidPosOpts(opts) {
|
||||
const { Fp, roundsFull } = opts;
|
||||
validateField(Fp);
|
||||
_validateObject(opts, {
|
||||
t: 'number',
|
||||
roundsFull: 'number',
|
||||
roundsPartial: 'number',
|
||||
}, {
|
||||
isSboxInverse: 'boolean',
|
||||
});
|
||||
for (const i of ['t', 'roundsFull', 'roundsPartial']) {
|
||||
if (!Number.isSafeInteger(opts[i]) || opts[i] < 1)
|
||||
throw new Error('invalid number ' + i);
|
||||
}
|
||||
if (roundsFull & 1)
|
||||
throw new Error('roundsFull is not even' + roundsFull);
|
||||
}
|
||||
function poseidonGrain(opts) {
|
||||
assertValidPosOpts(opts);
|
||||
const { Fp } = opts;
|
||||
const state = Array(80).fill(1);
|
||||
let pos = 0;
|
||||
const writeBits = (value, bitCount) => {
|
||||
for (let i = bitCount - 1; i >= 0; i--)
|
||||
state[pos++] = Number(bitGet(value, i));
|
||||
};
|
||||
const _0n = BigInt(0);
|
||||
const _1n = BigInt(1);
|
||||
writeBits(_1n, 2); // prime field
|
||||
writeBits(opts.isSboxInverse ? _1n : _0n, 4); // b2..b5
|
||||
writeBits(BigInt(Fp.BITS), 12); // b6..b17
|
||||
writeBits(BigInt(opts.t), 12); // b18..b29
|
||||
writeBits(BigInt(opts.roundsFull), 10); // b30..b39
|
||||
writeBits(BigInt(opts.roundsPartial), 10); // b40..b49
|
||||
const getBit = grainLFSR(state);
|
||||
return (count, reject) => {
|
||||
const res = [];
|
||||
for (let i = 0; i < count; i++) {
|
||||
while (true) {
|
||||
let num = _0n;
|
||||
for (let i = 0; i < Fp.BITS; i++) {
|
||||
num <<= _1n;
|
||||
if (getBit())
|
||||
num |= _1n;
|
||||
}
|
||||
if (reject && num >= Fp.ORDER)
|
||||
continue; // rejection sampling
|
||||
res.push(Fp.create(num));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
};
|
||||
}
|
||||
// NOTE: this is not standard but used often for constant generation for poseidon
|
||||
// (grain LFRS-like structure)
|
||||
export function grainGenConstants(opts, skipMDS = 0) {
|
||||
const { Fp, t, roundsFull, roundsPartial } = opts;
|
||||
const rounds = roundsFull + roundsPartial;
|
||||
const sample = poseidonGrain(opts);
|
||||
const roundConstants = [];
|
||||
for (let r = 0; r < rounds; r++)
|
||||
roundConstants.push(sample(t, true));
|
||||
if (skipMDS > 0)
|
||||
for (let i = 0; i < skipMDS; i++)
|
||||
sample(2 * t, false);
|
||||
const xs = sample(t, false);
|
||||
const ys = sample(t, false);
|
||||
// Construct MDS Matrix M[i][j] = 1 / (xs[i] + ys[j])
|
||||
const mds = [];
|
||||
for (let i = 0; i < t; i++) {
|
||||
const row = [];
|
||||
for (let j = 0; j < t; j++) {
|
||||
const xy = Fp.add(xs[i], ys[j]);
|
||||
if (Fp.is0(xy))
|
||||
throw new Error(`Error generating MDS matrix: xs[${i}] + ys[${j}] resulted in zero.`);
|
||||
row.push(xy);
|
||||
}
|
||||
mds.push(FpInvertBatch(Fp, row));
|
||||
}
|
||||
return { roundConstants, mds };
|
||||
}
|
||||
export function validateOpts(opts) {
|
||||
assertValidPosOpts(opts);
|
||||
const { Fp, mds, reversePartialPowIdx: rev, roundConstants: rc } = opts;
|
||||
const { roundsFull, roundsPartial, sboxPower, t } = opts;
|
||||
// MDS is TxT matrix
|
||||
if (!Array.isArray(mds) || mds.length !== t)
|
||||
throw new Error('Poseidon: invalid MDS matrix');
|
||||
const _mds = mds.map((mdsRow) => {
|
||||
if (!Array.isArray(mdsRow) || mdsRow.length !== t)
|
||||
throw new Error('invalid MDS matrix row: ' + mdsRow);
|
||||
return mdsRow.map((i) => {
|
||||
if (typeof i !== 'bigint')
|
||||
throw new Error('invalid MDS matrix bigint: ' + i);
|
||||
return Fp.create(i);
|
||||
});
|
||||
});
|
||||
if (rev !== undefined && typeof rev !== 'boolean')
|
||||
throw new Error('invalid param reversePartialPowIdx=' + rev);
|
||||
if (roundsFull & 1)
|
||||
throw new Error('roundsFull is not even' + roundsFull);
|
||||
const rounds = roundsFull + roundsPartial;
|
||||
if (!Array.isArray(rc) || rc.length !== rounds)
|
||||
throw new Error('Poseidon: invalid round constants');
|
||||
const roundConstants = rc.map((rc) => {
|
||||
if (!Array.isArray(rc) || rc.length !== t)
|
||||
throw new Error('invalid round constants');
|
||||
return rc.map((i) => {
|
||||
if (typeof i !== 'bigint' || !Fp.isValid(i))
|
||||
throw new Error('invalid round constant');
|
||||
return Fp.create(i);
|
||||
});
|
||||
});
|
||||
if (!sboxPower || ![3, 5, 7, 17].includes(sboxPower))
|
||||
throw new Error('invalid sboxPower');
|
||||
const _sboxPower = BigInt(sboxPower);
|
||||
let sboxFn = (n) => FpPow(Fp, n, _sboxPower);
|
||||
// Unwrapped sbox power for common cases (195->142μs)
|
||||
if (sboxPower === 3)
|
||||
sboxFn = (n) => Fp.mul(Fp.sqrN(n), n);
|
||||
else if (sboxPower === 5)
|
||||
sboxFn = (n) => Fp.mul(Fp.sqrN(Fp.sqrN(n)), n);
|
||||
return Object.freeze({ ...opts, rounds, sboxFn, roundConstants, mds: _mds });
|
||||
}
|
||||
export function splitConstants(rc, t) {
|
||||
if (typeof t !== 'number')
|
||||
throw new Error('poseidonSplitConstants: invalid t');
|
||||
if (!Array.isArray(rc) || rc.length % t)
|
||||
throw new Error('poseidonSplitConstants: invalid rc');
|
||||
const res = [];
|
||||
let tmp = [];
|
||||
for (let i = 0; i < rc.length; i++) {
|
||||
tmp.push(rc[i]);
|
||||
if (tmp.length === t) {
|
||||
res.push(tmp);
|
||||
tmp = [];
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
/** Poseidon NTT-friendly hash. */
|
||||
export function poseidon(opts) {
|
||||
const _opts = validateOpts(opts);
|
||||
const { Fp, mds, roundConstants, rounds: totalRounds, roundsPartial, sboxFn, t } = _opts;
|
||||
const halfRoundsFull = _opts.roundsFull / 2;
|
||||
const partialIdx = _opts.reversePartialPowIdx ? t - 1 : 0;
|
||||
const poseidonRound = (values, isFull, idx) => {
|
||||
values = values.map((i, j) => Fp.add(i, roundConstants[idx][j]));
|
||||
if (isFull)
|
||||
values = values.map((i) => sboxFn(i));
|
||||
else
|
||||
values[partialIdx] = sboxFn(values[partialIdx]);
|
||||
// Matrix multiplication
|
||||
values = mds.map((i) => i.reduce((acc, i, j) => Fp.add(acc, Fp.mulN(i, values[j])), Fp.ZERO));
|
||||
return values;
|
||||
};
|
||||
const poseidonHash = function poseidonHash(values) {
|
||||
if (!Array.isArray(values) || values.length !== t)
|
||||
throw new Error('invalid values, expected array of bigints with length ' + t);
|
||||
values = values.map((i) => {
|
||||
if (typeof i !== 'bigint')
|
||||
throw new Error('invalid bigint=' + i);
|
||||
return Fp.create(i);
|
||||
});
|
||||
let lastRound = 0;
|
||||
// Apply r_f/2 full rounds.
|
||||
for (let i = 0; i < halfRoundsFull; i++)
|
||||
values = poseidonRound(values, true, lastRound++);
|
||||
// Apply r_p partial rounds.
|
||||
for (let i = 0; i < roundsPartial; i++)
|
||||
values = poseidonRound(values, false, lastRound++);
|
||||
// Apply r_f/2 full rounds.
|
||||
for (let i = 0; i < halfRoundsFull; i++)
|
||||
values = poseidonRound(values, true, lastRound++);
|
||||
if (lastRound !== totalRounds)
|
||||
throw new Error('invalid number of rounds');
|
||||
return values;
|
||||
};
|
||||
// For verification in tests
|
||||
poseidonHash.roundConstants = roundConstants;
|
||||
return poseidonHash;
|
||||
}
|
||||
export class PoseidonSponge {
|
||||
constructor(Fp, rate, capacity, hash) {
|
||||
this.pos = 0;
|
||||
this.isAbsorbing = true;
|
||||
this.Fp = Fp;
|
||||
this.hash = hash;
|
||||
this.rate = rate;
|
||||
this.capacity = capacity;
|
||||
this.state = new Array(rate + capacity);
|
||||
this.clean();
|
||||
}
|
||||
process() {
|
||||
this.state = this.hash(this.state);
|
||||
}
|
||||
absorb(input) {
|
||||
for (const i of input)
|
||||
if (typeof i !== 'bigint' || !this.Fp.isValid(i))
|
||||
throw new Error('invalid input: ' + i);
|
||||
for (let i = 0; i < input.length;) {
|
||||
if (!this.isAbsorbing || this.pos === this.rate) {
|
||||
this.process();
|
||||
this.pos = 0;
|
||||
this.isAbsorbing = true;
|
||||
}
|
||||
const chunk = Math.min(this.rate - this.pos, input.length - i);
|
||||
for (let j = 0; j < chunk; j++) {
|
||||
const idx = this.capacity + this.pos++;
|
||||
this.state[idx] = this.Fp.add(this.state[idx], input[i++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
squeeze(count) {
|
||||
const res = [];
|
||||
while (res.length < count) {
|
||||
if (this.isAbsorbing || this.pos === this.rate) {
|
||||
this.process();
|
||||
this.pos = 0;
|
||||
this.isAbsorbing = false;
|
||||
}
|
||||
const chunk = Math.min(this.rate - this.pos, count - res.length);
|
||||
for (let i = 0; i < chunk; i++)
|
||||
res.push(this.state[this.capacity + this.pos++]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
clean() {
|
||||
this.state.fill(this.Fp.ZERO);
|
||||
this.isAbsorbing = true;
|
||||
this.pos = 0;
|
||||
}
|
||||
clone() {
|
||||
const c = new PoseidonSponge(this.Fp, this.rate, this.capacity, this.hash);
|
||||
c.pos = this.pos;
|
||||
c.state = [...this.state];
|
||||
return c;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* The method is not defined in spec, but nevertheless used often.
|
||||
* Check carefully for compatibility: there are many edge cases, like absorbing an empty array.
|
||||
* We cross-test against:
|
||||
* - https://github.com/ProvableHQ/snarkVM/tree/staging/algorithms
|
||||
* - https://github.com/arkworks-rs/crypto-primitives/tree/main
|
||||
*/
|
||||
export function poseidonSponge(opts) {
|
||||
for (const i of ['rate', 'capacity']) {
|
||||
if (typeof opts[i] !== 'number' || !Number.isSafeInteger(opts[i]))
|
||||
throw new Error('invalid number ' + i);
|
||||
}
|
||||
const { rate, capacity } = opts;
|
||||
const t = opts.rate + opts.capacity;
|
||||
// Re-use hash instance between multiple instances
|
||||
const hash = poseidon({ ...opts, t });
|
||||
const { Fp } = opts;
|
||||
return () => new PoseidonSponge(Fp, rate, capacity, hash);
|
||||
}
|
||||
//# sourceMappingURL=poseidon.js.map
|
||||
1
node_modules/@noble/curves/esm/abstract/poseidon.js.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/poseidon.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
95
node_modules/@noble/curves/esm/abstract/tower.d.ts
generated
vendored
Normal file
95
node_modules/@noble/curves/esm/abstract/tower.d.ts
generated
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
import * as mod from './modular.ts';
|
||||
import type { WeierstrassPoint, WeierstrassPointCons } from './weierstrass.ts';
|
||||
export type BigintTuple = [bigint, bigint];
|
||||
export type Fp = bigint;
|
||||
export type Fp2 = {
|
||||
c0: bigint;
|
||||
c1: bigint;
|
||||
};
|
||||
export type BigintSix = [bigint, bigint, bigint, bigint, bigint, bigint];
|
||||
export type Fp6 = {
|
||||
c0: Fp2;
|
||||
c1: Fp2;
|
||||
c2: Fp2;
|
||||
};
|
||||
export type Fp12 = {
|
||||
c0: Fp6;
|
||||
c1: Fp6;
|
||||
};
|
||||
export type BigintTwelve = [
|
||||
bigint,
|
||||
bigint,
|
||||
bigint,
|
||||
bigint,
|
||||
bigint,
|
||||
bigint,
|
||||
bigint,
|
||||
bigint,
|
||||
bigint,
|
||||
bigint,
|
||||
bigint,
|
||||
bigint
|
||||
];
|
||||
export type Fp2Bls = mod.IField<Fp2> & {
|
||||
Fp: mod.IField<Fp>;
|
||||
frobeniusMap(num: Fp2, power: number): Fp2;
|
||||
fromBigTuple(num: BigintTuple): Fp2;
|
||||
mulByB: (num: Fp2) => Fp2;
|
||||
mulByNonresidue: (num: Fp2) => Fp2;
|
||||
reim: (num: Fp2) => {
|
||||
re: Fp;
|
||||
im: Fp;
|
||||
};
|
||||
Fp4Square: (a: Fp2, b: Fp2) => {
|
||||
first: Fp2;
|
||||
second: Fp2;
|
||||
};
|
||||
NONRESIDUE: Fp2;
|
||||
};
|
||||
export type Fp6Bls = mod.IField<Fp6> & {
|
||||
Fp2: Fp2Bls;
|
||||
frobeniusMap(num: Fp6, power: number): Fp6;
|
||||
fromBigSix: (tuple: BigintSix) => Fp6;
|
||||
mul1(num: Fp6, b1: Fp2): Fp6;
|
||||
mul01(num: Fp6, b0: Fp2, b1: Fp2): Fp6;
|
||||
mulByFp2(lhs: Fp6, rhs: Fp2): Fp6;
|
||||
mulByNonresidue: (num: Fp6) => Fp6;
|
||||
};
|
||||
export type Fp12Bls = mod.IField<Fp12> & {
|
||||
Fp6: Fp6Bls;
|
||||
frobeniusMap(num: Fp12, power: number): Fp12;
|
||||
fromBigTwelve: (t: BigintTwelve) => Fp12;
|
||||
mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12;
|
||||
mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12;
|
||||
mulByFp2(lhs: Fp12, rhs: Fp2): Fp12;
|
||||
conjugate(num: Fp12): Fp12;
|
||||
finalExponentiate(num: Fp12): Fp12;
|
||||
_cyclotomicSquare(num: Fp12): Fp12;
|
||||
_cyclotomicExp(num: Fp12, n: bigint): Fp12;
|
||||
};
|
||||
export declare function psiFrobenius(Fp: mod.IField<Fp>, Fp2: Fp2Bls, base: Fp2): {
|
||||
psi: (x: Fp2, y: Fp2) => [Fp2, Fp2];
|
||||
psi2: (x: Fp2, y: Fp2) => [Fp2, Fp2];
|
||||
G2psi: (c: WeierstrassPointCons<Fp2>, P: WeierstrassPoint<Fp2>) => WeierstrassPoint<Fp2>;
|
||||
G2psi2: (c: WeierstrassPointCons<Fp2>, P: WeierstrassPoint<Fp2>) => WeierstrassPoint<Fp2>;
|
||||
PSI_X: Fp2;
|
||||
PSI_Y: Fp2;
|
||||
PSI2_X: Fp2;
|
||||
PSI2_Y: Fp2;
|
||||
};
|
||||
export type Tower12Opts = {
|
||||
ORDER: bigint;
|
||||
X_LEN: number;
|
||||
NONRESIDUE?: Fp;
|
||||
FP2_NONRESIDUE: BigintTuple;
|
||||
Fp2sqrt?: (num: Fp2) => Fp2;
|
||||
Fp2mulByB: (num: Fp2) => Fp2;
|
||||
Fp12finalExponentiate: (num: Fp12) => Fp12;
|
||||
};
|
||||
export declare function tower12(opts: Tower12Opts): {
|
||||
Fp: Readonly<mod.IField<bigint> & Required<Pick<mod.IField<bigint>, 'isOdd'>>>;
|
||||
Fp2: Fp2Bls;
|
||||
Fp6: Fp6Bls;
|
||||
Fp12: Fp12Bls;
|
||||
};
|
||||
//# sourceMappingURL=tower.d.ts.map
|
||||
1
node_modules/@noble/curves/esm/abstract/tower.d.ts.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/tower.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"tower.d.ts","sourceRoot":"","sources":["../../src/abstract/tower.ts"],"names":[],"mappings":"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"}
|
||||
714
node_modules/@noble/curves/esm/abstract/tower.js
generated
vendored
Normal file
714
node_modules/@noble/curves/esm/abstract/tower.js
generated
vendored
Normal file
@@ -0,0 +1,714 @@
|
||||
/**
|
||||
* Towered extension fields.
|
||||
* Rather than implementing a massive 12th-degree extension directly, it is more efficient
|
||||
* to build it up from smaller extensions: a tower of extensions.
|
||||
*
|
||||
* For BLS12-381, the Fp12 field is implemented as a quadratic (degree two) extension,
|
||||
* on top of a cubic (degree three) extension, on top of a quadratic extension of Fp.
|
||||
*
|
||||
* For more info: "Pairings for beginners" by Costello, section 7.3.
|
||||
* @module
|
||||
*/
|
||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||
import { bitGet, bitLen, concatBytes, notImplemented } from "../utils.js";
|
||||
import * as mod from "./modular.js";
|
||||
// Be friendly to bad ECMAScript parsers by not using bigint literals
|
||||
// prettier-ignore
|
||||
const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
|
||||
function calcFrobeniusCoefficients(Fp, nonResidue, modulus, degree, num = 1, divisor) {
|
||||
const _divisor = BigInt(divisor === undefined ? degree : divisor);
|
||||
const towerModulus = modulus ** BigInt(degree);
|
||||
const res = [];
|
||||
for (let i = 0; i < num; i++) {
|
||||
const a = BigInt(i + 1);
|
||||
const powers = [];
|
||||
for (let j = 0, qPower = _1n; j < degree; j++) {
|
||||
const power = ((a * qPower - a) / _divisor) % towerModulus;
|
||||
powers.push(Fp.pow(nonResidue, power));
|
||||
qPower *= modulus;
|
||||
}
|
||||
res.push(powers);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
// This works same at least for bls12-381, bn254 and bls12-377
|
||||
export function psiFrobenius(Fp, Fp2, base) {
|
||||
// GLV endomorphism Ψ(P)
|
||||
const PSI_X = Fp2.pow(base, (Fp.ORDER - _1n) / _3n); // u^((p-1)/3)
|
||||
const PSI_Y = Fp2.pow(base, (Fp.ORDER - _1n) / _2n); // u^((p-1)/2)
|
||||
function psi(x, y) {
|
||||
// This x10 faster than previous version in bls12-381
|
||||
const x2 = Fp2.mul(Fp2.frobeniusMap(x, 1), PSI_X);
|
||||
const y2 = Fp2.mul(Fp2.frobeniusMap(y, 1), PSI_Y);
|
||||
return [x2, y2];
|
||||
}
|
||||
// Ψ²(P) endomorphism (psi2(x) = psi(psi(x)))
|
||||
const PSI2_X = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _3n); // u^((p^2 - 1)/3)
|
||||
// This equals -1, which causes y to be Fp2.neg(y).
|
||||
// But not sure if there are case when this is not true?
|
||||
const PSI2_Y = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _2n); // u^((p^2 - 1)/3)
|
||||
if (!Fp2.eql(PSI2_Y, Fp2.neg(Fp2.ONE)))
|
||||
throw new Error('psiFrobenius: PSI2_Y!==-1');
|
||||
function psi2(x, y) {
|
||||
return [Fp2.mul(x, PSI2_X), Fp2.neg(y)];
|
||||
}
|
||||
// Map points
|
||||
const mapAffine = (fn) => (c, P) => {
|
||||
const affine = P.toAffine();
|
||||
const p = fn(affine.x, affine.y);
|
||||
return c.fromAffine({ x: p[0], y: p[1] });
|
||||
};
|
||||
const G2psi = mapAffine(psi);
|
||||
const G2psi2 = mapAffine(psi2);
|
||||
return { psi, psi2, G2psi, G2psi2, PSI_X, PSI_Y, PSI2_X, PSI2_Y };
|
||||
}
|
||||
const Fp2fromBigTuple = (Fp, tuple) => {
|
||||
if (tuple.length !== 2)
|
||||
throw new Error('invalid tuple');
|
||||
const fps = tuple.map((n) => Fp.create(n));
|
||||
return { c0: fps[0], c1: fps[1] };
|
||||
};
|
||||
class _Field2 {
|
||||
constructor(Fp, opts = {}) {
|
||||
this.MASK = _1n;
|
||||
const ORDER = Fp.ORDER;
|
||||
const FP2_ORDER = ORDER * ORDER;
|
||||
this.Fp = Fp;
|
||||
this.ORDER = FP2_ORDER;
|
||||
this.BITS = bitLen(FP2_ORDER);
|
||||
this.BYTES = Math.ceil(bitLen(FP2_ORDER) / 8);
|
||||
this.isLE = Fp.isLE;
|
||||
this.ZERO = { c0: Fp.ZERO, c1: Fp.ZERO };
|
||||
this.ONE = { c0: Fp.ONE, c1: Fp.ZERO };
|
||||
this.Fp_NONRESIDUE = Fp.create(opts.NONRESIDUE || BigInt(-1));
|
||||
this.Fp_div2 = Fp.div(Fp.ONE, _2n); // 1/2
|
||||
this.NONRESIDUE = Fp2fromBigTuple(Fp, opts.FP2_NONRESIDUE);
|
||||
// const Fp2Nonresidue = Fp2fromBigTuple(opts.FP2_NONRESIDUE);
|
||||
this.FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients(Fp, this.Fp_NONRESIDUE, Fp.ORDER, 2)[0];
|
||||
this.mulByB = opts.Fp2mulByB;
|
||||
Object.seal(this);
|
||||
}
|
||||
fromBigTuple(tuple) {
|
||||
return Fp2fromBigTuple(this.Fp, tuple);
|
||||
}
|
||||
create(num) {
|
||||
return num;
|
||||
}
|
||||
isValid({ c0, c1 }) {
|
||||
function isValidC(num, ORDER) {
|
||||
return typeof num === 'bigint' && _0n <= num && num < ORDER;
|
||||
}
|
||||
return isValidC(c0, this.ORDER) && isValidC(c1, this.ORDER);
|
||||
}
|
||||
is0({ c0, c1 }) {
|
||||
return this.Fp.is0(c0) && this.Fp.is0(c1);
|
||||
}
|
||||
isValidNot0(num) {
|
||||
return !this.is0(num) && this.isValid(num);
|
||||
}
|
||||
eql({ c0, c1 }, { c0: r0, c1: r1 }) {
|
||||
return this.Fp.eql(c0, r0) && this.Fp.eql(c1, r1);
|
||||
}
|
||||
neg({ c0, c1 }) {
|
||||
return { c0: this.Fp.neg(c0), c1: this.Fp.neg(c1) };
|
||||
}
|
||||
pow(num, power) {
|
||||
return mod.FpPow(this, num, power);
|
||||
}
|
||||
invertBatch(nums) {
|
||||
return mod.FpInvertBatch(this, nums);
|
||||
}
|
||||
// Normalized
|
||||
add(f1, f2) {
|
||||
const { c0, c1 } = f1;
|
||||
const { c0: r0, c1: r1 } = f2;
|
||||
return {
|
||||
c0: this.Fp.add(c0, r0),
|
||||
c1: this.Fp.add(c1, r1),
|
||||
};
|
||||
}
|
||||
sub({ c0, c1 }, { c0: r0, c1: r1 }) {
|
||||
return {
|
||||
c0: this.Fp.sub(c0, r0),
|
||||
c1: this.Fp.sub(c1, r1),
|
||||
};
|
||||
}
|
||||
mul({ c0, c1 }, rhs) {
|
||||
const { Fp } = this;
|
||||
if (typeof rhs === 'bigint')
|
||||
return { c0: Fp.mul(c0, rhs), c1: Fp.mul(c1, rhs) };
|
||||
// (a+bi)(c+di) = (ac−bd) + (ad+bc)i
|
||||
const { c0: r0, c1: r1 } = rhs;
|
||||
let t1 = Fp.mul(c0, r0); // c0 * o0
|
||||
let t2 = Fp.mul(c1, r1); // c1 * o1
|
||||
// (T1 - T2) + ((c0 + c1) * (r0 + r1) - (T1 + T2))*i
|
||||
const o0 = Fp.sub(t1, t2);
|
||||
const o1 = Fp.sub(Fp.mul(Fp.add(c0, c1), Fp.add(r0, r1)), Fp.add(t1, t2));
|
||||
return { c0: o0, c1: o1 };
|
||||
}
|
||||
sqr({ c0, c1 }) {
|
||||
const { Fp } = this;
|
||||
const a = Fp.add(c0, c1);
|
||||
const b = Fp.sub(c0, c1);
|
||||
const c = Fp.add(c0, c0);
|
||||
return { c0: Fp.mul(a, b), c1: Fp.mul(c, c1) };
|
||||
}
|
||||
// NonNormalized stuff
|
||||
addN(a, b) {
|
||||
return this.add(a, b);
|
||||
}
|
||||
subN(a, b) {
|
||||
return this.sub(a, b);
|
||||
}
|
||||
mulN(a, b) {
|
||||
return this.mul(a, b);
|
||||
}
|
||||
sqrN(a) {
|
||||
return this.sqr(a);
|
||||
}
|
||||
// Why inversion for bigint inside Fp instead of Fp2? it is even used in that context?
|
||||
div(lhs, rhs) {
|
||||
const { Fp } = this;
|
||||
// @ts-ignore
|
||||
return this.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : this.inv(rhs));
|
||||
}
|
||||
inv({ c0: a, c1: b }) {
|
||||
// We wish to find the multiplicative inverse of a nonzero
|
||||
// element a + bu in Fp2. We leverage an identity
|
||||
//
|
||||
// (a + bu)(a - bu) = a² + b²
|
||||
//
|
||||
// which holds because u² = -1. This can be rewritten as
|
||||
//
|
||||
// (a + bu)(a - bu)/(a² + b²) = 1
|
||||
//
|
||||
// because a² + b² = 0 has no nonzero solutions for (a, b).
|
||||
// This gives that (a - bu)/(a² + b²) is the inverse
|
||||
// of (a + bu). Importantly, this can be computing using
|
||||
// only a single inversion in Fp.
|
||||
const { Fp } = this;
|
||||
const factor = Fp.inv(Fp.create(a * a + b * b));
|
||||
return { c0: Fp.mul(factor, Fp.create(a)), c1: Fp.mul(factor, Fp.create(-b)) };
|
||||
}
|
||||
sqrt(num) {
|
||||
// This is generic for all quadratic extensions (Fp2)
|
||||
const { Fp } = this;
|
||||
const Fp2 = this;
|
||||
const { c0, c1 } = num;
|
||||
if (Fp.is0(c1)) {
|
||||
// if c0 is quadratic residue
|
||||
if (mod.FpLegendre(Fp, c0) === 1)
|
||||
return Fp2.create({ c0: Fp.sqrt(c0), c1: Fp.ZERO });
|
||||
else
|
||||
return Fp2.create({ c0: Fp.ZERO, c1: Fp.sqrt(Fp.div(c0, this.Fp_NONRESIDUE)) });
|
||||
}
|
||||
const a = Fp.sqrt(Fp.sub(Fp.sqr(c0), Fp.mul(Fp.sqr(c1), this.Fp_NONRESIDUE)));
|
||||
let d = Fp.mul(Fp.add(a, c0), this.Fp_div2);
|
||||
const legendre = mod.FpLegendre(Fp, d);
|
||||
// -1, Quadratic non residue
|
||||
if (legendre === -1)
|
||||
d = Fp.sub(d, a);
|
||||
const a0 = Fp.sqrt(d);
|
||||
const candidateSqrt = Fp2.create({ c0: a0, c1: Fp.div(Fp.mul(c1, this.Fp_div2), a0) });
|
||||
if (!Fp2.eql(Fp2.sqr(candidateSqrt), num))
|
||||
throw new Error('Cannot find square root');
|
||||
// Normalize root: at this point candidateSqrt ** 2 = num, but also -candidateSqrt ** 2 = num
|
||||
const x1 = candidateSqrt;
|
||||
const x2 = Fp2.neg(x1);
|
||||
const { re: re1, im: im1 } = Fp2.reim(x1);
|
||||
const { re: re2, im: im2 } = Fp2.reim(x2);
|
||||
if (im1 > im2 || (im1 === im2 && re1 > re2))
|
||||
return x1;
|
||||
return x2;
|
||||
}
|
||||
// Same as sgn0_m_eq_2 in RFC 9380
|
||||
isOdd(x) {
|
||||
const { re: x0, im: x1 } = this.reim(x);
|
||||
const sign_0 = x0 % _2n;
|
||||
const zero_0 = x0 === _0n;
|
||||
const sign_1 = x1 % _2n;
|
||||
return BigInt(sign_0 || (zero_0 && sign_1)) == _1n;
|
||||
}
|
||||
// Bytes util
|
||||
fromBytes(b) {
|
||||
const { Fp } = this;
|
||||
if (b.length !== this.BYTES)
|
||||
throw new Error('fromBytes invalid length=' + b.length);
|
||||
return { c0: Fp.fromBytes(b.subarray(0, Fp.BYTES)), c1: Fp.fromBytes(b.subarray(Fp.BYTES)) };
|
||||
}
|
||||
toBytes({ c0, c1 }) {
|
||||
return concatBytes(this.Fp.toBytes(c0), this.Fp.toBytes(c1));
|
||||
}
|
||||
cmov({ c0, c1 }, { c0: r0, c1: r1 }, c) {
|
||||
return {
|
||||
c0: this.Fp.cmov(c0, r0, c),
|
||||
c1: this.Fp.cmov(c1, r1, c),
|
||||
};
|
||||
}
|
||||
reim({ c0, c1 }) {
|
||||
return { re: c0, im: c1 };
|
||||
}
|
||||
Fp4Square(a, b) {
|
||||
const Fp2 = this;
|
||||
const a2 = Fp2.sqr(a);
|
||||
const b2 = Fp2.sqr(b);
|
||||
return {
|
||||
first: Fp2.add(Fp2.mulByNonresidue(b2), a2), // b² * Nonresidue + a²
|
||||
second: Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b²
|
||||
};
|
||||
}
|
||||
// multiply by u + 1
|
||||
mulByNonresidue({ c0, c1 }) {
|
||||
return this.mul({ c0, c1 }, this.NONRESIDUE);
|
||||
}
|
||||
frobeniusMap({ c0, c1 }, power) {
|
||||
return {
|
||||
c0,
|
||||
c1: this.Fp.mul(c1, this.FROBENIUS_COEFFICIENTS[power % 2]),
|
||||
};
|
||||
}
|
||||
}
|
||||
class _Field6 {
|
||||
constructor(Fp2) {
|
||||
this.MASK = _1n;
|
||||
this.Fp2 = Fp2;
|
||||
this.ORDER = Fp2.ORDER; // TODO: unused, but need to verify
|
||||
this.BITS = 3 * Fp2.BITS;
|
||||
this.BYTES = 3 * Fp2.BYTES;
|
||||
this.isLE = Fp2.isLE;
|
||||
this.ZERO = { c0: Fp2.ZERO, c1: Fp2.ZERO, c2: Fp2.ZERO };
|
||||
this.ONE = { c0: Fp2.ONE, c1: Fp2.ZERO, c2: Fp2.ZERO };
|
||||
const { Fp } = Fp2;
|
||||
const frob = calcFrobeniusCoefficients(Fp2, Fp2.NONRESIDUE, Fp.ORDER, 6, 2, 3);
|
||||
this.FROBENIUS_COEFFICIENTS_1 = frob[0];
|
||||
this.FROBENIUS_COEFFICIENTS_2 = frob[1];
|
||||
Object.seal(this);
|
||||
}
|
||||
add({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) {
|
||||
const { Fp2 } = this;
|
||||
return {
|
||||
c0: Fp2.add(c0, r0),
|
||||
c1: Fp2.add(c1, r1),
|
||||
c2: Fp2.add(c2, r2),
|
||||
};
|
||||
}
|
||||
sub({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) {
|
||||
const { Fp2 } = this;
|
||||
return {
|
||||
c0: Fp2.sub(c0, r0),
|
||||
c1: Fp2.sub(c1, r1),
|
||||
c2: Fp2.sub(c2, r2),
|
||||
};
|
||||
}
|
||||
mul({ c0, c1, c2 }, rhs) {
|
||||
const { Fp2 } = this;
|
||||
if (typeof rhs === 'bigint') {
|
||||
return {
|
||||
c0: Fp2.mul(c0, rhs),
|
||||
c1: Fp2.mul(c1, rhs),
|
||||
c2: Fp2.mul(c2, rhs),
|
||||
};
|
||||
}
|
||||
const { c0: r0, c1: r1, c2: r2 } = rhs;
|
||||
const t0 = Fp2.mul(c0, r0); // c0 * o0
|
||||
const t1 = Fp2.mul(c1, r1); // c1 * o1
|
||||
const t2 = Fp2.mul(c2, r2); // c2 * o2
|
||||
return {
|
||||
// t0 + (c1 + c2) * (r1 * r2) - (T1 + T2) * (u + 1)
|
||||
c0: Fp2.add(t0, Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), Fp2.add(r1, r2)), Fp2.add(t1, t2)))),
|
||||
// (c0 + c1) * (r0 + r1) - (T0 + T1) + T2 * (u + 1)
|
||||
c1: Fp2.add(Fp2.sub(Fp2.mul(Fp2.add(c0, c1), Fp2.add(r0, r1)), Fp2.add(t0, t1)), Fp2.mulByNonresidue(t2)),
|
||||
// T1 + (c0 + c2) * (r0 + r2) - T0 + T2
|
||||
c2: Fp2.sub(Fp2.add(t1, Fp2.mul(Fp2.add(c0, c2), Fp2.add(r0, r2))), Fp2.add(t0, t2)),
|
||||
};
|
||||
}
|
||||
sqr({ c0, c1, c2 }) {
|
||||
const { Fp2 } = this;
|
||||
let t0 = Fp2.sqr(c0); // c0²
|
||||
let t1 = Fp2.mul(Fp2.mul(c0, c1), _2n); // 2 * c0 * c1
|
||||
let t3 = Fp2.mul(Fp2.mul(c1, c2), _2n); // 2 * c1 * c2
|
||||
let t4 = Fp2.sqr(c2); // c2²
|
||||
return {
|
||||
c0: Fp2.add(Fp2.mulByNonresidue(t3), t0), // T3 * (u + 1) + T0
|
||||
c1: Fp2.add(Fp2.mulByNonresidue(t4), t1), // T4 * (u + 1) + T1
|
||||
// T1 + (c0 - c1 + c2)² + T3 - T0 - T4
|
||||
c2: Fp2.sub(Fp2.sub(Fp2.add(Fp2.add(t1, Fp2.sqr(Fp2.add(Fp2.sub(c0, c1), c2))), t3), t0), t4),
|
||||
};
|
||||
}
|
||||
addN(a, b) {
|
||||
return this.add(a, b);
|
||||
}
|
||||
subN(a, b) {
|
||||
return this.sub(a, b);
|
||||
}
|
||||
mulN(a, b) {
|
||||
return this.mul(a, b);
|
||||
}
|
||||
sqrN(a) {
|
||||
return this.sqr(a);
|
||||
}
|
||||
create(num) {
|
||||
return num;
|
||||
}
|
||||
isValid({ c0, c1, c2 }) {
|
||||
const { Fp2 } = this;
|
||||
return Fp2.isValid(c0) && Fp2.isValid(c1) && Fp2.isValid(c2);
|
||||
}
|
||||
is0({ c0, c1, c2 }) {
|
||||
const { Fp2 } = this;
|
||||
return Fp2.is0(c0) && Fp2.is0(c1) && Fp2.is0(c2);
|
||||
}
|
||||
isValidNot0(num) {
|
||||
return !this.is0(num) && this.isValid(num);
|
||||
}
|
||||
neg({ c0, c1, c2 }) {
|
||||
const { Fp2 } = this;
|
||||
return { c0: Fp2.neg(c0), c1: Fp2.neg(c1), c2: Fp2.neg(c2) };
|
||||
}
|
||||
eql({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) {
|
||||
const { Fp2 } = this;
|
||||
return Fp2.eql(c0, r0) && Fp2.eql(c1, r1) && Fp2.eql(c2, r2);
|
||||
}
|
||||
sqrt(_) {
|
||||
return notImplemented();
|
||||
}
|
||||
// Do we need division by bigint at all? Should be done via order:
|
||||
div(lhs, rhs) {
|
||||
const { Fp2 } = this;
|
||||
const { Fp } = Fp2;
|
||||
return this.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : this.inv(rhs));
|
||||
}
|
||||
pow(num, power) {
|
||||
return mod.FpPow(this, num, power);
|
||||
}
|
||||
invertBatch(nums) {
|
||||
return mod.FpInvertBatch(this, nums);
|
||||
}
|
||||
inv({ c0, c1, c2 }) {
|
||||
const { Fp2 } = this;
|
||||
let t0 = Fp2.sub(Fp2.sqr(c0), Fp2.mulByNonresidue(Fp2.mul(c2, c1))); // c0² - c2 * c1 * (u + 1)
|
||||
let t1 = Fp2.sub(Fp2.mulByNonresidue(Fp2.sqr(c2)), Fp2.mul(c0, c1)); // c2² * (u + 1) - c0 * c1
|
||||
let t2 = Fp2.sub(Fp2.sqr(c1), Fp2.mul(c0, c2)); // c1² - c0 * c2
|
||||
// 1/(((c2 * T1 + c1 * T2) * v) + c0 * T0)
|
||||
let t4 = Fp2.inv(Fp2.add(Fp2.mulByNonresidue(Fp2.add(Fp2.mul(c2, t1), Fp2.mul(c1, t2))), Fp2.mul(c0, t0)));
|
||||
return { c0: Fp2.mul(t4, t0), c1: Fp2.mul(t4, t1), c2: Fp2.mul(t4, t2) };
|
||||
}
|
||||
// Bytes utils
|
||||
fromBytes(b) {
|
||||
const { Fp2 } = this;
|
||||
if (b.length !== this.BYTES)
|
||||
throw new Error('fromBytes invalid length=' + b.length);
|
||||
const B2 = Fp2.BYTES;
|
||||
return {
|
||||
c0: Fp2.fromBytes(b.subarray(0, B2)),
|
||||
c1: Fp2.fromBytes(b.subarray(B2, B2 * 2)),
|
||||
c2: Fp2.fromBytes(b.subarray(2 * B2)),
|
||||
};
|
||||
}
|
||||
toBytes({ c0, c1, c2 }) {
|
||||
const { Fp2 } = this;
|
||||
return concatBytes(Fp2.toBytes(c0), Fp2.toBytes(c1), Fp2.toBytes(c2));
|
||||
}
|
||||
cmov({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }, c) {
|
||||
const { Fp2 } = this;
|
||||
return {
|
||||
c0: Fp2.cmov(c0, r0, c),
|
||||
c1: Fp2.cmov(c1, r1, c),
|
||||
c2: Fp2.cmov(c2, r2, c),
|
||||
};
|
||||
}
|
||||
fromBigSix(t) {
|
||||
const { Fp2 } = this;
|
||||
if (!Array.isArray(t) || t.length !== 6)
|
||||
throw new Error('invalid Fp6 usage');
|
||||
return {
|
||||
c0: Fp2.fromBigTuple(t.slice(0, 2)),
|
||||
c1: Fp2.fromBigTuple(t.slice(2, 4)),
|
||||
c2: Fp2.fromBigTuple(t.slice(4, 6)),
|
||||
};
|
||||
}
|
||||
frobeniusMap({ c0, c1, c2 }, power) {
|
||||
const { Fp2 } = this;
|
||||
return {
|
||||
c0: Fp2.frobeniusMap(c0, power),
|
||||
c1: Fp2.mul(Fp2.frobeniusMap(c1, power), this.FROBENIUS_COEFFICIENTS_1[power % 6]),
|
||||
c2: Fp2.mul(Fp2.frobeniusMap(c2, power), this.FROBENIUS_COEFFICIENTS_2[power % 6]),
|
||||
};
|
||||
}
|
||||
mulByFp2({ c0, c1, c2 }, rhs) {
|
||||
const { Fp2 } = this;
|
||||
return {
|
||||
c0: Fp2.mul(c0, rhs),
|
||||
c1: Fp2.mul(c1, rhs),
|
||||
c2: Fp2.mul(c2, rhs),
|
||||
};
|
||||
}
|
||||
mulByNonresidue({ c0, c1, c2 }) {
|
||||
const { Fp2 } = this;
|
||||
return { c0: Fp2.mulByNonresidue(c2), c1: c0, c2: c1 };
|
||||
}
|
||||
// Sparse multiplication
|
||||
mul1({ c0, c1, c2 }, b1) {
|
||||
const { Fp2 } = this;
|
||||
return {
|
||||
c0: Fp2.mulByNonresidue(Fp2.mul(c2, b1)),
|
||||
c1: Fp2.mul(c0, b1),
|
||||
c2: Fp2.mul(c1, b1),
|
||||
};
|
||||
}
|
||||
// Sparse multiplication
|
||||
mul01({ c0, c1, c2 }, b0, b1) {
|
||||
const { Fp2 } = this;
|
||||
let t0 = Fp2.mul(c0, b0); // c0 * b0
|
||||
let t1 = Fp2.mul(c1, b1); // c1 * b1
|
||||
return {
|
||||
// ((c1 + c2) * b1 - T1) * (u + 1) + T0
|
||||
c0: Fp2.add(Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), b1), t1)), t0),
|
||||
// (b0 + b1) * (c0 + c1) - T0 - T1
|
||||
c1: Fp2.sub(Fp2.sub(Fp2.mul(Fp2.add(b0, b1), Fp2.add(c0, c1)), t0), t1),
|
||||
// (c0 + c2) * b0 - T0 + T1
|
||||
c2: Fp2.add(Fp2.sub(Fp2.mul(Fp2.add(c0, c2), b0), t0), t1),
|
||||
};
|
||||
}
|
||||
}
|
||||
class _Field12 {
|
||||
constructor(Fp6, opts) {
|
||||
this.MASK = _1n;
|
||||
const { Fp2 } = Fp6;
|
||||
const { Fp } = Fp2;
|
||||
this.Fp6 = Fp6;
|
||||
this.ORDER = Fp2.ORDER; // TODO: verify if it's unuesd
|
||||
this.BITS = 2 * Fp6.BITS;
|
||||
this.BYTES = 2 * Fp6.BYTES;
|
||||
this.isLE = Fp6.isLE;
|
||||
this.ZERO = { c0: Fp6.ZERO, c1: Fp6.ZERO };
|
||||
this.ONE = { c0: Fp6.ONE, c1: Fp6.ZERO };
|
||||
this.FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients(Fp2, Fp2.NONRESIDUE, Fp.ORDER, 12, 1, 6)[0];
|
||||
this.X_LEN = opts.X_LEN;
|
||||
this.finalExponentiate = opts.Fp12finalExponentiate;
|
||||
}
|
||||
create(num) {
|
||||
return num;
|
||||
}
|
||||
isValid({ c0, c1 }) {
|
||||
const { Fp6 } = this;
|
||||
return Fp6.isValid(c0) && Fp6.isValid(c1);
|
||||
}
|
||||
is0({ c0, c1 }) {
|
||||
const { Fp6 } = this;
|
||||
return Fp6.is0(c0) && Fp6.is0(c1);
|
||||
}
|
||||
isValidNot0(num) {
|
||||
return !this.is0(num) && this.isValid(num);
|
||||
}
|
||||
neg({ c0, c1 }) {
|
||||
const { Fp6 } = this;
|
||||
return { c0: Fp6.neg(c0), c1: Fp6.neg(c1) };
|
||||
}
|
||||
eql({ c0, c1 }, { c0: r0, c1: r1 }) {
|
||||
const { Fp6 } = this;
|
||||
return Fp6.eql(c0, r0) && Fp6.eql(c1, r1);
|
||||
}
|
||||
sqrt(_) {
|
||||
notImplemented();
|
||||
}
|
||||
inv({ c0, c1 }) {
|
||||
const { Fp6 } = this;
|
||||
let t = Fp6.inv(Fp6.sub(Fp6.sqr(c0), Fp6.mulByNonresidue(Fp6.sqr(c1)))); // 1 / (c0² - c1² * v)
|
||||
return { c0: Fp6.mul(c0, t), c1: Fp6.neg(Fp6.mul(c1, t)) }; // ((C0 * T) * T) + (-C1 * T) * w
|
||||
}
|
||||
div(lhs, rhs) {
|
||||
const { Fp6 } = this;
|
||||
const { Fp2 } = Fp6;
|
||||
const { Fp } = Fp2;
|
||||
return this.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : this.inv(rhs));
|
||||
}
|
||||
pow(num, power) {
|
||||
return mod.FpPow(this, num, power);
|
||||
}
|
||||
invertBatch(nums) {
|
||||
return mod.FpInvertBatch(this, nums);
|
||||
}
|
||||
// Normalized
|
||||
add({ c0, c1 }, { c0: r0, c1: r1 }) {
|
||||
const { Fp6 } = this;
|
||||
return {
|
||||
c0: Fp6.add(c0, r0),
|
||||
c1: Fp6.add(c1, r1),
|
||||
};
|
||||
}
|
||||
sub({ c0, c1 }, { c0: r0, c1: r1 }) {
|
||||
const { Fp6 } = this;
|
||||
return {
|
||||
c0: Fp6.sub(c0, r0),
|
||||
c1: Fp6.sub(c1, r1),
|
||||
};
|
||||
}
|
||||
mul({ c0, c1 }, rhs) {
|
||||
const { Fp6 } = this;
|
||||
if (typeof rhs === 'bigint')
|
||||
return { c0: Fp6.mul(c0, rhs), c1: Fp6.mul(c1, rhs) };
|
||||
let { c0: r0, c1: r1 } = rhs;
|
||||
let t1 = Fp6.mul(c0, r0); // c0 * r0
|
||||
let t2 = Fp6.mul(c1, r1); // c1 * r1
|
||||
return {
|
||||
c0: Fp6.add(t1, Fp6.mulByNonresidue(t2)), // T1 + T2 * v
|
||||
// (c0 + c1) * (r0 + r1) - (T1 + T2)
|
||||
c1: Fp6.sub(Fp6.mul(Fp6.add(c0, c1), Fp6.add(r0, r1)), Fp6.add(t1, t2)),
|
||||
};
|
||||
}
|
||||
sqr({ c0, c1 }) {
|
||||
const { Fp6 } = this;
|
||||
let ab = Fp6.mul(c0, c1); // c0 * c1
|
||||
return {
|
||||
// (c1 * v + c0) * (c0 + c1) - AB - AB * v
|
||||
c0: Fp6.sub(Fp6.sub(Fp6.mul(Fp6.add(Fp6.mulByNonresidue(c1), c0), Fp6.add(c0, c1)), ab), Fp6.mulByNonresidue(ab)),
|
||||
c1: Fp6.add(ab, ab),
|
||||
}; // AB + AB
|
||||
}
|
||||
// NonNormalized stuff
|
||||
addN(a, b) {
|
||||
return this.add(a, b);
|
||||
}
|
||||
subN(a, b) {
|
||||
return this.sub(a, b);
|
||||
}
|
||||
mulN(a, b) {
|
||||
return this.mul(a, b);
|
||||
}
|
||||
sqrN(a) {
|
||||
return this.sqr(a);
|
||||
}
|
||||
// Bytes utils
|
||||
fromBytes(b) {
|
||||
const { Fp6 } = this;
|
||||
if (b.length !== this.BYTES)
|
||||
throw new Error('fromBytes invalid length=' + b.length);
|
||||
return {
|
||||
c0: Fp6.fromBytes(b.subarray(0, Fp6.BYTES)),
|
||||
c1: Fp6.fromBytes(b.subarray(Fp6.BYTES)),
|
||||
};
|
||||
}
|
||||
toBytes({ c0, c1 }) {
|
||||
const { Fp6 } = this;
|
||||
return concatBytes(Fp6.toBytes(c0), Fp6.toBytes(c1));
|
||||
}
|
||||
cmov({ c0, c1 }, { c0: r0, c1: r1 }, c) {
|
||||
const { Fp6 } = this;
|
||||
return {
|
||||
c0: Fp6.cmov(c0, r0, c),
|
||||
c1: Fp6.cmov(c1, r1, c),
|
||||
};
|
||||
}
|
||||
// Utils
|
||||
// toString() {
|
||||
// return '' + 'Fp12(' + this.c0 + this.c1 + '* w');
|
||||
// },
|
||||
// fromTuple(c: [Fp6, Fp6]) {
|
||||
// return new Fp12(...c);
|
||||
// }
|
||||
fromBigTwelve(t) {
|
||||
const { Fp6 } = this;
|
||||
return {
|
||||
c0: Fp6.fromBigSix(t.slice(0, 6)),
|
||||
c1: Fp6.fromBigSix(t.slice(6, 12)),
|
||||
};
|
||||
}
|
||||
// Raises to q**i -th power
|
||||
frobeniusMap(lhs, power) {
|
||||
const { Fp6 } = this;
|
||||
const { Fp2 } = Fp6;
|
||||
const { c0, c1, c2 } = Fp6.frobeniusMap(lhs.c1, power);
|
||||
const coeff = this.FROBENIUS_COEFFICIENTS[power % 12];
|
||||
return {
|
||||
c0: Fp6.frobeniusMap(lhs.c0, power),
|
||||
c1: Fp6.create({
|
||||
c0: Fp2.mul(c0, coeff),
|
||||
c1: Fp2.mul(c1, coeff),
|
||||
c2: Fp2.mul(c2, coeff),
|
||||
}),
|
||||
};
|
||||
}
|
||||
mulByFp2({ c0, c1 }, rhs) {
|
||||
const { Fp6 } = this;
|
||||
return {
|
||||
c0: Fp6.mulByFp2(c0, rhs),
|
||||
c1: Fp6.mulByFp2(c1, rhs),
|
||||
};
|
||||
}
|
||||
conjugate({ c0, c1 }) {
|
||||
return { c0, c1: this.Fp6.neg(c1) };
|
||||
}
|
||||
// Sparse multiplication
|
||||
mul014({ c0, c1 }, o0, o1, o4) {
|
||||
const { Fp6 } = this;
|
||||
const { Fp2 } = Fp6;
|
||||
let t0 = Fp6.mul01(c0, o0, o1);
|
||||
let t1 = Fp6.mul1(c1, o4);
|
||||
return {
|
||||
c0: Fp6.add(Fp6.mulByNonresidue(t1), t0), // T1 * v + T0
|
||||
// (c1 + c0) * [o0, o1+o4] - T0 - T1
|
||||
c1: Fp6.sub(Fp6.sub(Fp6.mul01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0), t1),
|
||||
};
|
||||
}
|
||||
mul034({ c0, c1 }, o0, o3, o4) {
|
||||
const { Fp6 } = this;
|
||||
const { Fp2 } = Fp6;
|
||||
const a = Fp6.create({
|
||||
c0: Fp2.mul(c0.c0, o0),
|
||||
c1: Fp2.mul(c0.c1, o0),
|
||||
c2: Fp2.mul(c0.c2, o0),
|
||||
});
|
||||
const b = Fp6.mul01(c1, o3, o4);
|
||||
const e = Fp6.mul01(Fp6.add(c0, c1), Fp2.add(o0, o3), o4);
|
||||
return {
|
||||
c0: Fp6.add(Fp6.mulByNonresidue(b), a),
|
||||
c1: Fp6.sub(e, Fp6.add(a, b)),
|
||||
};
|
||||
}
|
||||
// A cyclotomic group is a subgroup of Fp^n defined by
|
||||
// GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1}
|
||||
// The result of any pairing is in a cyclotomic subgroup
|
||||
// https://eprint.iacr.org/2009/565.pdf
|
||||
// https://eprint.iacr.org/2010/354.pdf
|
||||
_cyclotomicSquare({ c0, c1 }) {
|
||||
const { Fp6 } = this;
|
||||
const { Fp2 } = Fp6;
|
||||
const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0;
|
||||
const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1;
|
||||
const { first: t3, second: t4 } = Fp2.Fp4Square(c0c0, c1c1);
|
||||
const { first: t5, second: t6 } = Fp2.Fp4Square(c1c0, c0c2);
|
||||
const { first: t7, second: t8 } = Fp2.Fp4Square(c0c1, c1c2);
|
||||
const t9 = Fp2.mulByNonresidue(t8); // T8 * (u + 1)
|
||||
return {
|
||||
c0: Fp6.create({
|
||||
c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3
|
||||
c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5
|
||||
c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7),
|
||||
}), // 2 * (T7 - c0c2) + T7
|
||||
c1: Fp6.create({
|
||||
c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9
|
||||
c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4
|
||||
c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6),
|
||||
}),
|
||||
}; // 2 * (T6 + c1c2) + T6
|
||||
}
|
||||
// https://eprint.iacr.org/2009/565.pdf
|
||||
_cyclotomicExp(num, n) {
|
||||
let z = this.ONE;
|
||||
for (let i = this.X_LEN - 1; i >= 0; i--) {
|
||||
z = this._cyclotomicSquare(z);
|
||||
if (bitGet(n, i))
|
||||
z = this.mul(z, num);
|
||||
}
|
||||
return z;
|
||||
}
|
||||
}
|
||||
export function tower12(opts) {
|
||||
const Fp = mod.Field(opts.ORDER);
|
||||
const Fp2 = new _Field2(Fp, opts);
|
||||
const Fp6 = new _Field6(Fp2);
|
||||
const Fp12 = new _Field12(Fp6, opts);
|
||||
return { Fp, Fp2, Fp6, Fp12 };
|
||||
}
|
||||
//# sourceMappingURL=tower.js.map
|
||||
1
node_modules/@noble/curves/esm/abstract/tower.js.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/tower.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
78
node_modules/@noble/curves/esm/abstract/utils.d.ts
generated
vendored
Normal file
78
node_modules/@noble/curves/esm/abstract/utils.d.ts
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Deprecated module: moved from curves/abstract/utils.js to curves/utils.js
|
||||
* @module
|
||||
*/
|
||||
import * as u from '../utils.ts';
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export type Hex = u.Hex;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export type PrivKey = u.PrivKey;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export type CHash = u.CHash;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export type FHash = u.FHash;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const abytes: typeof u.abytes;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const anumber: typeof u.anumber;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const bytesToHex: typeof u.bytesToHex;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const bytesToUtf8: typeof u.bytesToUtf8;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const concatBytes: typeof u.concatBytes;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const hexToBytes: typeof u.hexToBytes;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const isBytes: typeof u.isBytes;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const randomBytes: typeof u.randomBytes;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const utf8ToBytes: typeof u.utf8ToBytes;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const abool: typeof u.abool;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const numberToHexUnpadded: typeof u.numberToHexUnpadded;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const hexToNumber: typeof u.hexToNumber;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const bytesToNumberBE: typeof u.bytesToNumberBE;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const bytesToNumberLE: typeof u.bytesToNumberLE;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const numberToBytesBE: typeof u.numberToBytesBE;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const numberToBytesLE: typeof u.numberToBytesLE;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const numberToVarBytesBE: typeof u.numberToVarBytesBE;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const ensureBytes: typeof u.ensureBytes;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const equalBytes: typeof u.equalBytes;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const copyBytes: typeof u.copyBytes;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const asciiToBytes: typeof u.asciiToBytes;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const inRange: typeof u.inRange;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const aInRange: typeof u.aInRange;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const bitLen: typeof u.bitLen;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const bitGet: typeof u.bitGet;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const bitSet: typeof u.bitSet;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const bitMask: typeof u.bitMask;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const createHmacDrbg: typeof u.createHmacDrbg;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const notImplemented: typeof u.notImplemented;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const memoized: typeof u.memoized;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const validateObject: typeof u.validateObject;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export declare const isHash: typeof u.isHash;
|
||||
//# sourceMappingURL=utils.d.ts.map
|
||||
1
node_modules/@noble/curves/esm/abstract/utils.d.ts.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/utils.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/abstract/utils.ts"],"names":[],"mappings":"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"}
|
||||
70
node_modules/@noble/curves/esm/abstract/utils.js
generated
vendored
Normal file
70
node_modules/@noble/curves/esm/abstract/utils.js
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Deprecated module: moved from curves/abstract/utils.js to curves/utils.js
|
||||
* @module
|
||||
*/
|
||||
import * as u from "../utils.js";
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const abytes = u.abytes;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const anumber = u.anumber;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const bytesToHex = u.bytesToHex;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const bytesToUtf8 = u.bytesToUtf8;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const concatBytes = u.concatBytes;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const hexToBytes = u.hexToBytes;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const isBytes = u.isBytes;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const randomBytes = u.randomBytes;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const utf8ToBytes = u.utf8ToBytes;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const abool = u.abool;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const numberToHexUnpadded = u.numberToHexUnpadded;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const hexToNumber = u.hexToNumber;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const bytesToNumberBE = u.bytesToNumberBE;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const bytesToNumberLE = u.bytesToNumberLE;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const numberToBytesBE = u.numberToBytesBE;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const numberToBytesLE = u.numberToBytesLE;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const numberToVarBytesBE = u.numberToVarBytesBE;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const ensureBytes = u.ensureBytes;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const equalBytes = u.equalBytes;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const copyBytes = u.copyBytes;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const asciiToBytes = u.asciiToBytes;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const inRange = u.inRange;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const aInRange = u.aInRange;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const bitLen = u.bitLen;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const bitGet = u.bitGet;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const bitSet = u.bitSet;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const bitMask = u.bitMask;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const createHmacDrbg = u.createHmacDrbg;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const notImplemented = u.notImplemented;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const memoized = u.memoized;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const validateObject = u.validateObject;
|
||||
/** @deprecated moved to `@noble/curves/utils.js` */
|
||||
export const isHash = u.isHash;
|
||||
//# sourceMappingURL=utils.js.map
|
||||
1
node_modules/@noble/curves/esm/abstract/utils.js.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/utils.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/abstract/utils.ts"],"names":[],"mappings":"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"}
|
||||
416
node_modules/@noble/curves/esm/abstract/weierstrass.d.ts
generated
vendored
Normal file
416
node_modules/@noble/curves/esm/abstract/weierstrass.d.ts
generated
vendored
Normal file
@@ -0,0 +1,416 @@
|
||||
import { type CHash, type Hex, type PrivKey } from '../utils.ts';
|
||||
import { type AffinePoint, type BasicCurve, type CurveLengths, type CurvePoint, type CurvePointCons } from './curve.ts';
|
||||
import { type IField, type NLength } from './modular.ts';
|
||||
export type { AffinePoint };
|
||||
export type HmacFnSync = (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
|
||||
type EndoBasis = [[bigint, bigint], [bigint, bigint]];
|
||||
/**
|
||||
* When Weierstrass curve has `a=0`, it becomes Koblitz curve.
|
||||
* Koblitz curves allow using **efficiently-computable GLV endomorphism ψ**.
|
||||
* Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%.
|
||||
* For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit.
|
||||
*
|
||||
* Endomorphism consists of beta, lambda and splitScalar:
|
||||
*
|
||||
* 1. GLV endomorphism ψ transforms a point: `P = (x, y) ↦ ψ(P) = (β·x mod p, y)`
|
||||
* 2. GLV scalar decomposition transforms a scalar: `k ≡ k₁ + k₂·λ (mod n)`
|
||||
* 3. Then these are combined: `k·P = k₁·P + k₂·ψ(P)`
|
||||
* 4. Two 128-bit point-by-scalar multiplications + one point addition is faster than
|
||||
* one 256-bit multiplication.
|
||||
*
|
||||
* where
|
||||
* * beta: β ∈ Fₚ with β³ = 1, β ≠ 1
|
||||
* * lambda: λ ∈ Fₙ with λ³ = 1, λ ≠ 1
|
||||
* * splitScalar decomposes k ↦ k₁, k₂, by using reduced basis vectors.
|
||||
* Gauss lattice reduction calculates them from initial basis vectors `(n, 0), (-λ, 0)`
|
||||
*
|
||||
* Check out `test/misc/endomorphism.js` and
|
||||
* [gist](https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066).
|
||||
*/
|
||||
export type EndomorphismOpts = {
|
||||
beta: bigint;
|
||||
basises?: EndoBasis;
|
||||
splitScalar?: (k: bigint) => {
|
||||
k1neg: boolean;
|
||||
k1: bigint;
|
||||
k2neg: boolean;
|
||||
k2: bigint;
|
||||
};
|
||||
};
|
||||
export type ScalarEndoParts = {
|
||||
k1neg: boolean;
|
||||
k1: bigint;
|
||||
k2neg: boolean;
|
||||
k2: bigint;
|
||||
};
|
||||
/**
|
||||
* Splits scalar for GLV endomorphism.
|
||||
*/
|
||||
export declare function _splitEndoScalar(k: bigint, basis: EndoBasis, n: bigint): ScalarEndoParts;
|
||||
export type ECDSASigFormat = 'compact' | 'recovered' | 'der';
|
||||
export type ECDSARecoverOpts = {
|
||||
prehash?: boolean;
|
||||
};
|
||||
export type ECDSAVerifyOpts = {
|
||||
prehash?: boolean;
|
||||
lowS?: boolean;
|
||||
format?: ECDSASigFormat;
|
||||
};
|
||||
export type ECDSASignOpts = {
|
||||
prehash?: boolean;
|
||||
lowS?: boolean;
|
||||
format?: ECDSASigFormat;
|
||||
extraEntropy?: Uint8Array | boolean;
|
||||
};
|
||||
/** Instance methods for 3D XYZ projective points. */
|
||||
export interface WeierstrassPoint<T> extends CurvePoint<T, WeierstrassPoint<T>> {
|
||||
/** projective X coordinate. Different from affine x. */
|
||||
readonly X: T;
|
||||
/** projective Y coordinate. Different from affine y. */
|
||||
readonly Y: T;
|
||||
/** projective z coordinate */
|
||||
readonly Z: T;
|
||||
/** affine x coordinate. Different from projective X. */
|
||||
get x(): T;
|
||||
/** affine y coordinate. Different from projective Y. */
|
||||
get y(): T;
|
||||
/** Encodes point using IEEE P1363 (DER) encoding. First byte is 2/3/4. Default = isCompressed. */
|
||||
toBytes(isCompressed?: boolean): Uint8Array;
|
||||
toHex(isCompressed?: boolean): string;
|
||||
/** @deprecated use `.X` */
|
||||
readonly px: T;
|
||||
/** @deprecated use `.Y` */
|
||||
readonly py: T;
|
||||
/** @deprecated use `.Z` */
|
||||
readonly pz: T;
|
||||
/** @deprecated use `toBytes` */
|
||||
toRawBytes(isCompressed?: boolean): Uint8Array;
|
||||
/** @deprecated use `multiplyUnsafe` */
|
||||
multiplyAndAddUnsafe(Q: WeierstrassPoint<T>, a: bigint, b: bigint): WeierstrassPoint<T> | undefined;
|
||||
/** @deprecated use `p.y % 2n === 0n` */
|
||||
hasEvenY(): boolean;
|
||||
/** @deprecated use `p.precompute(windowSize)` */
|
||||
_setWindowSize(windowSize: number): void;
|
||||
}
|
||||
/** Static methods for 3D XYZ projective points. */
|
||||
export interface WeierstrassPointCons<T> extends CurvePointCons<WeierstrassPoint<T>> {
|
||||
/** Does NOT validate if the point is valid. Use `.assertValidity()`. */
|
||||
new (X: T, Y: T, Z: T): WeierstrassPoint<T>;
|
||||
CURVE(): WeierstrassOpts<T>;
|
||||
/** @deprecated use `Point.BASE.multiply(Point.Fn.fromBytes(privateKey))` */
|
||||
fromPrivateKey(privateKey: PrivKey): WeierstrassPoint<T>;
|
||||
/** @deprecated use `import { normalizeZ } from '@noble/curves/abstract/curve.js';` */
|
||||
normalizeZ(points: WeierstrassPoint<T>[]): WeierstrassPoint<T>[];
|
||||
/** @deprecated use `import { pippenger } from '@noble/curves/abstract/curve.js';` */
|
||||
msm(points: WeierstrassPoint<T>[], scalars: bigint[]): WeierstrassPoint<T>;
|
||||
}
|
||||
/**
|
||||
* Weierstrass curve options.
|
||||
*
|
||||
* * p: prime characteristic (order) of finite field, in which arithmetics is done
|
||||
* * n: order of prime subgroup a.k.a total amount of valid curve points
|
||||
* * h: cofactor, usually 1. h*n is group order; n is subgroup order
|
||||
* * a: formula param, must be in field of p
|
||||
* * b: formula param, must be in field of p
|
||||
* * Gx: x coordinate of generator point a.k.a. base point
|
||||
* * Gy: y coordinate of generator point
|
||||
*/
|
||||
export type WeierstrassOpts<T> = Readonly<{
|
||||
p: bigint;
|
||||
n: bigint;
|
||||
h: bigint;
|
||||
a: T;
|
||||
b: T;
|
||||
Gx: T;
|
||||
Gy: T;
|
||||
}>;
|
||||
export type WeierstrassExtraOpts<T> = Partial<{
|
||||
Fp: IField<T>;
|
||||
Fn: IField<bigint>;
|
||||
allowInfinityPoint: boolean;
|
||||
endo: EndomorphismOpts;
|
||||
isTorsionFree: (c: WeierstrassPointCons<T>, point: WeierstrassPoint<T>) => boolean;
|
||||
clearCofactor: (c: WeierstrassPointCons<T>, point: WeierstrassPoint<T>) => WeierstrassPoint<T>;
|
||||
fromBytes: (bytes: Uint8Array) => AffinePoint<T>;
|
||||
toBytes: (c: WeierstrassPointCons<T>, point: WeierstrassPoint<T>, isCompressed: boolean) => Uint8Array;
|
||||
}>;
|
||||
/**
|
||||
* Options for ECDSA signatures over a Weierstrass curve.
|
||||
*
|
||||
* * lowS: (default: true) whether produced / verified signatures occupy low half of ecdsaOpts.p. Prevents malleability.
|
||||
* * hmac: (default: noble-hashes hmac) function, would be used to init hmac-drbg for k generation.
|
||||
* * randomBytes: (default: webcrypto os-level CSPRNG) custom method for fetching secure randomness.
|
||||
* * bits2int, bits2int_modN: used in sigs, sometimes overridden by curves
|
||||
*/
|
||||
export type ECDSAOpts = Partial<{
|
||||
lowS: boolean;
|
||||
hmac: HmacFnSync;
|
||||
randomBytes: (bytesLength?: number) => Uint8Array;
|
||||
bits2int: (bytes: Uint8Array) => bigint;
|
||||
bits2int_modN: (bytes: Uint8Array) => bigint;
|
||||
}>;
|
||||
/**
|
||||
* Elliptic Curve Diffie-Hellman interface.
|
||||
* Provides keygen, secret-to-public conversion, calculating shared secrets.
|
||||
*/
|
||||
export interface ECDH {
|
||||
keygen: (seed?: Uint8Array) => {
|
||||
secretKey: Uint8Array;
|
||||
publicKey: Uint8Array;
|
||||
};
|
||||
getPublicKey: (secretKey: PrivKey, isCompressed?: boolean) => Uint8Array;
|
||||
getSharedSecret: (secretKeyA: PrivKey, publicKeyB: Hex, isCompressed?: boolean) => Uint8Array;
|
||||
Point: WeierstrassPointCons<bigint>;
|
||||
utils: {
|
||||
isValidSecretKey: (secretKey: PrivKey) => boolean;
|
||||
isValidPublicKey: (publicKey: Uint8Array, isCompressed?: boolean) => boolean;
|
||||
randomSecretKey: (seed?: Uint8Array) => Uint8Array;
|
||||
/** @deprecated use `randomSecretKey` */
|
||||
randomPrivateKey: (seed?: Uint8Array) => Uint8Array;
|
||||
/** @deprecated use `isValidSecretKey` */
|
||||
isValidPrivateKey: (secretKey: PrivKey) => boolean;
|
||||
/** @deprecated use `Point.Fn.fromBytes()` */
|
||||
normPrivateKeyToScalar: (key: PrivKey) => bigint;
|
||||
/** @deprecated use `point.precompute()` */
|
||||
precompute: (windowSize?: number, point?: WeierstrassPoint<bigint>) => WeierstrassPoint<bigint>;
|
||||
};
|
||||
lengths: CurveLengths;
|
||||
}
|
||||
/**
|
||||
* ECDSA interface.
|
||||
* Only supported for prime fields, not Fp2 (extension fields).
|
||||
*/
|
||||
export interface ECDSA extends ECDH {
|
||||
sign: (message: Hex, secretKey: PrivKey, opts?: ECDSASignOpts) => ECDSASigRecovered;
|
||||
verify: (signature: Uint8Array, message: Uint8Array, publicKey: Uint8Array, opts?: ECDSAVerifyOpts) => boolean;
|
||||
recoverPublicKey(signature: Uint8Array, message: Uint8Array, opts?: ECDSARecoverOpts): Uint8Array;
|
||||
Signature: ECDSASignatureCons;
|
||||
}
|
||||
export declare class DERErr extends Error {
|
||||
constructor(m?: string);
|
||||
}
|
||||
export type IDER = {
|
||||
Err: typeof DERErr;
|
||||
_tlv: {
|
||||
encode: (tag: number, data: string) => string;
|
||||
decode(tag: number, data: Uint8Array): {
|
||||
v: Uint8Array;
|
||||
l: Uint8Array;
|
||||
};
|
||||
};
|
||||
_int: {
|
||||
encode(num: bigint): string;
|
||||
decode(data: Uint8Array): bigint;
|
||||
};
|
||||
toSig(hex: string | Uint8Array): {
|
||||
r: bigint;
|
||||
s: bigint;
|
||||
};
|
||||
hexFromSig(sig: {
|
||||
r: bigint;
|
||||
s: bigint;
|
||||
}): string;
|
||||
};
|
||||
/**
|
||||
* ASN.1 DER encoding utilities. ASN is very complex & fragile. Format:
|
||||
*
|
||||
* [0x30 (SEQUENCE), bytelength, 0x02 (INTEGER), intLength, R, 0x02 (INTEGER), intLength, S]
|
||||
*
|
||||
* Docs: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/, https://luca.ntop.org/Teaching/Appunti/asn1.html
|
||||
*/
|
||||
export declare const DER: IDER;
|
||||
export declare function _normFnElement(Fn: IField<bigint>, key: PrivKey): bigint;
|
||||
/**
|
||||
* Creates weierstrass Point constructor, based on specified curve options.
|
||||
*
|
||||
* @example
|
||||
```js
|
||||
const opts = {
|
||||
p: BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff'),
|
||||
n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'),
|
||||
h: BigInt(1),
|
||||
a: BigInt('0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc'),
|
||||
b: BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b'),
|
||||
Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'),
|
||||
Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'),
|
||||
};
|
||||
const p256_Point = weierstrass(opts);
|
||||
```
|
||||
*/
|
||||
export declare function weierstrassN<T>(params: WeierstrassOpts<T>, extraOpts?: WeierstrassExtraOpts<T>): WeierstrassPointCons<T>;
|
||||
/** Methods of ECDSA signature instance. */
|
||||
export interface ECDSASignature {
|
||||
readonly r: bigint;
|
||||
readonly s: bigint;
|
||||
readonly recovery?: number;
|
||||
addRecoveryBit(recovery: number): ECDSASigRecovered;
|
||||
hasHighS(): boolean;
|
||||
toBytes(format?: string): Uint8Array;
|
||||
toHex(format?: string): string;
|
||||
/** @deprecated */
|
||||
assertValidity(): void;
|
||||
/** @deprecated */
|
||||
normalizeS(): ECDSASignature;
|
||||
/** @deprecated use standalone method `curve.recoverPublicKey(sig.toBytes('recovered'), msg)` */
|
||||
recoverPublicKey(msgHash: Hex): WeierstrassPoint<bigint>;
|
||||
/** @deprecated use `.toBytes('compact')` */
|
||||
toCompactRawBytes(): Uint8Array;
|
||||
/** @deprecated use `.toBytes('compact')` */
|
||||
toCompactHex(): string;
|
||||
/** @deprecated use `.toBytes('der')` */
|
||||
toDERRawBytes(): Uint8Array;
|
||||
/** @deprecated use `.toBytes('der')` */
|
||||
toDERHex(): string;
|
||||
}
|
||||
export type ECDSASigRecovered = ECDSASignature & {
|
||||
readonly recovery: number;
|
||||
};
|
||||
/** Methods of ECDSA signature constructor. */
|
||||
export type ECDSASignatureCons = {
|
||||
new (r: bigint, s: bigint, recovery?: number): ECDSASignature;
|
||||
fromBytes(bytes: Uint8Array, format?: ECDSASigFormat): ECDSASignature;
|
||||
fromHex(hex: string, format?: ECDSASigFormat): ECDSASignature;
|
||||
/** @deprecated use `.fromBytes(bytes, 'compact')` */
|
||||
fromCompact(hex: Hex): ECDSASignature;
|
||||
/** @deprecated use `.fromBytes(bytes, 'der')` */
|
||||
fromDER(hex: Hex): ECDSASignature;
|
||||
};
|
||||
/**
|
||||
* Implementation of the Shallue and van de Woestijne method for any weierstrass curve.
|
||||
* TODO: check if there is a way to merge this with uvRatio in Edwards; move to modular.
|
||||
* b = True and y = sqrt(u / v) if (u / v) is square in F, and
|
||||
* b = False and y = sqrt(Z * (u / v)) otherwise.
|
||||
* @param Fp
|
||||
* @param Z
|
||||
* @returns
|
||||
*/
|
||||
export declare function SWUFpSqrtRatio<T>(Fp: IField<T>, Z: T): (u: T, v: T) => {
|
||||
isValid: boolean;
|
||||
value: T;
|
||||
};
|
||||
/**
|
||||
* Simplified Shallue-van de Woestijne-Ulas Method
|
||||
* https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2
|
||||
*/
|
||||
export declare function mapToCurveSimpleSWU<T>(Fp: IField<T>, opts: {
|
||||
A: T;
|
||||
B: T;
|
||||
Z: T;
|
||||
}): (u: T) => {
|
||||
x: T;
|
||||
y: T;
|
||||
};
|
||||
/**
|
||||
* Sometimes users only need getPublicKey, getSharedSecret, and secret key handling.
|
||||
* This helper ensures no signature functionality is present. Less code, smaller bundle size.
|
||||
*/
|
||||
export declare function ecdh(Point: WeierstrassPointCons<bigint>, ecdhOpts?: {
|
||||
randomBytes?: (bytesLength?: number) => Uint8Array;
|
||||
}): ECDH;
|
||||
/**
|
||||
* Creates ECDSA signing interface for given elliptic curve `Point` and `hash` function.
|
||||
* We need `hash` for 2 features:
|
||||
* 1. Message prehash-ing. NOT used if `sign` / `verify` are called with `prehash: false`
|
||||
* 2. k generation in `sign`, using HMAC-drbg(hash)
|
||||
*
|
||||
* ECDSAOpts are only rarely needed.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* const p256_Point = weierstrass(...);
|
||||
* const p256_sha256 = ecdsa(p256_Point, sha256);
|
||||
* const p256_sha224 = ecdsa(p256_Point, sha224);
|
||||
* const p256_sha224_r = ecdsa(p256_Point, sha224, { randomBytes: (length) => { ... } });
|
||||
* ```
|
||||
*/
|
||||
export declare function ecdsa(Point: WeierstrassPointCons<bigint>, hash: CHash, ecdsaOpts?: ECDSAOpts): ECDSA;
|
||||
/** @deprecated use ECDSASignature */
|
||||
export type SignatureType = ECDSASignature;
|
||||
/** @deprecated use ECDSASigRecovered */
|
||||
export type RecoveredSignatureType = ECDSASigRecovered;
|
||||
/** @deprecated switch to Uint8Array signatures in format 'compact' */
|
||||
export type SignatureLike = {
|
||||
r: bigint;
|
||||
s: bigint;
|
||||
};
|
||||
export type ECDSAExtraEntropy = Hex | boolean;
|
||||
/** @deprecated use `ECDSAExtraEntropy` */
|
||||
export type Entropy = Hex | boolean;
|
||||
export type BasicWCurve<T> = BasicCurve<T> & {
|
||||
a: T;
|
||||
b: T;
|
||||
allowedPrivateKeyLengths?: readonly number[];
|
||||
wrapPrivateKey?: boolean;
|
||||
endo?: EndomorphismOpts;
|
||||
isTorsionFree?: (c: WeierstrassPointCons<T>, point: WeierstrassPoint<T>) => boolean;
|
||||
clearCofactor?: (c: WeierstrassPointCons<T>, point: WeierstrassPoint<T>) => WeierstrassPoint<T>;
|
||||
};
|
||||
/** @deprecated use ECDSASignOpts */
|
||||
export type SignOpts = ECDSASignOpts;
|
||||
/** @deprecated use ECDSASignOpts */
|
||||
export type VerOpts = ECDSAVerifyOpts;
|
||||
/** @deprecated use WeierstrassPoint */
|
||||
export type ProjPointType<T> = WeierstrassPoint<T>;
|
||||
/** @deprecated use WeierstrassPointCons */
|
||||
export type ProjConstructor<T> = WeierstrassPointCons<T>;
|
||||
/** @deprecated use ECDSASignatureCons */
|
||||
export type SignatureConstructor = ECDSASignatureCons;
|
||||
export type CurvePointsType<T> = BasicWCurve<T> & {
|
||||
fromBytes?: (bytes: Uint8Array) => AffinePoint<T>;
|
||||
toBytes?: (c: WeierstrassPointCons<T>, point: WeierstrassPoint<T>, isCompressed: boolean) => Uint8Array;
|
||||
};
|
||||
export type CurvePointsTypeWithLength<T> = Readonly<CurvePointsType<T> & Partial<NLength>>;
|
||||
export type CurvePointsRes<T> = {
|
||||
Point: WeierstrassPointCons<T>;
|
||||
/** @deprecated use `Point.CURVE()` */
|
||||
CURVE: CurvePointsType<T>;
|
||||
/** @deprecated use `Point` */
|
||||
ProjectivePoint: WeierstrassPointCons<T>;
|
||||
/** @deprecated use `Point.Fn.fromBytes(privateKey)` */
|
||||
normPrivateKeyToScalar: (key: PrivKey) => bigint;
|
||||
/** @deprecated */
|
||||
weierstrassEquation: (x: T) => T;
|
||||
/** @deprecated use `Point.Fn.isValidNot0(num)` */
|
||||
isWithinCurveOrder: (num: bigint) => boolean;
|
||||
};
|
||||
/** @deprecated use `Uint8Array` */
|
||||
export type PubKey = Hex | WeierstrassPoint<bigint>;
|
||||
export type CurveType = BasicWCurve<bigint> & {
|
||||
hash: CHash;
|
||||
hmac?: HmacFnSync;
|
||||
randomBytes?: (bytesLength?: number) => Uint8Array;
|
||||
lowS?: boolean;
|
||||
bits2int?: (bytes: Uint8Array) => bigint;
|
||||
bits2int_modN?: (bytes: Uint8Array) => bigint;
|
||||
};
|
||||
export type CurveFn = {
|
||||
/** @deprecated use `Point.CURVE()` */
|
||||
CURVE: CurvePointsType<bigint>;
|
||||
keygen: ECDSA['keygen'];
|
||||
getPublicKey: ECDSA['getPublicKey'];
|
||||
getSharedSecret: ECDSA['getSharedSecret'];
|
||||
sign: ECDSA['sign'];
|
||||
verify: ECDSA['verify'];
|
||||
Point: WeierstrassPointCons<bigint>;
|
||||
/** @deprecated use `Point` */
|
||||
ProjectivePoint: WeierstrassPointCons<bigint>;
|
||||
Signature: ECDSASignatureCons;
|
||||
utils: ECDSA['utils'];
|
||||
lengths: ECDSA['lengths'];
|
||||
};
|
||||
/** @deprecated use `weierstrass` in newer releases */
|
||||
export declare function weierstrassPoints<T>(c: CurvePointsTypeWithLength<T>): CurvePointsRes<T>;
|
||||
export type WsPointComposed<T> = {
|
||||
CURVE: WeierstrassOpts<T>;
|
||||
curveOpts: WeierstrassExtraOpts<T>;
|
||||
};
|
||||
export type WsComposed = {
|
||||
/** @deprecated use `Point.CURVE()` */
|
||||
CURVE: WeierstrassOpts<bigint>;
|
||||
hash: CHash;
|
||||
curveOpts: WeierstrassExtraOpts<bigint>;
|
||||
ecdsaOpts: ECDSAOpts;
|
||||
};
|
||||
export declare function _legacyHelperEquat<T>(Fp: IField<T>, a: T, b: T): (x: T) => T;
|
||||
export declare function weierstrass(c: CurveType): CurveFn;
|
||||
//# sourceMappingURL=weierstrass.d.ts.map
|
||||
1
node_modules/@noble/curves/esm/abstract/weierstrass.d.ts.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/weierstrass.d.ts.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1413
node_modules/@noble/curves/esm/abstract/weierstrass.js
generated
vendored
Normal file
1413
node_modules/@noble/curves/esm/abstract/weierstrass.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
node_modules/@noble/curves/esm/abstract/weierstrass.js.map
generated
vendored
Normal file
1
node_modules/@noble/curves/esm/abstract/weierstrass.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user