From ff5b231e31a2785fdce0e5e55b380a3b303aac64 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Sat, 20 May 2023 10:47:42 +0200 Subject: [PATCH] secp256k1 & other implementations: reduce bundle size by 20% by using PURE. PURE annotation helps bundlers during tree-shaking and eliminates dead code. * secp256k1: 75.4kb => 62.3kb * ed25519: 67.5kb => 51.1kb * ed448: 55.1kb => 44.0kb * p256: 67.8kb => 59.8kb * p384: 75.4kb => 67.4kb * p521: 75.8kb => 67.8kb --- src/ed25519.ts | 115 ++++++++++++++++++++++++----------------------- src/ed448.ts | 63 +++++++++++++------------- src/p256.ts | 27 ++++++----- src/p384.ts | 25 +++++------ src/p521.ts | 25 +++++------ src/secp256k1.ts | 115 ++++++++++++++++++++++++----------------------- 6 files changed, 190 insertions(+), 180 deletions(-) diff --git a/src/ed25519.ts b/src/ed25519.ts index 48c6807..da610dc 100644 --- a/src/ed25519.ts +++ b/src/ed25519.ts @@ -12,7 +12,7 @@ import { Hex, numberToBytesLE, } from './abstract/utils.js'; -import * as htf from './abstract/hash-to-curve.js'; +import { createHasher, htfBasicOpts, expand_message_xmd } from './abstract/hash-to-curve.js'; import { AffinePoint } from './abstract/curve.js'; /** @@ -142,21 +142,22 @@ export const ed25519ph = twistedEdwards({ prehash: sha512, }); -export const x25519 = montgomery({ - P: ED25519_P, - a: BigInt(486662), - montgomeryBits: 255, // n is 253 bits - nByteLength: 32, - Gu: BigInt(9), - powPminus2: (x: bigint): bigint => { - const P = ED25519_P; - // x^(p-2) aka x^(2^255-21) - const { pow_p_5_8, b2 } = ed25519_pow_2_252_3(x); - return mod(pow2(pow_p_5_8, BigInt(3), P) * b2, P); - }, - adjustScalarBytes, - randomBytes, -}); +export const x25519 = /* @__PURE__ */ (() => + montgomery({ + P: ED25519_P, + a: BigInt(486662), + montgomeryBits: 255, // n is 253 bits + nByteLength: 32, + Gu: BigInt(9), + powPminus2: (x: bigint): bigint => { + const P = ED25519_P; + // x^(p-2) aka x^(2^255-21) + const { pow_p_5_8, b2 } = ed25519_pow_2_252_3(x); + return mod(pow2(pow_p_5_8, BigInt(3), P) * b2, P); + }, + adjustScalarBytes, + randomBytes, + }))(); /** * Converts ed25519 public key to x25519 public key. Uses formula: @@ -260,29 +261,29 @@ function map_to_curve_elligator2_edwards25519(u: bigint) { return { x: Fp.mul(xn, inv[0]), y: Fp.mul(yn, inv[1]) }; // 13. return (xn, xd, yn, yd) } -const { hashToCurve, encodeToCurve } = htf.createHasher( - ed25519.ExtendedPoint, - (scalars: bigint[]) => map_to_curve_elligator2_edwards25519(scalars[0]), - { - DST: 'edwards25519_XMD:SHA-512_ELL2_RO_', - encodeDST: 'edwards25519_XMD:SHA-512_ELL2_NU_', - p: Fp.ORDER, - m: 1, - k: 128, - expand: 'xmd', - hash: sha512, - } -); -export { hashToCurve, encodeToCurve }; +const htf = /* @__PURE__ */ (() => + createHasher( + ed25519.ExtendedPoint, + (scalars: bigint[]) => map_to_curve_elligator2_edwards25519(scalars[0]), + { + DST: 'edwards25519_XMD:SHA-512_ELL2_RO_', + encodeDST: 'edwards25519_XMD:SHA-512_ELL2_NU_', + p: Fp.ORDER, + m: 1, + k: 128, + expand: 'xmd', + hash: sha512, + } + ))(); +export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)(); +export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)(); function assertRstPoint(other: unknown) { - if (!(other instanceof RistrettoPoint)) throw new Error('RistrettoPoint expected'); + if (!(other instanceof RistPoint)) throw new Error('RistrettoPoint expected'); } // √(-1) aka √(a) aka 2^((p-1)/4) -const SQRT_M1 = BigInt( - '19681161376707505956807079304988542015446066515923890162744021073123829784752' -); +const SQRT_M1 = ED25519_SQRT_M1; // √(ad - 1) const SQRT_AD_MINUS_ONE = BigInt( '25063068953384623474111414158702152701244531502492656460079210482610430750235' @@ -339,16 +340,15 @@ function calcElligatorRistrettoMap(r0: bigint): ExtendedPoint { * but it should work in its own namespace: do not combine those two. * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 */ -export class RistrettoPoint { - static BASE = new RistrettoPoint(ed25519.ExtendedPoint.BASE); - static ZERO = new RistrettoPoint(ed25519.ExtendedPoint.ZERO); - +class RistPoint { + static BASE: RistPoint; + static ZERO: RistPoint; // Private property to discourage combining ExtendedPoint + RistrettoPoint // Always use Ristretto encoding/decoding instead. constructor(private readonly ep: ExtendedPoint) {} static fromAffine(ap: AffinePoint) { - return new RistrettoPoint(ed25519.ExtendedPoint.fromAffine(ap)); + return new RistPoint(ed25519.ExtendedPoint.fromAffine(ap)); } /** @@ -358,13 +358,13 @@ export class RistrettoPoint { * https://ristretto.group/formulas/elligator.html * @param hex 64-byte output of a hash function */ - static hashToCurve(hex: Hex): RistrettoPoint { + static hashToCurve(hex: Hex): RistPoint { hex = ensureBytes('ristrettoHash', hex, 64); const r1 = bytes255ToNumberLE(hex.slice(0, 32)); const R1 = calcElligatorRistrettoMap(r1); const r2 = bytes255ToNumberLE(hex.slice(32, 64)); const R2 = calcElligatorRistrettoMap(r2); - return new RistrettoPoint(R1.add(R2)); + return new RistPoint(R1.add(R2)); } /** @@ -372,7 +372,7 @@ export class RistrettoPoint { * https://ristretto.group/formulas/decoding.html * @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding */ - static fromHex(hex: Hex): RistrettoPoint { + static fromHex(hex: Hex): RistPoint { hex = ensureBytes('ristrettoHex', hex, 32); const { a, d } = ed25519.CURVE; const P = ed25519.CURVE.Fp.ORDER; @@ -396,7 +396,7 @@ export class RistrettoPoint { const y = mod(u1 * Dy); // 11 const t = mod(x * y); // 12 if (!isValid || isNegativeLE(t, P) || y === _0n) throw new Error(emsg); - return new RistrettoPoint(new ed25519.ExtendedPoint(x, y, _1n, t)); + return new RistPoint(new ed25519.ExtendedPoint(x, y, _1n, t)); } /** @@ -440,7 +440,7 @@ export class RistrettoPoint { } // Compare one point to another. - equals(other: RistrettoPoint): boolean { + equals(other: RistPoint): boolean { assertRstPoint(other); const { ex: X1, ey: Y1 } = this.ep; const { ex: X2, ey: Y2 } = other.ep; @@ -451,31 +451,36 @@ export class RistrettoPoint { return one || two; } - add(other: RistrettoPoint): RistrettoPoint { + add(other: RistPoint): RistPoint { assertRstPoint(other); - return new RistrettoPoint(this.ep.add(other.ep)); + return new RistPoint(this.ep.add(other.ep)); } - subtract(other: RistrettoPoint): RistrettoPoint { + subtract(other: RistPoint): RistPoint { assertRstPoint(other); - return new RistrettoPoint(this.ep.subtract(other.ep)); + return new RistPoint(this.ep.subtract(other.ep)); } - multiply(scalar: bigint): RistrettoPoint { - return new RistrettoPoint(this.ep.multiply(scalar)); + multiply(scalar: bigint): RistPoint { + return new RistPoint(this.ep.multiply(scalar)); } - multiplyUnsafe(scalar: bigint): RistrettoPoint { - return new RistrettoPoint(this.ep.multiplyUnsafe(scalar)); + multiplyUnsafe(scalar: bigint): RistPoint { + return new RistPoint(this.ep.multiplyUnsafe(scalar)); } } +export const RistrettoPoint = /* @__PURE__ */ (() => { + if (!RistPoint.BASE) RistPoint.BASE = new RistPoint(ed25519.ExtendedPoint.BASE); + if (!RistPoint.ZERO) RistPoint.ZERO = new RistPoint(ed25519.ExtendedPoint.ZERO); + return RistPoint; +})(); // https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/14/ // Appendix B. Hashing to ristretto255 -export const hash_to_ristretto255 = (msg: Uint8Array, options: htf.htfBasicOpts) => { +export const hash_to_ristretto255 = (msg: Uint8Array, options: htfBasicOpts) => { const d = options.DST; const DST = typeof d === 'string' ? utf8ToBytes(d) : d; - const uniform_bytes = htf.expand_message_xmd(msg, DST, 64, sha512); - const P = RistrettoPoint.hashToCurve(uniform_bytes); + const uniform_bytes = expand_message_xmd(msg, DST, 64, sha512); + const P = RistPoint.hashToCurve(uniform_bytes); return P; }; diff --git a/src/ed448.ts b/src/ed448.ts index bfc04e1..b0cf63e 100644 --- a/src/ed448.ts +++ b/src/ed448.ts @@ -4,7 +4,7 @@ import { concatBytes, randomBytes, utf8ToBytes, wrapConstructor } from '@noble/h import { twistedEdwards } from './abstract/edwards.js'; import { mod, pow2, Field } from './abstract/modular.js'; import { montgomery } from './abstract/montgomery.js'; -import * as htf from './abstract/hash-to-curve.js'; +import { createHasher } from './abstract/hash-to-curve.js'; /** * Edwards448 (not Ed448-Goldilocks) curve with following addons: @@ -122,21 +122,22 @@ export const ed448 = twistedEdwards(ED448_DEF); // NOTE: there is no ed448ctx, since ed448 supports ctx by default export const ed448ph = twistedEdwards({ ...ED448_DEF, prehash: shake256_64 }); -export const x448 = montgomery({ - a: BigInt(156326), - montgomeryBits: 448, - nByteLength: 57, - P: ed448P, - Gu: BigInt(5), - powPminus2: (x: bigint): bigint => { - const P = ed448P; - const Pminus3div4 = ed448_pow_Pminus3div4(x); - const Pminus3 = pow2(Pminus3div4, BigInt(2), P); - return mod(Pminus3 * x, P); // Pminus3 * x = Pminus2 - }, - adjustScalarBytes, - randomBytes, -}); +export const x448 = /* @__PURE__ */ (() => + montgomery({ + a: BigInt(156326), + montgomeryBits: 448, + nByteLength: 57, + P: ed448P, + Gu: BigInt(5), + powPminus2: (x: bigint): bigint => { + const P = ed448P; + const Pminus3div4 = ed448_pow_Pminus3div4(x); + const Pminus3 = pow2(Pminus3div4, BigInt(2), P); + return mod(Pminus3 * x, P); // Pminus3 * x = Pminus2 + }, + adjustScalarBytes, + randomBytes, + }))(); /** * Converts edwards448 public key to x448 public key. Uses formula: @@ -228,17 +229,19 @@ function map_to_curve_elligator2_edwards448(u: bigint) { return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) }; // 38. return (xEn, xEd, yEn, yEd) } -const { hashToCurve, encodeToCurve } = htf.createHasher( - ed448.ExtendedPoint, - (scalars: bigint[]) => map_to_curve_elligator2_edwards448(scalars[0]), - { - DST: 'edwards448_XOF:SHAKE256_ELL2_RO_', - encodeDST: 'edwards448_XOF:SHAKE256_ELL2_NU_', - p: Fp.ORDER, - m: 1, - k: 224, - expand: 'xof', - hash: shake256, - } -); -export { hashToCurve, encodeToCurve }; +const htf = /* @__PURE__ */ (() => + createHasher( + ed448.ExtendedPoint, + (scalars: bigint[]) => map_to_curve_elligator2_edwards448(scalars[0]), + { + DST: 'edwards448_XOF:SHAKE256_ELL2_RO_', + encodeDST: 'edwards448_XOF:SHAKE256_ELL2_NU_', + p: Fp.ORDER, + m: 1, + k: 224, + expand: 'xof', + hash: shake256, + } + ))(); +export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)(); +export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)(); diff --git a/src/p256.ts b/src/p256.ts index b124420..164c470 100644 --- a/src/p256.ts +++ b/src/p256.ts @@ -3,7 +3,7 @@ import { createCurve } from './_shortw_utils.js'; import { sha256 } from '@noble/hashes/sha256'; import { Field } from './abstract/modular.js'; import { mapToCurveSimpleSWU } from './abstract/weierstrass.js'; -import * as htf from './abstract/hash-to-curve.js'; +import { createHasher } from './abstract/hash-to-curve.js'; // NIST secp256r1 aka p256 // https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-256 @@ -12,12 +12,6 @@ const Fp = Field(BigInt('0xffffffff00000001000000000000000000000000fffffffffffff const CURVE_A = Fp.create(BigInt('-3')); const CURVE_B = BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b'); -const mapSWU = mapToCurveSimpleSWU(Fp, { - A: CURVE_A, - B: CURVE_B, - Z: Fp.create(BigInt('-10')), -}); - // prettier-ignore export const p256 = createCurve({ a: CURVE_A, // Equation params: a, b @@ -33,10 +27,15 @@ export const p256 = createCurve({ } as const, sha256); export const secp256r1 = p256; -const { hashToCurve, encodeToCurve } = htf.createHasher( - secp256r1.ProjectivePoint, - (scalars: bigint[]) => mapSWU(scalars[0]), - { +const mapSWU = /* @__PURE__ */ (() => + mapToCurveSimpleSWU(Fp, { + A: CURVE_A, + B: CURVE_B, + Z: Fp.create(BigInt('-10')), + }))(); + +const htf = /* @__PURE__ */ (() => + createHasher(secp256r1.ProjectivePoint, (scalars: bigint[]) => mapSWU(scalars[0]), { DST: 'P256_XMD:SHA-256_SSWU_RO_', encodeDST: 'P256_XMD:SHA-256_SSWU_NU_', p: Fp.ORDER, @@ -44,6 +43,6 @@ const { hashToCurve, encodeToCurve } = htf.createHasher( k: 128, expand: 'xmd', hash: sha256, - } -); -export { hashToCurve, encodeToCurve }; + }))(); +export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)(); +export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)(); diff --git a/src/p384.ts b/src/p384.ts index c70184f..436de9b 100644 --- a/src/p384.ts +++ b/src/p384.ts @@ -3,7 +3,7 @@ import { createCurve } from './_shortw_utils.js'; import { sha384 } from '@noble/hashes/sha512'; import { Field } from './abstract/modular.js'; import { mapToCurveSimpleSWU } from './abstract/weierstrass.js'; -import * as htf from './abstract/hash-to-curve.js'; +import { createHasher } from './abstract/hash-to-curve.js'; // NIST secp384r1 aka p384 // https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-384 @@ -31,16 +31,15 @@ export const p384 = createCurve({ } as const, sha384); export const secp384r1 = p384; -const mapSWU = mapToCurveSimpleSWU(Fp, { - A: CURVE_A, - B: CURVE_B, - Z: Fp.create(BigInt('-12')), -}); +const mapSWU = /* @__PURE__ */ (() => + mapToCurveSimpleSWU(Fp, { + A: CURVE_A, + B: CURVE_B, + Z: Fp.create(BigInt('-12')), + }))(); -const { hashToCurve, encodeToCurve } = htf.createHasher( - secp384r1.ProjectivePoint, - (scalars: bigint[]) => mapSWU(scalars[0]), - { +const htf = /* @__PURE__ */ (() => + createHasher(secp384r1.ProjectivePoint, (scalars: bigint[]) => mapSWU(scalars[0]), { DST: 'P384_XMD:SHA-384_SSWU_RO_', encodeDST: 'P384_XMD:SHA-384_SSWU_NU_', p: Fp.ORDER, @@ -48,6 +47,6 @@ const { hashToCurve, encodeToCurve } = htf.createHasher( k: 192, expand: 'xmd', hash: sha384, - } -); -export { hashToCurve, encodeToCurve }; + }))(); +export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)(); +export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)(); diff --git a/src/p521.ts b/src/p521.ts index 0bed62b..cc9fbbc 100644 --- a/src/p521.ts +++ b/src/p521.ts @@ -3,7 +3,7 @@ import { createCurve } from './_shortw_utils.js'; import { sha512 } from '@noble/hashes/sha512'; import { Field } from './abstract/modular.js'; import { mapToCurveSimpleSWU } from './abstract/weierstrass.js'; -import * as htf from './abstract/hash-to-curve.js'; +import { createHasher } from './abstract/hash-to-curve.js'; // NIST secp521r1 aka p521 // Note that it's 521, which differs from 512 of its hash function. @@ -47,16 +47,15 @@ export const p521 = createCurve({ } as const, sha512); export const secp521r1 = p521; -const mapSWU = mapToCurveSimpleSWU(Fp, { - A: CURVE.a, - B: CURVE.b, - Z: Fp.create(BigInt('-4')), -}); +const mapSWU = /* @__PURE__ */ (() => + mapToCurveSimpleSWU(Fp, { + A: CURVE.a, + B: CURVE.b, + Z: Fp.create(BigInt('-4')), + }))(); -const { hashToCurve, encodeToCurve } = htf.createHasher( - secp521r1.ProjectivePoint, - (scalars: bigint[]) => mapSWU(scalars[0]), - { +const htf = /* @__PURE__ */ (() => + createHasher(secp521r1.ProjectivePoint, (scalars: bigint[]) => mapSWU(scalars[0]), { DST: 'P521_XMD:SHA-512_SSWU_RO_', encodeDST: 'P521_XMD:SHA-512_SSWU_NU_', p: Fp.ORDER, @@ -64,6 +63,6 @@ const { hashToCurve, encodeToCurve } = htf.createHasher( k: 256, expand: 'xmd', hash: sha512, - } -); -export { hashToCurve, encodeToCurve }; + }))(); +export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)(); +export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)(); diff --git a/src/secp256k1.ts b/src/secp256k1.ts index c2256b5..7119222 100644 --- a/src/secp256k1.ts +++ b/src/secp256k1.ts @@ -5,7 +5,7 @@ import { Field, mod, pow2 } from './abstract/modular.js'; import { ProjPointType as PointType, mapToCurveSimpleSWU } from './abstract/weierstrass.js'; import type { Hex, PrivKey } from './abstract/utils.js'; import { bytesToNumberBE, concatBytes, ensureBytes, numberToBytesBE } from './abstract/utils.js'; -import * as htf from './abstract/hash-to-curve.js'; +import { createHasher, isogenyMap } from './abstract/hash-to-curve.js'; import { createCurve } from './_shortw_utils.js'; const secp256k1P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'); @@ -199,7 +199,7 @@ function schnorrVerify(signature: Hex, message: Hex, publicKey: Hex): boolean { } } -export const schnorr = { +export const schnorr = /* @__PURE__ */ (() => ({ getPublicKey: schnorrGetPublicKey, sign: schnorrSign, verify: schnorrVerify, @@ -212,58 +212,63 @@ export const schnorr = { taggedHash, mod, }, -}; +}))(); -const isoMap = htf.isogenyMap( - Fp, - [ - // xNum +const isoMap = /* @__PURE__ */ (() => + isogenyMap( + Fp, [ - '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7', - '0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581', - '0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262', - '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c', - ], - // xDen - [ - '0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b', - '0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14', - '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 - ], - // yNum - [ - '0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c', - '0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3', - '0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931', - '0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84', - ], - // yDen - [ - '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b', - '0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573', - '0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f', - '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 - ], - ].map((i) => i.map((j) => BigInt(j))) as [bigint[], bigint[], bigint[], bigint[]] -); -const mapSWU = mapToCurveSimpleSWU(Fp, { - A: BigInt('0x3f8731abdd661adca08a5558f0f5d272e953d363cb6f0e5d405447c01a444533'), - B: BigInt('1771'), - Z: Fp.create(BigInt('-11')), -}); -export const { hashToCurve, encodeToCurve } = htf.createHasher( - secp256k1.ProjectivePoint, - (scalars: bigint[]) => { - const { x, y } = mapSWU(Fp.create(scalars[0])); - return isoMap(x, y); - }, - { - DST: 'secp256k1_XMD:SHA-256_SSWU_RO_', - encodeDST: 'secp256k1_XMD:SHA-256_SSWU_NU_', - p: Fp.ORDER, - m: 1, - k: 128, - expand: 'xmd', - hash: sha256, - } -); + // xNum + [ + '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7', + '0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581', + '0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262', + '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c', + ], + // xDen + [ + '0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b', + '0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14', + '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + // yNum + [ + '0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c', + '0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3', + '0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931', + '0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84', + ], + // yDen + [ + '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b', + '0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573', + '0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f', + '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + ].map((i) => i.map((j) => BigInt(j))) as [bigint[], bigint[], bigint[], bigint[]] + ))(); +const mapSWU = /* @__PURE__ */ (() => + mapToCurveSimpleSWU(Fp, { + A: BigInt('0x3f8731abdd661adca08a5558f0f5d272e953d363cb6f0e5d405447c01a444533'), + B: BigInt('1771'), + Z: Fp.create(BigInt('-11')), + }))(); +const htf = /* @__PURE__ */ (() => + createHasher( + secp256k1.ProjectivePoint, + (scalars: bigint[]) => { + const { x, y } = mapSWU(Fp.create(scalars[0])); + return isoMap(x, y); + }, + { + DST: 'secp256k1_XMD:SHA-256_SSWU_RO_', + encodeDST: 'secp256k1_XMD:SHA-256_SSWU_NU_', + p: Fp.ORDER, + m: 1, + k: 128, + expand: 'xmd', + hash: sha256, + } + ))(); +export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)(); +export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)();