weierstrass.js 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062
  1. /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
  2. // Short Weierstrass curve. The formula is: y² = x³ + ax + b
  3. import { validateBasic, wNAF } from './curve.js';
  4. import * as mod from './modular.js';
  5. import * as ut from './utils.js';
  6. import { ensureBytes } from './utils.js';
  7. function validatePointOpts(curve) {
  8. const opts = validateBasic(curve);
  9. ut.validateObject(opts, {
  10. a: 'field',
  11. b: 'field',
  12. }, {
  13. allowedPrivateKeyLengths: 'array',
  14. wrapPrivateKey: 'boolean',
  15. isTorsionFree: 'function',
  16. clearCofactor: 'function',
  17. allowInfinityPoint: 'boolean',
  18. fromBytes: 'function',
  19. toBytes: 'function',
  20. });
  21. const { endo, Fp, a } = opts;
  22. if (endo) {
  23. if (!Fp.eql(a, Fp.ZERO)) {
  24. throw new Error('Endomorphism can only be defined for Koblitz curves that have a=0');
  25. }
  26. if (typeof endo !== 'object' ||
  27. typeof endo.beta !== 'bigint' ||
  28. typeof endo.splitScalar !== 'function') {
  29. throw new Error('Expected endomorphism with beta: bigint and splitScalar: function');
  30. }
  31. }
  32. return Object.freeze({ ...opts });
  33. }
  34. // ASN.1 DER encoding utilities
  35. const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut;
  36. export const DER = {
  37. // asn.1 DER encoding utils
  38. Err: class DERErr extends Error {
  39. constructor(m = '') {
  40. super(m);
  41. }
  42. },
  43. _parseInt(data) {
  44. const { Err: E } = DER;
  45. if (data.length < 2 || data[0] !== 0x02)
  46. throw new E('Invalid signature integer tag');
  47. const len = data[1];
  48. const res = data.subarray(2, len + 2);
  49. if (!len || res.length !== len)
  50. throw new E('Invalid signature integer: wrong length');
  51. // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag,
  52. // since we always use positive integers here. It must always be empty:
  53. // - add zero byte if exists
  54. // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding)
  55. if (res[0] & 0b10000000)
  56. throw new E('Invalid signature integer: negative');
  57. if (res[0] === 0x00 && !(res[1] & 0b10000000))
  58. throw new E('Invalid signature integer: unnecessary leading zero');
  59. return { d: b2n(res), l: data.subarray(len + 2) }; // d is data, l is left
  60. },
  61. toSig(hex) {
  62. // parse DER signature
  63. const { Err: E } = DER;
  64. const data = typeof hex === 'string' ? h2b(hex) : hex;
  65. ut.abytes(data);
  66. let l = data.length;
  67. if (l < 2 || data[0] != 0x30)
  68. throw new E('Invalid signature tag');
  69. if (data[1] !== l - 2)
  70. throw new E('Invalid signature: incorrect length');
  71. const { d: r, l: sBytes } = DER._parseInt(data.subarray(2));
  72. const { d: s, l: rBytesLeft } = DER._parseInt(sBytes);
  73. if (rBytesLeft.length)
  74. throw new E('Invalid signature: left bytes after parsing');
  75. return { r, s };
  76. },
  77. hexFromSig(sig) {
  78. // Add leading zero if first byte has negative bit enabled. More details in '_parseInt'
  79. const slice = (s) => (Number.parseInt(s[0], 16) & 0b1000 ? '00' + s : s);
  80. const h = (num) => {
  81. const hex = num.toString(16);
  82. return hex.length & 1 ? `0${hex}` : hex;
  83. };
  84. const s = slice(h(sig.s));
  85. const r = slice(h(sig.r));
  86. const shl = s.length / 2;
  87. const rhl = r.length / 2;
  88. const sl = h(shl);
  89. const rl = h(rhl);
  90. return `30${h(rhl + shl + 4)}02${rl}${r}02${sl}${s}`;
  91. },
  92. };
  93. // Be friendly to bad ECMAScript parsers by not using bigint literals
  94. // prettier-ignore
  95. const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);
  96. export function weierstrassPoints(opts) {
  97. const CURVE = validatePointOpts(opts);
  98. const { Fp } = CURVE; // All curves has same field / group length as for now, but they can differ
  99. const toBytes = CURVE.toBytes ||
  100. ((_c, point, _isCompressed) => {
  101. const a = point.toAffine();
  102. return ut.concatBytes(Uint8Array.from([0x04]), Fp.toBytes(a.x), Fp.toBytes(a.y));
  103. });
  104. const fromBytes = CURVE.fromBytes ||
  105. ((bytes) => {
  106. // const head = bytes[0];
  107. const tail = bytes.subarray(1);
  108. // if (head !== 0x04) throw new Error('Only non-compressed encoding is supported');
  109. const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES));
  110. const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES));
  111. return { x, y };
  112. });
  113. /**
  114. * y² = x³ + ax + b: Short weierstrass curve formula
  115. * @returns y²
  116. */
  117. function weierstrassEquation(x) {
  118. const { a, b } = CURVE;
  119. const x2 = Fp.sqr(x); // x * x
  120. const x3 = Fp.mul(x2, x); // x2 * x
  121. return Fp.add(Fp.add(x3, Fp.mul(x, a)), b); // x3 + a * x + b
  122. }
  123. // Validate whether the passed curve params are valid.
  124. // We check if curve equation works for generator point.
  125. // `assertValidity()` won't work: `isTorsionFree()` is not available at this point in bls12-381.
  126. // ProjectivePoint class has not been initialized yet.
  127. if (!Fp.eql(Fp.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx)))
  128. throw new Error('bad generator point: equation left != right');
  129. // Valid group elements reside in range 1..n-1
  130. function isWithinCurveOrder(num) {
  131. return typeof num === 'bigint' && _0n < num && num < CURVE.n;
  132. }
  133. function assertGE(num) {
  134. if (!isWithinCurveOrder(num))
  135. throw new Error('Expected valid bigint: 0 < bigint < curve.n');
  136. }
  137. // Validates if priv key is valid and converts it to bigint.
  138. // Supports options allowedPrivateKeyLengths and wrapPrivateKey.
  139. function normPrivateKeyToScalar(key) {
  140. const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n } = CURVE;
  141. if (lengths && typeof key !== 'bigint') {
  142. if (ut.isBytes(key))
  143. key = ut.bytesToHex(key);
  144. // Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes
  145. if (typeof key !== 'string' || !lengths.includes(key.length))
  146. throw new Error('Invalid key');
  147. key = key.padStart(nByteLength * 2, '0');
  148. }
  149. let num;
  150. try {
  151. num =
  152. typeof key === 'bigint'
  153. ? key
  154. : ut.bytesToNumberBE(ensureBytes('private key', key, nByteLength));
  155. }
  156. catch (error) {
  157. throw new Error(`private key must be ${nByteLength} bytes, hex or bigint, not ${typeof key}`);
  158. }
  159. if (wrapPrivateKey)
  160. num = mod.mod(num, n); // disabled by default, enabled for BLS
  161. assertGE(num); // num in range [1..N-1]
  162. return num;
  163. }
  164. const pointPrecomputes = new Map();
  165. function assertPrjPoint(other) {
  166. if (!(other instanceof Point))
  167. throw new Error('ProjectivePoint expected');
  168. }
  169. /**
  170. * Projective Point works in 3d / projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z)
  171. * Default Point works in 2d / affine coordinates: (x, y)
  172. * We're doing calculations in projective, because its operations don't require costly inversion.
  173. */
  174. class Point {
  175. constructor(px, py, pz) {
  176. this.px = px;
  177. this.py = py;
  178. this.pz = pz;
  179. if (px == null || !Fp.isValid(px))
  180. throw new Error('x required');
  181. if (py == null || !Fp.isValid(py))
  182. throw new Error('y required');
  183. if (pz == null || !Fp.isValid(pz))
  184. throw new Error('z required');
  185. }
  186. // Does not validate if the point is on-curve.
  187. // Use fromHex instead, or call assertValidity() later.
  188. static fromAffine(p) {
  189. const { x, y } = p || {};
  190. if (!p || !Fp.isValid(x) || !Fp.isValid(y))
  191. throw new Error('invalid affine point');
  192. if (p instanceof Point)
  193. throw new Error('projective point not allowed');
  194. const is0 = (i) => Fp.eql(i, Fp.ZERO);
  195. // fromAffine(x:0, y:0) would produce (x:0, y:0, z:1), but we need (x:0, y:1, z:0)
  196. if (is0(x) && is0(y))
  197. return Point.ZERO;
  198. return new Point(x, y, Fp.ONE);
  199. }
  200. get x() {
  201. return this.toAffine().x;
  202. }
  203. get y() {
  204. return this.toAffine().y;
  205. }
  206. /**
  207. * Takes a bunch of Projective Points but executes only one
  208. * inversion on all of them. Inversion is very slow operation,
  209. * so this improves performance massively.
  210. * Optimization: converts a list of projective points to a list of identical points with Z=1.
  211. */
  212. static normalizeZ(points) {
  213. const toInv = Fp.invertBatch(points.map((p) => p.pz));
  214. return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine);
  215. }
  216. /**
  217. * Converts hash string or Uint8Array to Point.
  218. * @param hex short/long ECDSA hex
  219. */
  220. static fromHex(hex) {
  221. const P = Point.fromAffine(fromBytes(ensureBytes('pointHex', hex)));
  222. P.assertValidity();
  223. return P;
  224. }
  225. // Multiplies generator point by privateKey.
  226. static fromPrivateKey(privateKey) {
  227. return Point.BASE.multiply(normPrivateKeyToScalar(privateKey));
  228. }
  229. // "Private method", don't use it directly
  230. _setWindowSize(windowSize) {
  231. this._WINDOW_SIZE = windowSize;
  232. pointPrecomputes.delete(this);
  233. }
  234. // A point on curve is valid if it conforms to equation.
  235. assertValidity() {
  236. if (this.is0()) {
  237. // (0, 1, 0) aka ZERO is invalid in most contexts.
  238. // In BLS, ZERO can be serialized, so we allow it.
  239. // (0, 0, 0) is wrong representation of ZERO and is always invalid.
  240. if (CURVE.allowInfinityPoint && !Fp.is0(this.py))
  241. return;
  242. throw new Error('bad point: ZERO');
  243. }
  244. // Some 3rd-party test vectors require different wording between here & `fromCompressedHex`
  245. const { x, y } = this.toAffine();
  246. // Check if x, y are valid field elements
  247. if (!Fp.isValid(x) || !Fp.isValid(y))
  248. throw new Error('bad point: x or y not FE');
  249. const left = Fp.sqr(y); // y²
  250. const right = weierstrassEquation(x); // x³ + ax + b
  251. if (!Fp.eql(left, right))
  252. throw new Error('bad point: equation left != right');
  253. if (!this.isTorsionFree())
  254. throw new Error('bad point: not in prime-order subgroup');
  255. }
  256. hasEvenY() {
  257. const { y } = this.toAffine();
  258. if (Fp.isOdd)
  259. return !Fp.isOdd(y);
  260. throw new Error("Field doesn't support isOdd");
  261. }
  262. /**
  263. * Compare one point to another.
  264. */
  265. equals(other) {
  266. assertPrjPoint(other);
  267. const { px: X1, py: Y1, pz: Z1 } = this;
  268. const { px: X2, py: Y2, pz: Z2 } = other;
  269. const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1));
  270. const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1));
  271. return U1 && U2;
  272. }
  273. /**
  274. * Flips point to one corresponding to (x, -y) in Affine coordinates.
  275. */
  276. negate() {
  277. return new Point(this.px, Fp.neg(this.py), this.pz);
  278. }
  279. // Renes-Costello-Batina exception-free doubling formula.
  280. // There is 30% faster Jacobian formula, but it is not complete.
  281. // https://eprint.iacr.org/2015/1060, algorithm 3
  282. // Cost: 8M + 3S + 3*a + 2*b3 + 15add.
  283. double() {
  284. const { a, b } = CURVE;
  285. const b3 = Fp.mul(b, _3n);
  286. const { px: X1, py: Y1, pz: Z1 } = this;
  287. let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
  288. let t0 = Fp.mul(X1, X1); // step 1
  289. let t1 = Fp.mul(Y1, Y1);
  290. let t2 = Fp.mul(Z1, Z1);
  291. let t3 = Fp.mul(X1, Y1);
  292. t3 = Fp.add(t3, t3); // step 5
  293. Z3 = Fp.mul(X1, Z1);
  294. Z3 = Fp.add(Z3, Z3);
  295. X3 = Fp.mul(a, Z3);
  296. Y3 = Fp.mul(b3, t2);
  297. Y3 = Fp.add(X3, Y3); // step 10
  298. X3 = Fp.sub(t1, Y3);
  299. Y3 = Fp.add(t1, Y3);
  300. Y3 = Fp.mul(X3, Y3);
  301. X3 = Fp.mul(t3, X3);
  302. Z3 = Fp.mul(b3, Z3); // step 15
  303. t2 = Fp.mul(a, t2);
  304. t3 = Fp.sub(t0, t2);
  305. t3 = Fp.mul(a, t3);
  306. t3 = Fp.add(t3, Z3);
  307. Z3 = Fp.add(t0, t0); // step 20
  308. t0 = Fp.add(Z3, t0);
  309. t0 = Fp.add(t0, t2);
  310. t0 = Fp.mul(t0, t3);
  311. Y3 = Fp.add(Y3, t0);
  312. t2 = Fp.mul(Y1, Z1); // step 25
  313. t2 = Fp.add(t2, t2);
  314. t0 = Fp.mul(t2, t3);
  315. X3 = Fp.sub(X3, t0);
  316. Z3 = Fp.mul(t2, t1);
  317. Z3 = Fp.add(Z3, Z3); // step 30
  318. Z3 = Fp.add(Z3, Z3);
  319. return new Point(X3, Y3, Z3);
  320. }
  321. // Renes-Costello-Batina exception-free addition formula.
  322. // There is 30% faster Jacobian formula, but it is not complete.
  323. // https://eprint.iacr.org/2015/1060, algorithm 1
  324. // Cost: 12M + 0S + 3*a + 3*b3 + 23add.
  325. add(other) {
  326. assertPrjPoint(other);
  327. const { px: X1, py: Y1, pz: Z1 } = this;
  328. const { px: X2, py: Y2, pz: Z2 } = other;
  329. let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
  330. const a = CURVE.a;
  331. const b3 = Fp.mul(CURVE.b, _3n);
  332. let t0 = Fp.mul(X1, X2); // step 1
  333. let t1 = Fp.mul(Y1, Y2);
  334. let t2 = Fp.mul(Z1, Z2);
  335. let t3 = Fp.add(X1, Y1);
  336. let t4 = Fp.add(X2, Y2); // step 5
  337. t3 = Fp.mul(t3, t4);
  338. t4 = Fp.add(t0, t1);
  339. t3 = Fp.sub(t3, t4);
  340. t4 = Fp.add(X1, Z1);
  341. let t5 = Fp.add(X2, Z2); // step 10
  342. t4 = Fp.mul(t4, t5);
  343. t5 = Fp.add(t0, t2);
  344. t4 = Fp.sub(t4, t5);
  345. t5 = Fp.add(Y1, Z1);
  346. X3 = Fp.add(Y2, Z2); // step 15
  347. t5 = Fp.mul(t5, X3);
  348. X3 = Fp.add(t1, t2);
  349. t5 = Fp.sub(t5, X3);
  350. Z3 = Fp.mul(a, t4);
  351. X3 = Fp.mul(b3, t2); // step 20
  352. Z3 = Fp.add(X3, Z3);
  353. X3 = Fp.sub(t1, Z3);
  354. Z3 = Fp.add(t1, Z3);
  355. Y3 = Fp.mul(X3, Z3);
  356. t1 = Fp.add(t0, t0); // step 25
  357. t1 = Fp.add(t1, t0);
  358. t2 = Fp.mul(a, t2);
  359. t4 = Fp.mul(b3, t4);
  360. t1 = Fp.add(t1, t2);
  361. t2 = Fp.sub(t0, t2); // step 30
  362. t2 = Fp.mul(a, t2);
  363. t4 = Fp.add(t4, t2);
  364. t0 = Fp.mul(t1, t4);
  365. Y3 = Fp.add(Y3, t0);
  366. t0 = Fp.mul(t5, t4); // step 35
  367. X3 = Fp.mul(t3, X3);
  368. X3 = Fp.sub(X3, t0);
  369. t0 = Fp.mul(t3, t1);
  370. Z3 = Fp.mul(t5, Z3);
  371. Z3 = Fp.add(Z3, t0); // step 40
  372. return new Point(X3, Y3, Z3);
  373. }
  374. subtract(other) {
  375. return this.add(other.negate());
  376. }
  377. is0() {
  378. return this.equals(Point.ZERO);
  379. }
  380. wNAF(n) {
  381. return wnaf.wNAFCached(this, pointPrecomputes, n, (comp) => {
  382. const toInv = Fp.invertBatch(comp.map((p) => p.pz));
  383. return comp.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine);
  384. });
  385. }
  386. /**
  387. * Non-constant-time multiplication. Uses double-and-add algorithm.
  388. * It's faster, but should only be used when you don't care about
  389. * an exposed private key e.g. sig verification, which works over *public* keys.
  390. */
  391. multiplyUnsafe(n) {
  392. const I = Point.ZERO;
  393. if (n === _0n)
  394. return I;
  395. assertGE(n); // Will throw on 0
  396. if (n === _1n)
  397. return this;
  398. const { endo } = CURVE;
  399. if (!endo)
  400. return wnaf.unsafeLadder(this, n);
  401. // Apply endomorphism
  402. let { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);
  403. let k1p = I;
  404. let k2p = I;
  405. let d = this;
  406. while (k1 > _0n || k2 > _0n) {
  407. if (k1 & _1n)
  408. k1p = k1p.add(d);
  409. if (k2 & _1n)
  410. k2p = k2p.add(d);
  411. d = d.double();
  412. k1 >>= _1n;
  413. k2 >>= _1n;
  414. }
  415. if (k1neg)
  416. k1p = k1p.negate();
  417. if (k2neg)
  418. k2p = k2p.negate();
  419. k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
  420. return k1p.add(k2p);
  421. }
  422. /**
  423. * Constant time multiplication.
  424. * Uses wNAF method. Windowed method may be 10% faster,
  425. * but takes 2x longer to generate and consumes 2x memory.
  426. * Uses precomputes when available.
  427. * Uses endomorphism for Koblitz curves.
  428. * @param scalar by which the point would be multiplied
  429. * @returns New point
  430. */
  431. multiply(scalar) {
  432. assertGE(scalar);
  433. let n = scalar;
  434. let point, fake; // Fake point is used to const-time mult
  435. const { endo } = CURVE;
  436. if (endo) {
  437. const { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);
  438. let { p: k1p, f: f1p } = this.wNAF(k1);
  439. let { p: k2p, f: f2p } = this.wNAF(k2);
  440. k1p = wnaf.constTimeNegate(k1neg, k1p);
  441. k2p = wnaf.constTimeNegate(k2neg, k2p);
  442. k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
  443. point = k1p.add(k2p);
  444. fake = f1p.add(f2p);
  445. }
  446. else {
  447. const { p, f } = this.wNAF(n);
  448. point = p;
  449. fake = f;
  450. }
  451. // Normalize `z` for both points, but return only real one
  452. return Point.normalizeZ([point, fake])[0];
  453. }
  454. /**
  455. * Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly.
  456. * Not using Strauss-Shamir trick: precomputation tables are faster.
  457. * The trick could be useful if both P and Q are not G (not in our case).
  458. * @returns non-zero affine point
  459. */
  460. multiplyAndAddUnsafe(Q, a, b) {
  461. const G = Point.BASE; // No Strauss-Shamir trick: we have 10% faster G precomputes
  462. const mul = (P, a // Select faster multiply() method
  463. ) => (a === _0n || a === _1n || !P.equals(G) ? P.multiplyUnsafe(a) : P.multiply(a));
  464. const sum = mul(this, a).add(mul(Q, b));
  465. return sum.is0() ? undefined : sum;
  466. }
  467. // Converts Projective point to affine (x, y) coordinates.
  468. // Can accept precomputed Z^-1 - for example, from invertBatch.
  469. // (x, y, z) ∋ (x=x/z, y=y/z)
  470. toAffine(iz) {
  471. const { px: x, py: y, pz: z } = this;
  472. const is0 = this.is0();
  473. // If invZ was 0, we return zero point. However we still want to execute
  474. // all operations, so we replace invZ with a random number, 1.
  475. if (iz == null)
  476. iz = is0 ? Fp.ONE : Fp.inv(z);
  477. const ax = Fp.mul(x, iz);
  478. const ay = Fp.mul(y, iz);
  479. const zz = Fp.mul(z, iz);
  480. if (is0)
  481. return { x: Fp.ZERO, y: Fp.ZERO };
  482. if (!Fp.eql(zz, Fp.ONE))
  483. throw new Error('invZ was invalid');
  484. return { x: ax, y: ay };
  485. }
  486. isTorsionFree() {
  487. const { h: cofactor, isTorsionFree } = CURVE;
  488. if (cofactor === _1n)
  489. return true; // No subgroups, always torsion-free
  490. if (isTorsionFree)
  491. return isTorsionFree(Point, this);
  492. throw new Error('isTorsionFree() has not been declared for the elliptic curve');
  493. }
  494. clearCofactor() {
  495. const { h: cofactor, clearCofactor } = CURVE;
  496. if (cofactor === _1n)
  497. return this; // Fast-path
  498. if (clearCofactor)
  499. return clearCofactor(Point, this);
  500. return this.multiplyUnsafe(CURVE.h);
  501. }
  502. toRawBytes(isCompressed = true) {
  503. this.assertValidity();
  504. return toBytes(Point, this, isCompressed);
  505. }
  506. toHex(isCompressed = true) {
  507. return ut.bytesToHex(this.toRawBytes(isCompressed));
  508. }
  509. }
  510. Point.BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE);
  511. Point.ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO);
  512. const _bits = CURVE.nBitLength;
  513. const wnaf = wNAF(Point, CURVE.endo ? Math.ceil(_bits / 2) : _bits);
  514. // Validate if generator point is on curve
  515. return {
  516. CURVE,
  517. ProjectivePoint: Point,
  518. normPrivateKeyToScalar,
  519. weierstrassEquation,
  520. isWithinCurveOrder,
  521. };
  522. }
  523. function validateOpts(curve) {
  524. const opts = validateBasic(curve);
  525. ut.validateObject(opts, {
  526. hash: 'hash',
  527. hmac: 'function',
  528. randomBytes: 'function',
  529. }, {
  530. bits2int: 'function',
  531. bits2int_modN: 'function',
  532. lowS: 'boolean',
  533. });
  534. return Object.freeze({ lowS: true, ...opts });
  535. }
  536. export function weierstrass(curveDef) {
  537. const CURVE = validateOpts(curveDef);
  538. const { Fp, n: CURVE_ORDER } = CURVE;
  539. const compressedLen = Fp.BYTES + 1; // e.g. 33 for 32
  540. const uncompressedLen = 2 * Fp.BYTES + 1; // e.g. 65 for 32
  541. function isValidFieldElement(num) {
  542. return _0n < num && num < Fp.ORDER; // 0 is banned since it's not invertible FE
  543. }
  544. function modN(a) {
  545. return mod.mod(a, CURVE_ORDER);
  546. }
  547. function invN(a) {
  548. return mod.invert(a, CURVE_ORDER);
  549. }
  550. const { ProjectivePoint: Point, normPrivateKeyToScalar, weierstrassEquation, isWithinCurveOrder, } = weierstrassPoints({
  551. ...CURVE,
  552. toBytes(_c, point, isCompressed) {
  553. const a = point.toAffine();
  554. const x = Fp.toBytes(a.x);
  555. const cat = ut.concatBytes;
  556. if (isCompressed) {
  557. return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x);
  558. }
  559. else {
  560. return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y));
  561. }
  562. },
  563. fromBytes(bytes) {
  564. const len = bytes.length;
  565. const head = bytes[0];
  566. const tail = bytes.subarray(1);
  567. // this.assertValidity() is done inside of fromHex
  568. if (len === compressedLen && (head === 0x02 || head === 0x03)) {
  569. const x = ut.bytesToNumberBE(tail);
  570. if (!isValidFieldElement(x))
  571. throw new Error('Point is not on curve');
  572. const y2 = weierstrassEquation(x); // y² = x³ + ax + b
  573. let y;
  574. try {
  575. y = Fp.sqrt(y2); // y = y² ^ (p+1)/4
  576. }
  577. catch (sqrtError) {
  578. const suffix = sqrtError instanceof Error ? ': ' + sqrtError.message : '';
  579. throw new Error('Point is not on curve' + suffix);
  580. }
  581. const isYOdd = (y & _1n) === _1n;
  582. // ECDSA
  583. const isHeadOdd = (head & 1) === 1;
  584. if (isHeadOdd !== isYOdd)
  585. y = Fp.neg(y);
  586. return { x, y };
  587. }
  588. else if (len === uncompressedLen && head === 0x04) {
  589. const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES));
  590. const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES));
  591. return { x, y };
  592. }
  593. else {
  594. throw new Error(`Point of length ${len} was invalid. Expected ${compressedLen} compressed bytes or ${uncompressedLen} uncompressed bytes`);
  595. }
  596. },
  597. });
  598. const numToNByteStr = (num) => ut.bytesToHex(ut.numberToBytesBE(num, CURVE.nByteLength));
  599. function isBiggerThanHalfOrder(number) {
  600. const HALF = CURVE_ORDER >> _1n;
  601. return number > HALF;
  602. }
  603. function normalizeS(s) {
  604. return isBiggerThanHalfOrder(s) ? modN(-s) : s;
  605. }
  606. // slice bytes num
  607. const slcNum = (b, from, to) => ut.bytesToNumberBE(b.slice(from, to));
  608. /**
  609. * ECDSA signature with its (r, s) properties. Supports DER & compact representations.
  610. */
  611. class Signature {
  612. constructor(r, s, recovery) {
  613. this.r = r;
  614. this.s = s;
  615. this.recovery = recovery;
  616. this.assertValidity();
  617. }
  618. // pair (bytes of r, bytes of s)
  619. static fromCompact(hex) {
  620. const l = CURVE.nByteLength;
  621. hex = ensureBytes('compactSignature', hex, l * 2);
  622. return new Signature(slcNum(hex, 0, l), slcNum(hex, l, 2 * l));
  623. }
  624. // DER encoded ECDSA signature
  625. // https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script
  626. static fromDER(hex) {
  627. const { r, s } = DER.toSig(ensureBytes('DER', hex));
  628. return new Signature(r, s);
  629. }
  630. assertValidity() {
  631. // can use assertGE here
  632. if (!isWithinCurveOrder(this.r))
  633. throw new Error('r must be 0 < r < CURVE.n');
  634. if (!isWithinCurveOrder(this.s))
  635. throw new Error('s must be 0 < s < CURVE.n');
  636. }
  637. addRecoveryBit(recovery) {
  638. return new Signature(this.r, this.s, recovery);
  639. }
  640. recoverPublicKey(msgHash) {
  641. const { r, s, recovery: rec } = this;
  642. const h = bits2int_modN(ensureBytes('msgHash', msgHash)); // Truncate hash
  643. if (rec == null || ![0, 1, 2, 3].includes(rec))
  644. throw new Error('recovery id invalid');
  645. const radj = rec === 2 || rec === 3 ? r + CURVE.n : r;
  646. if (radj >= Fp.ORDER)
  647. throw new Error('recovery id 2 or 3 invalid');
  648. const prefix = (rec & 1) === 0 ? '02' : '03';
  649. const R = Point.fromHex(prefix + numToNByteStr(radj));
  650. const ir = invN(radj); // r^-1
  651. const u1 = modN(-h * ir); // -hr^-1
  652. const u2 = modN(s * ir); // sr^-1
  653. const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2); // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1)
  654. if (!Q)
  655. throw new Error('point at infinify'); // unsafe is fine: no priv data leaked
  656. Q.assertValidity();
  657. return Q;
  658. }
  659. // Signatures should be low-s, to prevent malleability.
  660. hasHighS() {
  661. return isBiggerThanHalfOrder(this.s);
  662. }
  663. normalizeS() {
  664. return this.hasHighS() ? new Signature(this.r, modN(-this.s), this.recovery) : this;
  665. }
  666. // DER-encoded
  667. toDERRawBytes() {
  668. return ut.hexToBytes(this.toDERHex());
  669. }
  670. toDERHex() {
  671. return DER.hexFromSig({ r: this.r, s: this.s });
  672. }
  673. // padded bytes of r, then padded bytes of s
  674. toCompactRawBytes() {
  675. return ut.hexToBytes(this.toCompactHex());
  676. }
  677. toCompactHex() {
  678. return numToNByteStr(this.r) + numToNByteStr(this.s);
  679. }
  680. }
  681. const utils = {
  682. isValidPrivateKey(privateKey) {
  683. try {
  684. normPrivateKeyToScalar(privateKey);
  685. return true;
  686. }
  687. catch (error) {
  688. return false;
  689. }
  690. },
  691. normPrivateKeyToScalar: normPrivateKeyToScalar,
  692. /**
  693. * Produces cryptographically secure private key from random of size
  694. * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible.
  695. */
  696. randomPrivateKey: () => {
  697. const length = mod.getMinHashLength(CURVE.n);
  698. return mod.mapHashToField(CURVE.randomBytes(length), CURVE.n);
  699. },
  700. /**
  701. * Creates precompute table for an arbitrary EC point. Makes point "cached".
  702. * Allows to massively speed-up `point.multiply(scalar)`.
  703. * @returns cached point
  704. * @example
  705. * const fast = utils.precompute(8, ProjectivePoint.fromHex(someonesPubKey));
  706. * fast.multiply(privKey); // much faster ECDH now
  707. */
  708. precompute(windowSize = 8, point = Point.BASE) {
  709. point._setWindowSize(windowSize);
  710. point.multiply(BigInt(3)); // 3 is arbitrary, just need any number here
  711. return point;
  712. },
  713. };
  714. /**
  715. * Computes public key for a private key. Checks for validity of the private key.
  716. * @param privateKey private key
  717. * @param isCompressed whether to return compact (default), or full key
  718. * @returns Public key, full when isCompressed=false; short when isCompressed=true
  719. */
  720. function getPublicKey(privateKey, isCompressed = true) {
  721. return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed);
  722. }
  723. /**
  724. * Quick and dirty check for item being public key. Does not validate hex, or being on-curve.
  725. */
  726. function isProbPub(item) {
  727. const arr = ut.isBytes(item);
  728. const str = typeof item === 'string';
  729. const len = (arr || str) && item.length;
  730. if (arr)
  731. return len === compressedLen || len === uncompressedLen;
  732. if (str)
  733. return len === 2 * compressedLen || len === 2 * uncompressedLen;
  734. if (item instanceof Point)
  735. return true;
  736. return false;
  737. }
  738. /**
  739. * ECDH (Elliptic Curve Diffie Hellman).
  740. * Computes shared public key from private key and public key.
  741. * Checks: 1) private key validity 2) shared key is on-curve.
  742. * Does NOT hash the result.
  743. * @param privateA private key
  744. * @param publicB different public key
  745. * @param isCompressed whether to return compact (default), or full key
  746. * @returns shared public key
  747. */
  748. function getSharedSecret(privateA, publicB, isCompressed = true) {
  749. if (isProbPub(privateA))
  750. throw new Error('first arg must be private key');
  751. if (!isProbPub(publicB))
  752. throw new Error('second arg must be public key');
  753. const b = Point.fromHex(publicB); // check for being on-curve
  754. return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed);
  755. }
  756. // RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets.
  757. // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int.
  758. // bits2int can produce res>N, we can do mod(res, N) since the bitLen is the same.
  759. // int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors
  760. const bits2int = CURVE.bits2int ||
  761. function (bytes) {
  762. // For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m)
  763. // for some cases, since bytes.length * 8 is not actual bitLength.
  764. const num = ut.bytesToNumberBE(bytes); // check for == u8 done here
  765. const delta = bytes.length * 8 - CURVE.nBitLength; // truncate to nBitLength leftmost bits
  766. return delta > 0 ? num >> BigInt(delta) : num;
  767. };
  768. const bits2int_modN = CURVE.bits2int_modN ||
  769. function (bytes) {
  770. return modN(bits2int(bytes)); // can't use bytesToNumberBE here
  771. };
  772. // NOTE: pads output with zero as per spec
  773. const ORDER_MASK = ut.bitMask(CURVE.nBitLength);
  774. /**
  775. * Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`.
  776. */
  777. function int2octets(num) {
  778. if (typeof num !== 'bigint')
  779. throw new Error('bigint expected');
  780. if (!(_0n <= num && num < ORDER_MASK))
  781. throw new Error(`bigint expected < 2^${CURVE.nBitLength}`);
  782. // works with order, can have different size than numToField!
  783. return ut.numberToBytesBE(num, CURVE.nByteLength);
  784. }
  785. // Steps A, D of RFC6979 3.2
  786. // Creates RFC6979 seed; converts msg/privKey to numbers.
  787. // Used only in sign, not in verify.
  788. // NOTE: we cannot assume here that msgHash has same amount of bytes as curve order, this will be wrong at least for P521.
  789. // Also it can be bigger for P224 + SHA256
  790. function prepSig(msgHash, privateKey, opts = defaultSigOpts) {
  791. if (['recovered', 'canonical'].some((k) => k in opts))
  792. throw new Error('sign() legacy options not supported');
  793. const { hash, randomBytes } = CURVE;
  794. let { lowS, prehash, extraEntropy: ent } = opts; // generates low-s sigs by default
  795. if (lowS == null)
  796. lowS = true; // RFC6979 3.2: we skip step A, because we already provide hash
  797. msgHash = ensureBytes('msgHash', msgHash);
  798. if (prehash)
  799. msgHash = ensureBytes('prehashed msgHash', hash(msgHash));
  800. // We can't later call bits2octets, since nested bits2int is broken for curves
  801. // with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call.
  802. // const bits2octets = (bits) => int2octets(bits2int_modN(bits))
  803. const h1int = bits2int_modN(msgHash);
  804. const d = normPrivateKeyToScalar(privateKey); // validate private key, convert to bigint
  805. const seedArgs = [int2octets(d), int2octets(h1int)];
  806. // extraEntropy. RFC6979 3.6: additional k' (optional).
  807. if (ent != null && ent !== false) {
  808. // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
  809. const e = ent === true ? randomBytes(Fp.BYTES) : ent; // generate random bytes OR pass as-is
  810. seedArgs.push(ensureBytes('extraEntropy', e)); // check for being bytes
  811. }
  812. const seed = ut.concatBytes(...seedArgs); // Step D of RFC6979 3.2
  813. const m = h1int; // NOTE: no need to call bits2int second time here, it is inside truncateHash!
  814. // Converts signature params into point w r/s, checks result for validity.
  815. function k2sig(kBytes) {
  816. // RFC 6979 Section 3.2, step 3: k = bits2int(T)
  817. const k = bits2int(kBytes); // Cannot use fields methods, since it is group element
  818. if (!isWithinCurveOrder(k))
  819. return; // Important: all mod() calls here must be done over N
  820. const ik = invN(k); // k^-1 mod n
  821. const q = Point.BASE.multiply(k).toAffine(); // q = Gk
  822. const r = modN(q.x); // r = q.x mod n
  823. if (r === _0n)
  824. return;
  825. // Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q−1] according to
  826. // https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it:
  827. // a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT
  828. const s = modN(ik * modN(m + r * d)); // Not using blinding here
  829. if (s === _0n)
  830. return;
  831. let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n); // recovery bit (2 or 3, when q.x > n)
  832. let normS = s;
  833. if (lowS && isBiggerThanHalfOrder(s)) {
  834. normS = normalizeS(s); // if lowS was passed, ensure s is always
  835. recovery ^= 1; // // in the bottom half of N
  836. }
  837. return new Signature(r, normS, recovery); // use normS, not s
  838. }
  839. return { seed, k2sig };
  840. }
  841. const defaultSigOpts = { lowS: CURVE.lowS, prehash: false };
  842. const defaultVerOpts = { lowS: CURVE.lowS, prehash: false };
  843. /**
  844. * Signs message hash with a private key.
  845. * ```
  846. * sign(m, d, k) where
  847. * (x, y) = G × k
  848. * r = x mod n
  849. * s = (m + dr)/k mod n
  850. * ```
  851. * @param msgHash NOT message. msg needs to be hashed to `msgHash`, or use `prehash`.
  852. * @param privKey private key
  853. * @param opts lowS for non-malleable sigs. extraEntropy for mixing randomness into k. prehash will hash first arg.
  854. * @returns signature with recovery param
  855. */
  856. function sign(msgHash, privKey, opts = defaultSigOpts) {
  857. const { seed, k2sig } = prepSig(msgHash, privKey, opts); // Steps A, D of RFC6979 3.2.
  858. const C = CURVE;
  859. const drbg = ut.createHmacDrbg(C.hash.outputLen, C.nByteLength, C.hmac);
  860. return drbg(seed, k2sig); // Steps B, C, D, E, F, G
  861. }
  862. // Enable precomputes. Slows down first publicKey computation by 20ms.
  863. Point.BASE._setWindowSize(8);
  864. // utils.precompute(8, ProjectivePoint.BASE)
  865. /**
  866. * Verifies a signature against message hash and public key.
  867. * Rejects lowS signatures by default: to override,
  868. * specify option `{lowS: false}`. Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf:
  869. *
  870. * ```
  871. * verify(r, s, h, P) where
  872. * U1 = hs^-1 mod n
  873. * U2 = rs^-1 mod n
  874. * R = U1⋅G - U2⋅P
  875. * mod(R.x, n) == r
  876. * ```
  877. */
  878. function verify(signature, msgHash, publicKey, opts = defaultVerOpts) {
  879. const sg = signature;
  880. msgHash = ensureBytes('msgHash', msgHash);
  881. publicKey = ensureBytes('publicKey', publicKey);
  882. if ('strict' in opts)
  883. throw new Error('options.strict was renamed to lowS');
  884. const { lowS, prehash } = opts;
  885. let _sig = undefined;
  886. let P;
  887. try {
  888. if (typeof sg === 'string' || ut.isBytes(sg)) {
  889. // Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length).
  890. // Since DER can also be 2*nByteLength bytes, we check for it first.
  891. try {
  892. _sig = Signature.fromDER(sg);
  893. }
  894. catch (derError) {
  895. if (!(derError instanceof DER.Err))
  896. throw derError;
  897. _sig = Signature.fromCompact(sg);
  898. }
  899. }
  900. else if (typeof sg === 'object' && typeof sg.r === 'bigint' && typeof sg.s === 'bigint') {
  901. const { r, s } = sg;
  902. _sig = new Signature(r, s);
  903. }
  904. else {
  905. throw new Error('PARSE');
  906. }
  907. P = Point.fromHex(publicKey);
  908. }
  909. catch (error) {
  910. if (error.message === 'PARSE')
  911. throw new Error(`signature must be Signature instance, Uint8Array or hex string`);
  912. return false;
  913. }
  914. if (lowS && _sig.hasHighS())
  915. return false;
  916. if (prehash)
  917. msgHash = CURVE.hash(msgHash);
  918. const { r, s } = _sig;
  919. const h = bits2int_modN(msgHash); // Cannot use fields methods, since it is group element
  920. const is = invN(s); // s^-1
  921. const u1 = modN(h * is); // u1 = hs^-1 mod n
  922. const u2 = modN(r * is); // u2 = rs^-1 mod n
  923. const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2)?.toAffine(); // R = u1⋅G + u2⋅P
  924. if (!R)
  925. return false;
  926. const v = modN(R.x);
  927. return v === r;
  928. }
  929. return {
  930. CURVE,
  931. getPublicKey,
  932. getSharedSecret,
  933. sign,
  934. verify,
  935. ProjectivePoint: Point,
  936. Signature,
  937. utils,
  938. };
  939. }
  940. /**
  941. * Implementation of the Shallue and van de Woestijne method for any weierstrass curve.
  942. * TODO: check if there is a way to merge this with uvRatio in Edwards; move to modular.
  943. * b = True and y = sqrt(u / v) if (u / v) is square in F, and
  944. * b = False and y = sqrt(Z * (u / v)) otherwise.
  945. * @param Fp
  946. * @param Z
  947. * @returns
  948. */
  949. export function SWUFpSqrtRatio(Fp, Z) {
  950. // Generic implementation
  951. const q = Fp.ORDER;
  952. let l = _0n;
  953. for (let o = q - _1n; o % _2n === _0n; o /= _2n)
  954. l += _1n;
  955. const c1 = l; // 1. c1, the largest integer such that 2^c1 divides q - 1.
  956. // We need 2n ** c1 and 2n ** (c1-1). We can't use **; but we can use <<.
  957. // 2n ** c1 == 2n << (c1-1)
  958. const _2n_pow_c1_1 = _2n << (c1 - _1n - _1n);
  959. const _2n_pow_c1 = _2n_pow_c1_1 * _2n;
  960. const c2 = (q - _1n) / _2n_pow_c1; // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic
  961. const c3 = (c2 - _1n) / _2n; // 3. c3 = (c2 - 1) / 2 # Integer arithmetic
  962. const c4 = _2n_pow_c1 - _1n; // 4. c4 = 2^c1 - 1 # Integer arithmetic
  963. const c5 = _2n_pow_c1_1; // 5. c5 = 2^(c1 - 1) # Integer arithmetic
  964. const c6 = Fp.pow(Z, c2); // 6. c6 = Z^c2
  965. const c7 = Fp.pow(Z, (c2 + _1n) / _2n); // 7. c7 = Z^((c2 + 1) / 2)
  966. let sqrtRatio = (u, v) => {
  967. let tv1 = c6; // 1. tv1 = c6
  968. let tv2 = Fp.pow(v, c4); // 2. tv2 = v^c4
  969. let tv3 = Fp.sqr(tv2); // 3. tv3 = tv2^2
  970. tv3 = Fp.mul(tv3, v); // 4. tv3 = tv3 * v
  971. let tv5 = Fp.mul(u, tv3); // 5. tv5 = u * tv3
  972. tv5 = Fp.pow(tv5, c3); // 6. tv5 = tv5^c3
  973. tv5 = Fp.mul(tv5, tv2); // 7. tv5 = tv5 * tv2
  974. tv2 = Fp.mul(tv5, v); // 8. tv2 = tv5 * v
  975. tv3 = Fp.mul(tv5, u); // 9. tv3 = tv5 * u
  976. let tv4 = Fp.mul(tv3, tv2); // 10. tv4 = tv3 * tv2
  977. tv5 = Fp.pow(tv4, c5); // 11. tv5 = tv4^c5
  978. let isQR = Fp.eql(tv5, Fp.ONE); // 12. isQR = tv5 == 1
  979. tv2 = Fp.mul(tv3, c7); // 13. tv2 = tv3 * c7
  980. tv5 = Fp.mul(tv4, tv1); // 14. tv5 = tv4 * tv1
  981. tv3 = Fp.cmov(tv2, tv3, isQR); // 15. tv3 = CMOV(tv2, tv3, isQR)
  982. tv4 = Fp.cmov(tv5, tv4, isQR); // 16. tv4 = CMOV(tv5, tv4, isQR)
  983. // 17. for i in (c1, c1 - 1, ..., 2):
  984. for (let i = c1; i > _1n; i--) {
  985. let tv5 = i - _2n; // 18. tv5 = i - 2
  986. tv5 = _2n << (tv5 - _1n); // 19. tv5 = 2^tv5
  987. let tvv5 = Fp.pow(tv4, tv5); // 20. tv5 = tv4^tv5
  988. const e1 = Fp.eql(tvv5, Fp.ONE); // 21. e1 = tv5 == 1
  989. tv2 = Fp.mul(tv3, tv1); // 22. tv2 = tv3 * tv1
  990. tv1 = Fp.mul(tv1, tv1); // 23. tv1 = tv1 * tv1
  991. tvv5 = Fp.mul(tv4, tv1); // 24. tv5 = tv4 * tv1
  992. tv3 = Fp.cmov(tv2, tv3, e1); // 25. tv3 = CMOV(tv2, tv3, e1)
  993. tv4 = Fp.cmov(tvv5, tv4, e1); // 26. tv4 = CMOV(tv5, tv4, e1)
  994. }
  995. return { isValid: isQR, value: tv3 };
  996. };
  997. if (Fp.ORDER % _4n === _3n) {
  998. // sqrt_ratio_3mod4(u, v)
  999. const c1 = (Fp.ORDER - _3n) / _4n; // 1. c1 = (q - 3) / 4 # Integer arithmetic
  1000. const c2 = Fp.sqrt(Fp.neg(Z)); // 2. c2 = sqrt(-Z)
  1001. sqrtRatio = (u, v) => {
  1002. let tv1 = Fp.sqr(v); // 1. tv1 = v^2
  1003. const tv2 = Fp.mul(u, v); // 2. tv2 = u * v
  1004. tv1 = Fp.mul(tv1, tv2); // 3. tv1 = tv1 * tv2
  1005. let y1 = Fp.pow(tv1, c1); // 4. y1 = tv1^c1
  1006. y1 = Fp.mul(y1, tv2); // 5. y1 = y1 * tv2
  1007. const y2 = Fp.mul(y1, c2); // 6. y2 = y1 * c2
  1008. const tv3 = Fp.mul(Fp.sqr(y1), v); // 7. tv3 = y1^2; 8. tv3 = tv3 * v
  1009. const isQR = Fp.eql(tv3, u); // 9. isQR = tv3 == u
  1010. let y = Fp.cmov(y2, y1, isQR); // 10. y = CMOV(y2, y1, isQR)
  1011. return { isValid: isQR, value: y }; // 11. return (isQR, y) isQR ? y : y*c2
  1012. };
  1013. }
  1014. // No curves uses that
  1015. // if (Fp.ORDER % _8n === _5n) // sqrt_ratio_5mod8
  1016. return sqrtRatio;
  1017. }
  1018. /**
  1019. * Simplified Shallue-van de Woestijne-Ulas Method
  1020. * https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2
  1021. */
  1022. export function mapToCurveSimpleSWU(Fp, opts) {
  1023. mod.validateField(Fp);
  1024. if (!Fp.isValid(opts.A) || !Fp.isValid(opts.B) || !Fp.isValid(opts.Z))
  1025. throw new Error('mapToCurveSimpleSWU: invalid opts');
  1026. const sqrtRatio = SWUFpSqrtRatio(Fp, opts.Z);
  1027. if (!Fp.isOdd)
  1028. throw new Error('Fp.isOdd is not implemented!');
  1029. // Input: u, an element of F.
  1030. // Output: (x, y), a point on E.
  1031. return (u) => {
  1032. // prettier-ignore
  1033. let tv1, tv2, tv3, tv4, tv5, tv6, x, y;
  1034. tv1 = Fp.sqr(u); // 1. tv1 = u^2
  1035. tv1 = Fp.mul(tv1, opts.Z); // 2. tv1 = Z * tv1
  1036. tv2 = Fp.sqr(tv1); // 3. tv2 = tv1^2
  1037. tv2 = Fp.add(tv2, tv1); // 4. tv2 = tv2 + tv1
  1038. tv3 = Fp.add(tv2, Fp.ONE); // 5. tv3 = tv2 + 1
  1039. tv3 = Fp.mul(tv3, opts.B); // 6. tv3 = B * tv3
  1040. tv4 = Fp.cmov(opts.Z, Fp.neg(tv2), !Fp.eql(tv2, Fp.ZERO)); // 7. tv4 = CMOV(Z, -tv2, tv2 != 0)
  1041. tv4 = Fp.mul(tv4, opts.A); // 8. tv4 = A * tv4
  1042. tv2 = Fp.sqr(tv3); // 9. tv2 = tv3^2
  1043. tv6 = Fp.sqr(tv4); // 10. tv6 = tv4^2
  1044. tv5 = Fp.mul(tv6, opts.A); // 11. tv5 = A * tv6
  1045. tv2 = Fp.add(tv2, tv5); // 12. tv2 = tv2 + tv5
  1046. tv2 = Fp.mul(tv2, tv3); // 13. tv2 = tv2 * tv3
  1047. tv6 = Fp.mul(tv6, tv4); // 14. tv6 = tv6 * tv4
  1048. tv5 = Fp.mul(tv6, opts.B); // 15. tv5 = B * tv6
  1049. tv2 = Fp.add(tv2, tv5); // 16. tv2 = tv2 + tv5
  1050. x = Fp.mul(tv1, tv3); // 17. x = tv1 * tv3
  1051. const { isValid, value } = sqrtRatio(tv2, tv6); // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6)
  1052. y = Fp.mul(tv1, u); // 19. y = tv1 * u -> Z * u^3 * y1
  1053. y = Fp.mul(y, value); // 20. y = y * y1
  1054. x = Fp.cmov(x, tv3, isValid); // 21. x = CMOV(x, tv3, is_gx1_square)
  1055. y = Fp.cmov(y, value, isValid); // 22. y = CMOV(y, y1, is_gx1_square)
  1056. const e1 = Fp.isOdd(u) === Fp.isOdd(y); // 23. e1 = sgn0(u) == sgn0(y)
  1057. y = Fp.cmov(Fp.neg(y), y, e1); // 24. y = CMOV(-y, y, e1)
  1058. x = Fp.div(x, tv4); // 25. x = x / tv4
  1059. return { x, y };
  1060. };
  1061. }
  1062. //# sourceMappingURL=weierstrass.js.map