UNPKG

@okxweb3/crypto-lib

Version:

A base package for @okxweb3/coin-*

870 lines 32.5 kB
"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