@okxweb3/crypto-lib
Version:
A base package for @okxweb3/coin-*
870 lines • 32.5 kB
JavaScript
"use strict";
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.mapToCurveSimpleSWU = exports.SWUFpSqrtRatio = exports.weierstrass = exports.weierstrassPoints = exports.DER = void 0;
const mod = __importStar(require("./modular"));
const ut = __importStar(require("./utils"));
const utils_1 = require("./utils");
const curve_1 = require("./curve");
function validatePointOpts(curve) {
const opts = (0, curve_1.validateBasic)(curve);
ut.validateObject(opts, {
a: 'field',
b: 'field',
}, {
allowedPrivateKeyLengths: 'array',
wrapPrivateKey: 'boolean',
isTorsionFree: 'function',
clearCofactor: 'function',
allowInfinityPoint: 'boolean',
fromBytes: 'function',
toBytes: 'function',
});
const { endo, Fp, a } = opts;
if (endo) {
if (!Fp.eql(a, Fp.ZERO)) {
throw new Error('Endomorphism can only be defined for Koblitz curves that have a=0');
}
if (typeof endo !== 'object' ||
typeof endo.beta !== 'bigint' ||
typeof endo.splitScalar !== 'function') {
throw new Error('Expected endomorphism with beta: bigint and splitScalar: function');
}
}
return Object.freeze({ ...opts });
}
const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut;
exports.DER = {
Err: class DERErr extends Error {
constructor(m = '') {
super(m);
}
},
_parseInt(data) {
const { Err: E } = exports.DER;
if (data.length < 2 || data[0] !== 0x02)
throw new E('Invalid signature integer tag');
const len = data[1];
const res = data.subarray(2, len + 2);
if (!len || res.length !== len)
throw new E('Invalid signature integer: wrong length');
if (res[0] & 0b10000000)
throw new E('Invalid signature integer: negative');
if (res[0] === 0x00 && !(res[1] & 0b10000000))
throw new E('Invalid signature integer: unnecessary leading zero');
return { d: b2n(res), l: data.subarray(len + 2) };
},
toSig(hex) {
const { Err: E } = exports.DER;
const data = typeof hex === 'string' ? h2b(hex) : hex;
if (!(data instanceof Uint8Array))
throw new Error('ui8a expected');
let l = data.length;
if (l < 2 || data[0] != 0x30)
throw new E('Invalid signature tag');
if (data[1] !== l - 2)
throw new E('Invalid signature: incorrect length');
const { d: r, l: sBytes } = exports.DER._parseInt(data.subarray(2));
const { d: s, l: rBytesLeft } = exports.DER._parseInt(sBytes);
if (rBytesLeft.length)
throw new E('Invalid signature: left bytes after parsing');
return { r, s };
},
hexFromSig(sig) {
const slice = (s) => (Number.parseInt(s[0], 16) & 0b1000 ? '00' + s : s);
const h = (num) => {
const hex = num.toString(16);
return hex.length & 1 ? `0${hex}` : hex;
};
const s = slice(h(sig.s));
const r = slice(h(sig.r));
const shl = s.length / 2;
const rhl = r.length / 2;
const sl = h(shl);
const rl = h(rhl);
return `30${h(rhl + shl + 4)}02${rl}${r}02${sl}${s}`;
},
};
const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);
function weierstrassPoints(opts) {
const CURVE = validatePointOpts(opts);
const { Fp } = CURVE;
const toBytes = CURVE.toBytes ||
((c, point, isCompressed) => {
const a = point.toAffine();
return ut.concatBytes(Uint8Array.from([0x04]), Fp.toBytes(a.x), Fp.toBytes(a.y));
});
const fromBytes = CURVE.fromBytes ||
((bytes) => {
const tail = bytes.subarray(1);
const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES));
const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES));
return { x, y };
});
function weierstrassEquation(x) {
const { a, b } = CURVE;
const x2 = Fp.sqr(x);
const x3 = Fp.mul(x2, x);
return Fp.add(Fp.add(x3, Fp.mul(x, a)), b);
}
if (!Fp.eql(Fp.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx)))
throw new Error('bad generator point: equation left != right');
function isWithinCurveOrder(num) {
return typeof num === 'bigint' && _0n < num && num < CURVE.n;
}
function assertGE(num) {
if (!isWithinCurveOrder(num))
throw new Error('Expected valid bigint: 0 < bigint < curve.n');
}
function normPrivateKeyToScalar(key) {
const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n } = CURVE;
if (lengths && typeof key !== 'bigint') {
if (key instanceof Uint8Array)
key = ut.bytesToHex(key);
if (typeof key !== 'string' || !lengths.includes(key.length))
throw new Error('Invalid key');
key = key.padStart(nByteLength * 2, '0');
}
let num;
try {
num =
typeof key === 'bigint'
? key
: ut.bytesToNumberBE((0, utils_1.ensureBytes)('private key', key, nByteLength));
}
catch (error) {
throw new Error(`private key must be ${nByteLength} bytes, hex or bigint, not ${typeof key}`);
}
if (wrapPrivateKey)
num = mod.mod(num, n);
assertGE(num);
return num;
}
const pointPrecomputes = new Map();
function assertPrjPoint(other) {
if (!(other instanceof Point))
throw new Error('ProjectivePoint expected');
}
class Point {
constructor(px, py, pz) {
this.px = px;
this.py = py;
this.pz = pz;
if (px == null || !Fp.isValid(px))
throw new Error('x required');
if (py == null || !Fp.isValid(py))
throw new Error('y required');
if (pz == null || !Fp.isValid(pz))
throw new Error('z required');
}
static fromAffine(p) {
const { x, y } = p || {};
if (!p || !Fp.isValid(x) || !Fp.isValid(y))
throw new Error('invalid affine point');
if (p instanceof Point)
throw new Error('projective point not allowed');
const is0 = (i) => Fp.eql(i, Fp.ZERO);
if (is0(x) && is0(y))
return Point.ZERO;
return new Point(x, y, Fp.ONE);
}
get x() {
return this.toAffine().x;
}
get y() {
return this.toAffine().y;
}
static normalizeZ(points) {
const toInv = Fp.invertBatch(points.map((p) => p.pz));
return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine);
}
static fromHex(hex) {
const P = Point.fromAffine(fromBytes((0, utils_1.ensureBytes)('pointHex', hex)));
P.assertValidity();
return P;
}
static fromPrivateKey(privateKey) {
return Point.BASE.multiply(normPrivateKeyToScalar(privateKey));
}
_setWindowSize(windowSize) {
this._WINDOW_SIZE = windowSize;
pointPrecomputes.delete(this);
}
assertValidity() {
if (this.is0()) {
if (CURVE.allowInfinityPoint)
return;
throw new Error('bad point: ZERO');
}
const { x, y } = this.toAffine();
if (!Fp.isValid(x) || !Fp.isValid(y))
throw new Error('bad point: x or y not FE');
const left = Fp.sqr(y);
const right = weierstrassEquation(x);
if (!Fp.eql(left, right))
throw new Error('bad point: equation left != right');
if (!this.isTorsionFree())
throw new Error('bad point: not in prime-order subgroup');
}
hasEvenY() {
const { y } = this.toAffine();
if (Fp.isOdd)
return !Fp.isOdd(y);
throw new Error("Field doesn't support isOdd");
}
equals(other) {
assertPrjPoint(other);
const { px: X1, py: Y1, pz: Z1 } = this;
const { px: X2, py: Y2, pz: Z2 } = other;
const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1));
const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1));
return U1 && U2;
}
negate() {
return new Point(this.px, Fp.neg(this.py), this.pz);
}
double() {
const { a, b } = CURVE;
const b3 = Fp.mul(b, _3n);
const { px: X1, py: Y1, pz: Z1 } = this;
let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO;
let t0 = Fp.mul(X1, X1);
let t1 = Fp.mul(Y1, Y1);
let t2 = Fp.mul(Z1, Z1);
let t3 = Fp.mul(X1, Y1);
t3 = Fp.add(t3, t3);
Z3 = Fp.mul(X1, Z1);
Z3 = Fp.add(Z3, Z3);
X3 = Fp.mul(a, Z3);
Y3 = Fp.mul(b3, t2);
Y3 = Fp.add(X3, Y3);
X3 = Fp.sub(t1, Y3);
Y3 = Fp.add(t1, Y3);
Y3 = Fp.mul(X3, Y3);
X3 = Fp.mul(t3, X3);
Z3 = Fp.mul(b3, Z3);
t2 = Fp.mul(a, t2);
t3 = Fp.sub(t0, t2);
t3 = Fp.mul(a, t3);
t3 = Fp.add(t3, Z3);
Z3 = Fp.add(t0, t0);
t0 = Fp.add(Z3, t0);
t0 = Fp.add(t0, t2);
t0 = Fp.mul(t0, t3);
Y3 = Fp.add(Y3, t0);
t2 = Fp.mul(Y1, Z1);
t2 = Fp.add(t2, t2);
t0 = Fp.mul(t2, t3);
X3 = Fp.sub(X3, t0);
Z3 = Fp.mul(t2, t1);
Z3 = Fp.add(Z3, Z3);
Z3 = Fp.add(Z3, Z3);
return new Point(X3, Y3, Z3);
}
add(other) {
assertPrjPoint(other);
const { px: X1, py: Y1, pz: Z1 } = this;
const { px: X2, py: Y2, pz: Z2 } = other;
let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO;
const a = CURVE.a;
const b3 = Fp.mul(CURVE.b, _3n);
let t0 = Fp.mul(X1, X2);
let t1 = Fp.mul(Y1, Y2);
let t2 = Fp.mul(Z1, Z2);
let t3 = Fp.add(X1, Y1);
let t4 = Fp.add(X2, Y2);
t3 = Fp.mul(t3, t4);
t4 = Fp.add(t0, t1);
t3 = Fp.sub(t3, t4);
t4 = Fp.add(X1, Z1);
let t5 = Fp.add(X2, Z2);
t4 = Fp.mul(t4, t5);
t5 = Fp.add(t0, t2);
t4 = Fp.sub(t4, t5);
t5 = Fp.add(Y1, Z1);
X3 = Fp.add(Y2, Z2);
t5 = Fp.mul(t5, X3);
X3 = Fp.add(t1, t2);
t5 = Fp.sub(t5, X3);
Z3 = Fp.mul(a, t4);
X3 = Fp.mul(b3, t2);
Z3 = Fp.add(X3, Z3);
X3 = Fp.sub(t1, Z3);
Z3 = Fp.add(t1, Z3);
Y3 = Fp.mul(X3, Z3);
t1 = Fp.add(t0, t0);
t1 = Fp.add(t1, t0);
t2 = Fp.mul(a, t2);
t4 = Fp.mul(b3, t4);
t1 = Fp.add(t1, t2);
t2 = Fp.sub(t0, t2);
t2 = Fp.mul(a, t2);
t4 = Fp.add(t4, t2);
t0 = Fp.mul(t1, t4);
Y3 = Fp.add(Y3, t0);
t0 = Fp.mul(t5, t4);
X3 = Fp.mul(t3, X3);
X3 = Fp.sub(X3, t0);
t0 = Fp.mul(t3, t1);
Z3 = Fp.mul(t5, Z3);
Z3 = Fp.add(Z3, t0);
return new Point(X3, Y3, Z3);
}
subtract(other) {
return this.add(other.negate());
}
is0() {
return this.equals(Point.ZERO);
}
wNAF(n) {
return wnaf.wNAFCached(this, pointPrecomputes, n, (comp) => {
const toInv = Fp.invertBatch(comp.map((p) => p.pz));
return comp.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine);
});
}
multiplyUnsafe(n) {
const I = Point.ZERO;
if (n === _0n)
return I;
assertGE(n);
if (n === _1n)
return this;
const { endo } = CURVE;
if (!endo)
return wnaf.unsafeLadder(this, n);
let { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);
let k1p = I;
let k2p = I;
let d = this;
while (k1 > _0n || k2 > _0n) {
if (k1 & _1n)
k1p = k1p.add(d);
if (k2 & _1n)
k2p = k2p.add(d);
d = d.double();
k1 >>= _1n;
k2 >>= _1n;
}
if (k1neg)
k1p = k1p.negate();
if (k2neg)
k2p = k2p.negate();
k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
return k1p.add(k2p);
}
multiply(scalar) {
assertGE(scalar);
let n = scalar;
let point, fake;
const { endo } = CURVE;
if (endo) {
const { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);
let { p: k1p, f: f1p } = this.wNAF(k1);
let { p: k2p, f: f2p } = this.wNAF(k2);
k1p = wnaf.constTimeNegate(k1neg, k1p);
k2p = wnaf.constTimeNegate(k2neg, k2p);
k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
point = k1p.add(k2p);
fake = f1p.add(f2p);
}
else {
const { p, f } = this.wNAF(n);
point = p;
fake = f;
}
return Point.normalizeZ([point, fake])[0];
}
multiplyAndAddUnsafe(Q, a, b) {
const G = Point.BASE;
const mul = (P, a) => (a === _0n || a === _1n || !P.equals(G) ? P.multiplyUnsafe(a) : P.multiply(a));
const sum = mul(this, a).add(mul(Q, b));
return sum.is0() ? undefined : sum;
}
toAffine(iz) {
const { px: x, py: y, pz: z } = this;
const is0 = this.is0();
if (iz == null)
iz = is0 ? Fp.ONE : Fp.inv(z);
const ax = Fp.mul(x, iz);
const ay = Fp.mul(y, iz);
const zz = Fp.mul(z, iz);
if (is0)
return { x: Fp.ZERO, y: Fp.ZERO };
if (!Fp.eql(zz, Fp.ONE))
throw new Error('invZ was invalid');
return { x: ax, y: ay };
}
isTorsionFree() {
const { h: cofactor, isTorsionFree } = CURVE;
if (cofactor === _1n)
return true;
if (isTorsionFree)
return isTorsionFree(Point, this);
throw new Error('isTorsionFree() has not been declared for the elliptic curve');
}
clearCofactor() {
const { h: cofactor, clearCofactor } = CURVE;
if (cofactor === _1n)
return this;
if (clearCofactor)
return clearCofactor(Point, this);
return this.multiplyUnsafe(CURVE.h);
}
toRawBytes(isCompressed = true) {
this.assertValidity();
return toBytes(Point, this, isCompressed);
}
toHex(isCompressed = true) {
return ut.bytesToHex(this.toRawBytes(isCompressed));
}
}
Point.BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE);
Point.ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO);
const _bits = CURVE.nBitLength;
const wnaf = (0, curve_1.wNAF)(Point, CURVE.endo ? Math.ceil(_bits / 2) : _bits);
return {
CURVE,
ProjectivePoint: Point,
normPrivateKeyToScalar,
weierstrassEquation,
isWithinCurveOrder,
};
}
exports.weierstrassPoints = weierstrassPoints;
function validateOpts(curve) {
const opts = (0, curve_1.validateBasic)(curve);
ut.validateObject(opts, {
hash: 'hash',
hmac: 'function',
randomBytes: 'function',
}, {
bits2int: 'function',
bits2int_modN: 'function',
lowS: 'boolean',
});
return Object.freeze({ lowS: true, ...opts });
}
function weierstrass(curveDef) {
const CURVE = validateOpts(curveDef);
const { Fp, n: CURVE_ORDER } = CURVE;
const compressedLen = Fp.BYTES + 1;
const uncompressedLen = 2 * Fp.BYTES + 1;
function isValidFieldElement(num) {
return _0n < num && num < Fp.ORDER;
}
function modN(a) {
return mod.mod(a, CURVE_ORDER);
}
function invN(a) {
return mod.invert(a, CURVE_ORDER);
}
const { ProjectivePoint: Point, normPrivateKeyToScalar, weierstrassEquation, isWithinCurveOrder, } = weierstrassPoints({
...CURVE,
toBytes(c, point, isCompressed) {
const a = point.toAffine();
const x = Fp.toBytes(a.x);
const cat = ut.concatBytes;
if (isCompressed) {
return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x);
}
else {
return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y));
}
},
fromBytes(bytes) {
const len = bytes.length;
const head = bytes[0];
const tail = bytes.subarray(1);
if (len === compressedLen && (head === 0x02 || head === 0x03)) {
const x = ut.bytesToNumberBE(tail);
if (!isValidFieldElement(x))
throw new Error('Point is not on curve');
const y2 = weierstrassEquation(x);
let y = Fp.sqrt(y2);
const isYOdd = (y & _1n) === _1n;
const isHeadOdd = (head & 1) === 1;
if (isHeadOdd !== isYOdd)
y = Fp.neg(y);
return { x, y };
}
else if (len === uncompressedLen && head === 0x04) {
const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES));
const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES));
return { x, y };
}
else {
throw new Error(`Point of length ${len} was invalid. Expected ${compressedLen} compressed bytes or ${uncompressedLen} uncompressed bytes`);
}
},
});
const numToNByteStr = (num) => ut.bytesToHex(ut.numberToBytesBE(num, CURVE.nByteLength));
function isBiggerThanHalfOrder(number) {
const HALF = CURVE_ORDER >> _1n;
return number > HALF;
}
function normalizeS(s) {
return isBiggerThanHalfOrder(s) ? modN(-s) : s;
}
const slcNum = (b, from, to) => ut.bytesToNumberBE(b.slice(from, to));
class Signature {
constructor(r, s, recovery) {
this.r = r;
this.s = s;
this.recovery = recovery;
this.assertValidity();
}
static fromCompact(hex) {
const l = CURVE.nByteLength;
hex = (0, utils_1.ensureBytes)('compactSignature', hex, l * 2);
return new Signature(slcNum(hex, 0, l), slcNum(hex, l, 2 * l));
}
static fromDER(hex) {
const { r, s } = exports.DER.toSig((0, utils_1.ensureBytes)('DER', hex));
return new Signature(r, s);
}
assertValidity() {
if (!isWithinCurveOrder(this.r))
throw new Error('r must be 0 < r < CURVE.n');
if (!isWithinCurveOrder(this.s))
throw new Error('s must be 0 < s < CURVE.n');
}
addRecoveryBit(recovery) {
return new Signature(this.r, this.s, recovery);
}
recoverPublicKey(msgHash) {
const { r, s, recovery: rec } = this;
const h = bits2int_modN((0, utils_1.ensureBytes)('msgHash', msgHash));
if (rec == null || ![0, 1, 2, 3].includes(rec))
throw new Error('recovery id invalid');
const radj = rec === 2 || rec === 3 ? r + CURVE.n : r;
if (radj >= Fp.ORDER)
throw new Error('recovery id 2 or 3 invalid');
const prefix = (rec & 1) === 0 ? '02' : '03';
const R = Point.fromHex(prefix + numToNByteStr(radj));
const ir = invN(radj);
const u1 = modN(-h * ir);
const u2 = modN(s * ir);
const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2);
if (!Q)
throw new Error('point at infinify');
Q.assertValidity();
return Q;
}
hasHighS() {
return isBiggerThanHalfOrder(this.s);
}
normalizeS() {
return this.hasHighS() ? new Signature(this.r, modN(-this.s), this.recovery) : this;
}
toDERRawBytes() {
return ut.hexToBytes(this.toDERHex());
}
toDERHex() {
return exports.DER.hexFromSig({ r: this.r, s: this.s });
}
toCompactRawBytes() {
return ut.hexToBytes(this.toCompactHex());
}
toCompactHex() {
return numToNByteStr(this.r) + numToNByteStr(this.s);
}
}
const utils = {
isValidPrivateKey(privateKey) {
try {
normPrivateKeyToScalar(privateKey);
return true;
}
catch (error) {
return false;
}
},
normPrivateKeyToScalar: normPrivateKeyToScalar,
randomPrivateKey: () => {
const rand = CURVE.randomBytes(Fp.BYTES + 8);
const num = mod.hashToPrivateScalar(rand, CURVE_ORDER);
return ut.numberToBytesBE(num, CURVE.nByteLength);
},
precompute(windowSize = 8, point = Point.BASE) {
point._setWindowSize(windowSize);
point.multiply(BigInt(3));
return point;
},
};
function getPublicKey(privateKey, isCompressed = true) {
return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed);
}
function isProbPub(item) {
const arr = item instanceof Uint8Array;
const str = typeof item === 'string';
const len = (arr || str) && item.length;
if (arr)
return len === compressedLen || len === uncompressedLen;
if (str)
return len === 2 * compressedLen || len === 2 * uncompressedLen;
if (item instanceof Point)
return true;
return false;
}
function getSharedSecret(privateA, publicB, isCompressed = true) {
if (isProbPub(privateA))
throw new Error('first arg must be private key');
if (!isProbPub(publicB))
throw new Error('second arg must be public key');
const b = Point.fromHex(publicB);
return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed);
}
const bits2int = CURVE.bits2int ||
function (bytes) {
const num = ut.bytesToNumberBE(bytes);
const delta = bytes.length * 8 - CURVE.nBitLength;
return delta > 0 ? num >> BigInt(delta) : num;
};
const bits2int_modN = CURVE.bits2int_modN ||
function (bytes) {
return modN(bits2int(bytes));
};
const ORDER_MASK = ut.bitMask(CURVE.nBitLength);
function int2octets(num) {
if (typeof num !== 'bigint')
throw new Error('bigint expected');
if (!(_0n <= num && num < ORDER_MASK))
throw new Error(`bigint expected < 2^${CURVE.nBitLength}`);
return ut.numberToBytesBE(num, CURVE.nByteLength);
}
function prepSig(msgHash, privateKey, opts = defaultSigOpts) {
if (['recovered', 'canonical'].some((k) => k in opts))
throw new Error('sign() legacy options not supported');
const { hash, randomBytes } = CURVE;
let { lowS, prehash, extraEntropy: ent } = opts;
if (lowS == null)
lowS = true;
msgHash = (0, utils_1.ensureBytes)('msgHash', msgHash);
if (prehash)
msgHash = (0, utils_1.ensureBytes)('prehashed msgHash', hash(msgHash));
const h1int = bits2int_modN(msgHash);
const d = normPrivateKeyToScalar(privateKey);
const seedArgs = [int2octets(d), int2octets(h1int)];
if (ent != null) {
const e = ent === true ? randomBytes(Fp.BYTES) : ent;
seedArgs.push((0, utils_1.ensureBytes)('extraEntropy', e, Fp.BYTES));
}
const seed = ut.concatBytes(...seedArgs);
const m = h1int;
function k2sig(kBytes) {
const k = bits2int(kBytes);
if (!isWithinCurveOrder(k))
return;
const ik = invN(k);
const q = Point.BASE.multiply(k).toAffine();
const r = modN(q.x);
if (r === _0n)
return;
const s = modN(ik * modN(m + r * d));
if (s === _0n)
return;
let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n);
let normS = s;
if (lowS && isBiggerThanHalfOrder(s)) {
normS = normalizeS(s);
recovery ^= 1;
}
return new Signature(r, normS, recovery);
}
return { seed, k2sig };
}
const defaultSigOpts = { lowS: CURVE.lowS, prehash: false };
const defaultVerOpts = { lowS: CURVE.lowS, prehash: false };
function sign(msgHash, privKey, opts = defaultSigOpts) {
const { seed, k2sig } = prepSig(msgHash, privKey, opts);
const C = CURVE;
const drbg = ut.createHmacDrbg(C.hash.outputLen, C.nByteLength, C.hmac);
return drbg(seed, k2sig);
}
Point.BASE._setWindowSize(8);
function verify(signature, msgHash, publicKey, opts = defaultVerOpts) {
const sg = signature;
msgHash = (0, utils_1.ensureBytes)('msgHash', msgHash);
publicKey = (0, utils_1.ensureBytes)('publicKey', publicKey);
if ('strict' in opts)
throw new Error('options.strict was renamed to lowS');
const { lowS, prehash } = opts;
let _sig = undefined;
let P;
try {
if (typeof sg === 'string' || sg instanceof Uint8Array) {
try {
_sig = Signature.fromDER(sg);
}
catch (derError) {
if (!(derError instanceof exports.DER.Err))
throw derError;
_sig = Signature.fromCompact(sg);
}
}
else if (typeof sg === 'object' && typeof sg.r === 'bigint' && typeof sg.s === 'bigint') {
const { r, s } = sg;
_sig = new Signature(r, s);
}
else {
throw new Error('PARSE');
}
P = Point.fromHex(publicKey);
}
catch (error) {
if (error.message === 'PARSE')
throw new Error(`signature must be Signature instance, Uint8Array or hex string`);
return false;
}
if (lowS && _sig.hasHighS())
return false;
if (prehash)
msgHash = CURVE.hash(msgHash);
const { r, s } = _sig;
const h = bits2int_modN(msgHash);
const is = invN(s);
const u1 = modN(h * is);
const u2 = modN(r * is);
const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2)?.toAffine();
if (!R)
return false;
const v = modN(R.x);
return v === r;
}
return {
CURVE,
getPublicKey,
getSharedSecret,
sign,
verify,
ProjectivePoint: Point,
Signature,
utils,
};
}
exports.weierstrass = weierstrass;
function SWUFpSqrtRatio(Fp, Z) {
const q = Fp.ORDER;
let l = _0n;
for (let o = q - _1n; o % _2n === _0n; o /= _2n)
l += _1n;
const c1 = l;
const _2n_pow_c1_1 = _2n << (c1 - _1n - _1n);
const _2n_pow_c1 = _2n_pow_c1_1 * _2n;
const c2 = (q - _1n) / _2n_pow_c1;
const c3 = (c2 - _1n) / _2n;
const c4 = _2n_pow_c1 - _1n;
const c5 = _2n_pow_c1_1;
const c6 = Fp.pow(Z, c2);
const c7 = Fp.pow(Z, (c2 + _1n) / _2n);
let sqrtRatio = (u, v) => {
let tv1 = c6;
let tv2 = Fp.pow(v, c4);
let tv3 = Fp.sqr(tv2);
tv3 = Fp.mul(tv3, v);
let tv5 = Fp.mul(u, tv3);
tv5 = Fp.pow(tv5, c3);
tv5 = Fp.mul(tv5, tv2);
tv2 = Fp.mul(tv5, v);
tv3 = Fp.mul(tv5, u);
let tv4 = Fp.mul(tv3, tv2);
tv5 = Fp.pow(tv4, c5);
let isQR = Fp.eql(tv5, Fp.ONE);
tv2 = Fp.mul(tv3, c7);
tv5 = Fp.mul(tv4, tv1);
tv3 = Fp.cmov(tv2, tv3, isQR);
tv4 = Fp.cmov(tv5, tv4, isQR);
for (let i = c1; i > _1n; i--) {
let tv5 = i - _2n;
tv5 = _2n << (tv5 - _1n);
let tvv5 = Fp.pow(tv4, tv5);
const e1 = Fp.eql(tvv5, Fp.ONE);
tv2 = Fp.mul(tv3, tv1);
tv1 = Fp.mul(tv1, tv1);
tvv5 = Fp.mul(tv4, tv1);
tv3 = Fp.cmov(tv2, tv3, e1);
tv4 = Fp.cmov(tvv5, tv4, e1);
}
return { isValid: isQR, value: tv3 };
};
if (Fp.ORDER % _4n === _3n) {
const c1 = (Fp.ORDER - _3n) / _4n;
const c2 = Fp.sqrt(Fp.neg(Z));
sqrtRatio = (u, v) => {
let tv1 = Fp.sqr(v);
const tv2 = Fp.mul(u, v);
tv1 = Fp.mul(tv1, tv2);
let y1 = Fp.pow(tv1, c1);
y1 = Fp.mul(y1, tv2);
const y2 = Fp.mul(y1, c2);
const tv3 = Fp.mul(Fp.sqr(y1), v);
const isQR = Fp.eql(tv3, u);
let y = Fp.cmov(y2, y1, isQR);
return { isValid: isQR, value: y };
};
}
return sqrtRatio;
}
exports.SWUFpSqrtRatio = SWUFpSqrtRatio;
function mapToCurveSimpleSWU(Fp, opts) {
mod.validateField(Fp);
if (!Fp.isValid(opts.A) || !Fp.isValid(opts.B) || !Fp.isValid(opts.Z))
throw new Error('mapToCurveSimpleSWU: invalid opts');
const sqrtRatio = SWUFpSqrtRatio(Fp, opts.Z);
if (!Fp.isOdd)
throw new Error('Fp.isOdd is not implemented!');
return (u) => {
let tv1, tv2, tv3, tv4, tv5, tv6, x, y;
tv1 = Fp.sqr(u);
tv1 = Fp.mul(tv1, opts.Z);
tv2 = Fp.sqr(tv1);
tv2 = Fp.add(tv2, tv1);
tv3 = Fp.add(tv2, Fp.ONE);
tv3 = Fp.mul(tv3, opts.B);
tv4 = Fp.cmov(opts.Z, Fp.neg(tv2), !Fp.eql(tv2, Fp.ZERO));
tv4 = Fp.mul(tv4, opts.A);
tv2 = Fp.sqr(tv3);
tv6 = Fp.sqr(tv4);
tv5 = Fp.mul(tv6, opts.A);
tv2 = Fp.add(tv2, tv5);
tv2 = Fp.mul(tv2, tv3);
tv6 = Fp.mul(tv6, tv4);
tv5 = Fp.mul(tv6, opts.B);
tv2 = Fp.add(tv2, tv5);
x = Fp.mul(tv1, tv3);
const { isValid, value } = sqrtRatio(tv2, tv6);
y = Fp.mul(tv1, u);
y = Fp.mul(y, value);
x = Fp.cmov(x, tv3, isValid);
y = Fp.cmov(y, value, isValid);
const e1 = Fp.isOdd(u) === Fp.isOdd(y);
y = Fp.cmov(Fp.neg(y), y, e1);
x = Fp.div(x, tv4);
return { x, y };
};
}
exports.mapToCurveSimpleSWU = mapToCurveSimpleSWU;
//# sourceMappingURL=weierstrass.js.map