@noble/curves 1.9.2 → 1.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/README.md +186 -206
  2. package/_shortw_utils.d.ts +1 -0
  3. package/_shortw_utils.d.ts.map +1 -1
  4. package/_shortw_utils.js +1 -0
  5. package/_shortw_utils.js.map +1 -1
  6. package/abstract/bls.d.ts +87 -62
  7. package/abstract/bls.d.ts.map +1 -1
  8. package/abstract/bls.js +170 -163
  9. package/abstract/bls.js.map +1 -1
  10. package/abstract/curve.d.ts +109 -23
  11. package/abstract/curve.d.ts.map +1 -1
  12. package/abstract/curve.js +158 -156
  13. package/abstract/curve.js.map +1 -1
  14. package/abstract/edwards.d.ts +124 -70
  15. package/abstract/edwards.d.ts.map +1 -1
  16. package/abstract/edwards.js +212 -62
  17. package/abstract/edwards.js.map +1 -1
  18. package/abstract/hash-to-curve.d.ts +8 -4
  19. package/abstract/hash-to-curve.d.ts.map +1 -1
  20. package/abstract/hash-to-curve.js +23 -11
  21. package/abstract/hash-to-curve.js.map +1 -1
  22. package/abstract/modular.d.ts +8 -3
  23. package/abstract/modular.d.ts.map +1 -1
  24. package/abstract/modular.js +79 -35
  25. package/abstract/modular.js.map +1 -1
  26. package/abstract/montgomery.d.ts +17 -4
  27. package/abstract/montgomery.d.ts.map +1 -1
  28. package/abstract/montgomery.js +19 -3
  29. package/abstract/montgomery.js.map +1 -1
  30. package/abstract/tower.d.ts +3 -3
  31. package/abstract/tower.d.ts.map +1 -1
  32. package/abstract/tower.js.map +1 -1
  33. package/abstract/weierstrass.d.ts +142 -116
  34. package/abstract/weierstrass.d.ts.map +1 -1
  35. package/abstract/weierstrass.js +414 -335
  36. package/abstract/weierstrass.js.map +1 -1
  37. package/bls12-381.d.ts.map +1 -1
  38. package/bls12-381.js +4 -4
  39. package/bls12-381.js.map +1 -1
  40. package/ed25519.d.ts +52 -66
  41. package/ed25519.d.ts.map +1 -1
  42. package/ed25519.js +128 -155
  43. package/ed25519.js.map +1 -1
  44. package/ed448.d.ts +57 -58
  45. package/ed448.d.ts.map +1 -1
  46. package/ed448.js +114 -131
  47. package/ed448.js.map +1 -1
  48. package/esm/_shortw_utils.d.ts +1 -0
  49. package/esm/_shortw_utils.d.ts.map +1 -1
  50. package/esm/_shortw_utils.js +1 -0
  51. package/esm/_shortw_utils.js.map +1 -1
  52. package/esm/abstract/bls.d.ts +87 -62
  53. package/esm/abstract/bls.d.ts.map +1 -1
  54. package/esm/abstract/bls.js +171 -164
  55. package/esm/abstract/bls.js.map +1 -1
  56. package/esm/abstract/curve.d.ts +109 -23
  57. package/esm/abstract/curve.d.ts.map +1 -1
  58. package/esm/abstract/curve.js +156 -155
  59. package/esm/abstract/curve.js.map +1 -1
  60. package/esm/abstract/edwards.d.ts +124 -70
  61. package/esm/abstract/edwards.d.ts.map +1 -1
  62. package/esm/abstract/edwards.js +210 -62
  63. package/esm/abstract/edwards.js.map +1 -1
  64. package/esm/abstract/hash-to-curve.d.ts +8 -4
  65. package/esm/abstract/hash-to-curve.d.ts.map +1 -1
  66. package/esm/abstract/hash-to-curve.js +22 -11
  67. package/esm/abstract/hash-to-curve.js.map +1 -1
  68. package/esm/abstract/modular.d.ts +8 -3
  69. package/esm/abstract/modular.d.ts.map +1 -1
  70. package/esm/abstract/modular.js +79 -35
  71. package/esm/abstract/modular.js.map +1 -1
  72. package/esm/abstract/montgomery.d.ts +17 -4
  73. package/esm/abstract/montgomery.d.ts.map +1 -1
  74. package/esm/abstract/montgomery.js +19 -3
  75. package/esm/abstract/montgomery.js.map +1 -1
  76. package/esm/abstract/tower.d.ts +3 -3
  77. package/esm/abstract/tower.d.ts.map +1 -1
  78. package/esm/abstract/tower.js.map +1 -1
  79. package/esm/abstract/weierstrass.d.ts +142 -116
  80. package/esm/abstract/weierstrass.d.ts.map +1 -1
  81. package/esm/abstract/weierstrass.js +411 -333
  82. package/esm/abstract/weierstrass.js.map +1 -1
  83. package/esm/bls12-381.d.ts.map +1 -1
  84. package/esm/bls12-381.js +4 -4
  85. package/esm/bls12-381.js.map +1 -1
  86. package/esm/ed25519.d.ts +52 -66
  87. package/esm/ed25519.d.ts.map +1 -1
  88. package/esm/ed25519.js +131 -157
  89. package/esm/ed25519.js.map +1 -1
  90. package/esm/ed448.d.ts +57 -58
  91. package/esm/ed448.d.ts.map +1 -1
  92. package/esm/ed448.js +116 -132
  93. package/esm/ed448.js.map +1 -1
  94. package/esm/index.js +7 -9
  95. package/esm/index.js.map +1 -1
  96. package/esm/jubjub.d.ts +3 -3
  97. package/esm/jubjub.d.ts.map +1 -1
  98. package/esm/jubjub.js +3 -3
  99. package/esm/jubjub.js.map +1 -1
  100. package/esm/misc.d.ts +3 -5
  101. package/esm/misc.d.ts.map +1 -1
  102. package/esm/misc.js +0 -3
  103. package/esm/misc.js.map +1 -1
  104. package/esm/nist.d.ts +0 -6
  105. package/esm/nist.d.ts.map +1 -1
  106. package/esm/nist.js +31 -15
  107. package/esm/nist.js.map +1 -1
  108. package/esm/p256.d.ts +4 -0
  109. package/esm/p256.d.ts.map +1 -1
  110. package/esm/p256.js +4 -0
  111. package/esm/p256.js.map +1 -1
  112. package/esm/p384.d.ts +4 -1
  113. package/esm/p384.d.ts.map +1 -1
  114. package/esm/p384.js +4 -1
  115. package/esm/p384.js.map +1 -1
  116. package/esm/p521.d.ts +4 -0
  117. package/esm/p521.d.ts.map +1 -1
  118. package/esm/p521.js +4 -0
  119. package/esm/p521.js.map +1 -1
  120. package/esm/secp256k1.d.ts +32 -15
  121. package/esm/secp256k1.d.ts.map +1 -1
  122. package/esm/secp256k1.js +72 -67
  123. package/esm/secp256k1.js.map +1 -1
  124. package/esm/utils.d.ts +1 -1
  125. package/esm/utils.js +1 -1
  126. package/index.js +7 -9
  127. package/index.js.map +1 -1
  128. package/jubjub.d.ts +3 -3
  129. package/jubjub.d.ts.map +1 -1
  130. package/jubjub.js +3 -3
  131. package/jubjub.js.map +1 -1
  132. package/misc.d.ts +3 -5
  133. package/misc.d.ts.map +1 -1
  134. package/misc.js +0 -3
  135. package/misc.js.map +1 -1
  136. package/nist.d.ts +0 -6
  137. package/nist.d.ts.map +1 -1
  138. package/nist.js +31 -15
  139. package/nist.js.map +1 -1
  140. package/p256.d.ts +4 -0
  141. package/p256.d.ts.map +1 -1
  142. package/p256.js +4 -0
  143. package/p256.js.map +1 -1
  144. package/p384.d.ts +4 -1
  145. package/p384.d.ts.map +1 -1
  146. package/p384.js +4 -1
  147. package/p384.js.map +1 -1
  148. package/p521.d.ts +4 -0
  149. package/p521.d.ts.map +1 -1
  150. package/p521.js +4 -0
  151. package/p521.js.map +1 -1
  152. package/package.json +4 -2
  153. package/secp256k1.d.ts +32 -15
  154. package/secp256k1.d.ts.map +1 -1
  155. package/secp256k1.js +70 -65
  156. package/secp256k1.js.map +1 -1
  157. package/src/_shortw_utils.ts +1 -0
  158. package/src/abstract/bls.ts +319 -257
  159. package/src/abstract/curve.ts +226 -170
  160. package/src/abstract/edwards.ts +350 -139
  161. package/src/abstract/hash-to-curve.ts +33 -16
  162. package/src/abstract/modular.ts +86 -35
  163. package/src/abstract/montgomery.ts +36 -9
  164. package/src/abstract/tower.ts +4 -4
  165. package/src/abstract/weierstrass.ts +567 -474
  166. package/src/bls12-381.ts +28 -20
  167. package/src/ed25519.ts +161 -179
  168. package/src/ed448.ts +150 -156
  169. package/src/index.ts +7 -9
  170. package/src/jubjub.ts +3 -3
  171. package/src/misc.ts +3 -7
  172. package/src/nist.ts +40 -16
  173. package/src/p256.ts +4 -0
  174. package/src/p384.ts +4 -2
  175. package/src/p521.ts +4 -0
  176. package/src/secp256k1.ts +91 -73
  177. package/src/utils.ts +1 -1
  178. package/utils.d.ts +1 -1
  179. package/utils.js +1 -1
@@ -1,14 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DER = exports.DERErr = void 0;
4
+ exports._splitEndoScalar = _splitEndoScalar;
4
5
  exports._legacyHelperEquat = _legacyHelperEquat;
5
- exports._legacyHelperNormPriv = _legacyHelperNormPriv;
6
+ exports._normFnElement = _normFnElement;
6
7
  exports.weierstrassN = weierstrassN;
7
8
  exports.weierstrassPoints = weierstrassPoints;
8
- exports.ecdsa = ecdsa;
9
- exports.weierstrass = weierstrass;
10
9
  exports.SWUFpSqrtRatio = SWUFpSqrtRatio;
11
10
  exports.mapToCurveSimpleSWU = mapToCurveSimpleSWU;
11
+ exports.ecdsa = ecdsa;
12
+ exports.weierstrass = weierstrass;
12
13
  /**
13
14
  * Short Weierstrass curve methods. The formula is: y² = x³ + ax + b.
14
15
  *
@@ -37,9 +38,40 @@ exports.mapToCurveSimpleSWU = mapToCurveSimpleSWU;
37
38
  */
38
39
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
39
40
  const hmac_js_1 = require("@noble/hashes/hmac.js");
41
+ const utils_1 = require("@noble/hashes/utils");
40
42
  const utils_ts_1 = require("../utils.js");
41
43
  const curve_ts_1 = require("./curve.js");
42
44
  const modular_ts_1 = require("./modular.js");
45
+ // We construct basis in such way that den is always positive and equals n, but num sign depends on basis (not on secret value)
46
+ const divNearest = (num, den) => (num + (num >= 0 ? den : -den) / _2n) / den;
47
+ /**
48
+ * Splits scalar for GLV endomorphism.
49
+ */
50
+ function _splitEndoScalar(k, basis, n) {
51
+ // Split scalar into two such that part is ~half bits: `abs(part) < sqrt(N)`
52
+ // Since part can be negative, we need to do this on point.
53
+ // TODO: verifyScalar function which consumes lambda
54
+ const [[a1, b1], [a2, b2]] = basis;
55
+ const c1 = divNearest(b2 * k, n);
56
+ const c2 = divNearest(-b1 * k, n);
57
+ // |k1|/|k2| is < sqrt(N), but can be negative.
58
+ // If we do `k1 mod N`, we'll get big scalar (`> sqrt(N)`): so, we do cheaper negation instead.
59
+ let k1 = k - c1 * a1 - c2 * a2;
60
+ let k2 = -c1 * b1 - c2 * b2;
61
+ const k1neg = k1 < _0n;
62
+ const k2neg = k2 < _0n;
63
+ if (k1neg)
64
+ k1 = -k1;
65
+ if (k2neg)
66
+ k2 = -k2;
67
+ // Double check that resulting scalar less than half bits of N: otherwise wNAF will fail.
68
+ // This should only happen on wrong basises. Also, math inside is too complex and I don't trust it.
69
+ const MAX_NUM = (0, utils_ts_1.bitMask)(Math.ceil((0, utils_ts_1.bitLen)(n) / 2)) + _1n; // Half bits of N
70
+ if (k1 < _0n || k1 >= MAX_NUM || k2 < _0n || k2 >= MAX_NUM) {
71
+ throw new Error('splitScalar (endomorphism): failed, k=' + k);
72
+ }
73
+ return { k1neg, k1, k2neg, k2 };
74
+ }
43
75
  function validateSigVerOpts(opts) {
44
76
  if (opts.lowS !== undefined)
45
77
  (0, utils_ts_1.abool)('lowS', opts.lowS);
@@ -179,37 +211,24 @@ function _legacyHelperEquat(Fp, a, b) {
179
211
  }
180
212
  return weierstrassEquation;
181
213
  }
182
- function _legacyHelperNormPriv(Fn, allowedPrivateKeyLengths, wrapPrivateKey) {
214
+ function _normFnElement(Fn, key) {
183
215
  const { BYTES: expected } = Fn;
184
- // Validates if priv key is valid and converts it to bigint.
185
- function normPrivateKeyToScalar(key) {
186
- let num;
187
- if (typeof key === 'bigint') {
188
- num = key;
216
+ let num;
217
+ if (typeof key === 'bigint') {
218
+ num = key;
219
+ }
220
+ else {
221
+ let bytes = (0, utils_ts_1.ensureBytes)('private key', key);
222
+ try {
223
+ num = Fn.fromBytes(bytes);
189
224
  }
190
- else {
191
- let bytes = (0, utils_ts_1.ensureBytes)('private key', key);
192
- if (allowedPrivateKeyLengths) {
193
- if (!allowedPrivateKeyLengths.includes(bytes.length * 2))
194
- throw new Error('invalid private key');
195
- const padded = new Uint8Array(expected);
196
- padded.set(bytes, padded.length - bytes.length);
197
- bytes = padded;
198
- }
199
- try {
200
- num = Fn.fromBytes(bytes);
201
- }
202
- catch (error) {
203
- throw new Error(`invalid private key: expected ui8a of size ${expected}, got ${typeof key}`);
204
- }
225
+ catch (error) {
226
+ throw new Error(`invalid private key: expected ui8a of size ${expected}, got ${typeof key}`);
205
227
  }
206
- if (wrapPrivateKey)
207
- num = Fn.create(num); // disabled by default, enabled for BLS
208
- if (!Fn.isValidNot0(num))
209
- throw new Error('invalid private key: out of range [1..N-1]');
210
- return num;
211
228
  }
212
- return normPrivateKeyToScalar;
229
+ if (!Fn.isValidNot0(num))
230
+ throw new Error('invalid private key: out of range [1..N-1]');
231
+ return num;
213
232
  }
214
233
  function weierstrassN(CURVE, curveOpts = {}) {
215
234
  const { Fp, Fn } = (0, curve_ts_1._createCurveFields)('weierstrass', CURVE, curveOpts);
@@ -226,10 +245,8 @@ function weierstrassN(CURVE, curveOpts = {}) {
226
245
  const { endo } = curveOpts;
227
246
  if (endo) {
228
247
  // validateObject(endo, { beta: 'bigint', splitScalar: 'function' });
229
- if (!Fp.is0(CURVE.a) ||
230
- typeof endo.beta !== 'bigint' ||
231
- typeof endo.splitScalar !== 'function') {
232
- throw new Error('invalid endo: expected "beta": bigint and "splitScalar": function');
248
+ if (!Fp.is0(CURVE.a) || typeof endo.beta !== 'bigint' || !Array.isArray(endo.basises)) {
249
+ throw new Error('invalid endo: expected "beta": bigint and "basises": array');
233
250
  }
234
251
  }
235
252
  function assertCompressionIsSupported() {
@@ -321,28 +338,33 @@ function weierstrassN(CURVE, curveOpts = {}) {
321
338
  if (!(other instanceof Point))
322
339
  throw new Error('ProjectivePoint expected');
323
340
  }
341
+ function splitEndoScalarN(k) {
342
+ if (!endo || !endo.basises)
343
+ throw new Error('no endo');
344
+ return _splitEndoScalar(k, endo.basises, Fn.ORDER);
345
+ }
324
346
  // Memoized toAffine / validity check. They are heavy. Points are immutable.
325
347
  // Converts Projective point to affine (x, y) coordinates.
326
348
  // Can accept precomputed Z^-1 - for example, from invertBatch.
327
349
  // (X, Y, Z) ∋ (x=X/Z, y=Y/Z)
328
350
  const toAffineMemo = (0, utils_ts_1.memoized)((p, iz) => {
329
- const { px: x, py: y, pz: z } = p;
351
+ const { X, Y, Z } = p;
330
352
  // Fast-path for normalized points
331
- if (Fp.eql(z, Fp.ONE))
332
- return { x, y };
353
+ if (Fp.eql(Z, Fp.ONE))
354
+ return { x: X, y: Y };
333
355
  const is0 = p.is0();
334
356
  // If invZ was 0, we return zero point. However we still want to execute
335
357
  // all operations, so we replace invZ with a random number, 1.
336
358
  if (iz == null)
337
- iz = is0 ? Fp.ONE : Fp.inv(z);
338
- const ax = Fp.mul(x, iz);
339
- const ay = Fp.mul(y, iz);
340
- const zz = Fp.mul(z, iz);
359
+ iz = is0 ? Fp.ONE : Fp.inv(Z);
360
+ const x = Fp.mul(X, iz);
361
+ const y = Fp.mul(Y, iz);
362
+ const zz = Fp.mul(Z, iz);
341
363
  if (is0)
342
364
  return { x: Fp.ZERO, y: Fp.ZERO };
343
365
  if (!Fp.eql(zz, Fp.ONE))
344
366
  throw new Error('invZ was invalid');
345
- return { x: ax, y: ay };
367
+ return { x, y };
346
368
  });
347
369
  // NOTE: on exception this will crash 'cached' and no value will be set.
348
370
  // Otherwise true will be return
@@ -351,7 +373,7 @@ function weierstrassN(CURVE, curveOpts = {}) {
351
373
  // (0, 1, 0) aka ZERO is invalid in most contexts.
352
374
  // In BLS, ZERO can be serialized, so we allow it.
353
375
  // (0, 0, 0) is invalid representation of ZERO.
354
- if (curveOpts.allowInfinityPoint && !Fp.is0(p.py))
376
+ if (curveOpts.allowInfinityPoint && !Fp.is0(p.Y))
355
377
  return;
356
378
  throw new Error('bad point: ZERO');
357
379
  }
@@ -366,7 +388,7 @@ function weierstrassN(CURVE, curveOpts = {}) {
366
388
  return true;
367
389
  });
368
390
  function finishEndo(endoBeta, k1p, k2p, k1neg, k2neg) {
369
- k2p = new Point(Fp.mul(k2p.px, endoBeta), k2p.py, k2p.pz);
391
+ k2p = new Point(Fp.mul(k2p.X, endoBeta), k2p.Y, k2p.Z);
370
392
  k1p = (0, curve_ts_1.negateCt)(k1neg, k1p);
371
393
  k2p = (0, curve_ts_1.negateCt)(k2neg, k2p);
372
394
  return k1p.add(k2p);
@@ -378,10 +400,10 @@ function weierstrassN(CURVE, curveOpts = {}) {
378
400
  */
379
401
  class Point {
380
402
  /** Does NOT validate if the point is valid. Use `.assertValidity()`. */
381
- constructor(px, py, pz) {
382
- this.px = acoord('x', px);
383
- this.py = acoord('y', py, true);
384
- this.pz = acoord('z', pz);
403
+ constructor(X, Y, Z) {
404
+ this.X = acoord('x', X);
405
+ this.Y = acoord('y', Y, true);
406
+ this.Z = acoord('z', Z);
385
407
  Object.freeze(this);
386
408
  }
387
409
  /** Does NOT validate if the point is valid. Use `.assertValidity()`. */
@@ -402,8 +424,18 @@ function weierstrassN(CURVE, curveOpts = {}) {
402
424
  get y() {
403
425
  return this.toAffine().y;
404
426
  }
427
+ // TODO: remove
428
+ get px() {
429
+ return this.X;
430
+ }
431
+ get py() {
432
+ return this.X;
433
+ }
434
+ get pz() {
435
+ return this.Z;
436
+ }
405
437
  static normalizeZ(points) {
406
- return (0, curve_ts_1.normalizeZ)(Point, 'pz', points);
438
+ return (0, curve_ts_1.normalizeZ)(Point, points);
407
439
  }
408
440
  static fromBytes(bytes) {
409
441
  (0, utils_ts_1.abytes)(bytes);
@@ -417,13 +449,15 @@ function weierstrassN(CURVE, curveOpts = {}) {
417
449
  }
418
450
  /** Multiplies generator point by privateKey. */
419
451
  static fromPrivateKey(privateKey) {
420
- const normPrivateKeyToScalar = _legacyHelperNormPriv(Fn, curveOpts.allowedPrivateKeyLengths, curveOpts.wrapPrivateKey);
421
- return Point.BASE.multiply(normPrivateKeyToScalar(privateKey));
452
+ return Point.BASE.multiply(_normFnElement(Fn, privateKey));
422
453
  }
423
- /** Multiscalar Multiplication */
454
+ // TODO: remove
424
455
  static msm(points, scalars) {
425
456
  return (0, curve_ts_1.pippenger)(Point, Fn, points, scalars);
426
457
  }
458
+ _setWindowSize(windowSize) {
459
+ this.precompute(windowSize);
460
+ }
427
461
  /**
428
462
  *
429
463
  * @param windowSize
@@ -431,15 +465,11 @@ function weierstrassN(CURVE, curveOpts = {}) {
431
465
  * @returns
432
466
  */
433
467
  precompute(windowSize = 8, isLazy = true) {
434
- wnaf.setWindowSize(this, windowSize);
468
+ wnaf.createCache(this, windowSize);
435
469
  if (!isLazy)
436
470
  this.multiply(_3n); // random number
437
471
  return this;
438
472
  }
439
- /** "Private method", don't use it directly */
440
- _setWindowSize(windowSize) {
441
- this.precompute(windowSize);
442
- }
443
473
  // TODO: return `this`
444
474
  /** A point on curve is valid if it conforms to equation. */
445
475
  assertValidity() {
@@ -454,15 +484,15 @@ function weierstrassN(CURVE, curveOpts = {}) {
454
484
  /** Compare one point to another. */
455
485
  equals(other) {
456
486
  aprjpoint(other);
457
- const { px: X1, py: Y1, pz: Z1 } = this;
458
- const { px: X2, py: Y2, pz: Z2 } = other;
487
+ const { X: X1, Y: Y1, Z: Z1 } = this;
488
+ const { X: X2, Y: Y2, Z: Z2 } = other;
459
489
  const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1));
460
490
  const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1));
461
491
  return U1 && U2;
462
492
  }
463
493
  /** Flips point to one corresponding to (x, -y) in Affine coordinates. */
464
494
  negate() {
465
- return new Point(this.px, Fp.neg(this.py), this.pz);
495
+ return new Point(this.X, Fp.neg(this.Y), this.Z);
466
496
  }
467
497
  // Renes-Costello-Batina exception-free doubling formula.
468
498
  // There is 30% faster Jacobian formula, but it is not complete.
@@ -471,7 +501,7 @@ function weierstrassN(CURVE, curveOpts = {}) {
471
501
  double() {
472
502
  const { a, b } = CURVE;
473
503
  const b3 = Fp.mul(b, _3n);
474
- const { px: X1, py: Y1, pz: Z1 } = this;
504
+ const { X: X1, Y: Y1, Z: Z1 } = this;
475
505
  let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
476
506
  let t0 = Fp.mul(X1, X1); // step 1
477
507
  let t1 = Fp.mul(Y1, Y1);
@@ -512,8 +542,8 @@ function weierstrassN(CURVE, curveOpts = {}) {
512
542
  // Cost: 12M + 0S + 3*a + 3*b3 + 23add.
513
543
  add(other) {
514
544
  aprjpoint(other);
515
- const { px: X1, py: Y1, pz: Z1 } = this;
516
- const { px: X2, py: Y2, pz: Z2 } = other;
545
+ const { X: X1, Y: Y1, Z: Z1 } = this;
546
+ const { X: X2, Y: Y2, Z: Z2 } = other;
517
547
  let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
518
548
  const a = CURVE.a;
519
549
  const b3 = Fp.mul(CURVE.b, _3n);
@@ -579,10 +609,10 @@ function weierstrassN(CURVE, curveOpts = {}) {
579
609
  if (!Fn.isValidNot0(scalar))
580
610
  throw new Error('invalid scalar: out of range'); // 0 is invalid
581
611
  let point, fake; // Fake point is used to const-time mult
582
- const mul = (n) => wnaf.wNAFCached(this, n, Point.normalizeZ);
612
+ const mul = (n) => wnaf.cached(this, n, (p) => (0, curve_ts_1.normalizeZ)(Point, p));
583
613
  /** See docs for {@link EndomorphismOpts} */
584
614
  if (endo) {
585
- const { k1neg, k1, k2neg, k2 } = endo.splitScalar(scalar);
615
+ const { k1neg, k1, k2neg, k2 } = splitEndoScalarN(scalar);
586
616
  const { p: k1p, f: k1f } = mul(k1);
587
617
  const { p: k2p, f: k2f } = mul(k2);
588
618
  fake = k1f.add(k2f);
@@ -594,12 +624,12 @@ function weierstrassN(CURVE, curveOpts = {}) {
594
624
  fake = f;
595
625
  }
596
626
  // Normalize `z` for both points, but return only real one
597
- return Point.normalizeZ([point, fake])[0];
627
+ return (0, curve_ts_1.normalizeZ)(Point, [point, fake])[0];
598
628
  }
599
629
  /**
600
630
  * Non-constant-time multiplication. Uses double-and-add algorithm.
601
631
  * It's faster, but should only be used when you don't care about
602
- * an exposed private key e.g. sig verification, which works over *public* keys.
632
+ * an exposed secret key e.g. sig verification, which works over *public* keys.
603
633
  */
604
634
  multiplyUnsafe(sc) {
605
635
  const { endo } = curveOpts;
@@ -610,16 +640,15 @@ function weierstrassN(CURVE, curveOpts = {}) {
610
640
  return Point.ZERO;
611
641
  if (sc === _1n)
612
642
  return p; // fast-path
613
- if (wnaf.hasPrecomputes(this))
643
+ if (wnaf.hasCache(this))
614
644
  return this.multiply(sc);
615
645
  if (endo) {
616
- const { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc);
617
- // `wNAFCachedUnsafe` is 30% slower
618
- const { p1, p2 } = (0, curve_ts_1.mulEndoUnsafe)(Point, p, k1, k2);
646
+ const { k1neg, k1, k2neg, k2 } = splitEndoScalarN(sc);
647
+ const { p1, p2 } = (0, curve_ts_1.mulEndoUnsafe)(Point, p, k1, k2); // 30% faster vs wnaf.unsafe
619
648
  return finishEndo(endo.beta, p1, p2, k1neg, k2neg);
620
649
  }
621
650
  else {
622
- return wnaf.wNAFCachedUnsafe(p, sc);
651
+ return wnaf.unsafe(p, sc);
623
652
  }
624
653
  }
625
654
  multiplyAndAddUnsafe(Q, a, b) {
@@ -643,7 +672,7 @@ function weierstrassN(CURVE, curveOpts = {}) {
643
672
  return true;
644
673
  if (isTorsionFree)
645
674
  return isTorsionFree(Point, this);
646
- return wnaf.wNAFCachedUnsafe(this, CURVE_ORDER).is0();
675
+ return wnaf.unsafe(this, CURVE_ORDER).is0();
647
676
  }
648
677
  clearCofactor() {
649
678
  const { clearCofactor } = curveOpts;
@@ -653,6 +682,10 @@ function weierstrassN(CURVE, curveOpts = {}) {
653
682
  return clearCofactor(Point, this);
654
683
  return this.multiplyUnsafe(cofactor);
655
684
  }
685
+ isSmallOrder() {
686
+ // can we use this.clearCofactor()?
687
+ return this.multiplyUnsafe(cofactor).is0();
688
+ }
656
689
  toBytes(isCompressed = true) {
657
690
  (0, utils_ts_1.abool)('isCompressed', isCompressed);
658
691
  this.assertValidity();
@@ -677,10 +710,11 @@ function weierstrassN(CURVE, curveOpts = {}) {
677
710
  Point.Fp = Fp;
678
711
  Point.Fn = Fn;
679
712
  const bits = Fn.BITS;
680
- const wnaf = (0, curve_ts_1.wNAF)(Point, curveOpts.endo ? Math.ceil(bits / 2) : bits);
713
+ const wnaf = new curve_ts_1.wNAF(Point, curveOpts.endo ? Math.ceil(bits / 2) : bits);
681
714
  return Point;
682
715
  }
683
716
  // _legacyWeierstrass
717
+ // TODO: remove
684
718
  /** @deprecated use `weierstrassN` */
685
719
  function weierstrassPoints(c) {
686
720
  const { CURVE, curveOpts } = _weierstrass_legacy_opts_to_new(c);
@@ -691,8 +725,136 @@ function weierstrassPoints(c) {
691
725
  function pprefix(hasEvenY) {
692
726
  return Uint8Array.of(hasEvenY ? 0x02 : 0x03);
693
727
  }
694
- function ecdsa(Point, ecdsaOpts, curveOpts = {}) {
695
- (0, utils_ts_1._validateObject)(ecdsaOpts, { hash: 'function' }, {
728
+ /**
729
+ * Implementation of the Shallue and van de Woestijne method for any weierstrass curve.
730
+ * TODO: check if there is a way to merge this with uvRatio in Edwards; move to modular.
731
+ * b = True and y = sqrt(u / v) if (u / v) is square in F, and
732
+ * b = False and y = sqrt(Z * (u / v)) otherwise.
733
+ * @param Fp
734
+ * @param Z
735
+ * @returns
736
+ */
737
+ function SWUFpSqrtRatio(Fp, Z) {
738
+ // Generic implementation
739
+ const q = Fp.ORDER;
740
+ let l = _0n;
741
+ for (let o = q - _1n; o % _2n === _0n; o /= _2n)
742
+ l += _1n;
743
+ const c1 = l; // 1. c1, the largest integer such that 2^c1 divides q - 1.
744
+ // We need 2n ** c1 and 2n ** (c1-1). We can't use **; but we can use <<.
745
+ // 2n ** c1 == 2n << (c1-1)
746
+ const _2n_pow_c1_1 = _2n << (c1 - _1n - _1n);
747
+ const _2n_pow_c1 = _2n_pow_c1_1 * _2n;
748
+ const c2 = (q - _1n) / _2n_pow_c1; // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic
749
+ const c3 = (c2 - _1n) / _2n; // 3. c3 = (c2 - 1) / 2 # Integer arithmetic
750
+ const c4 = _2n_pow_c1 - _1n; // 4. c4 = 2^c1 - 1 # Integer arithmetic
751
+ const c5 = _2n_pow_c1_1; // 5. c5 = 2^(c1 - 1) # Integer arithmetic
752
+ const c6 = Fp.pow(Z, c2); // 6. c6 = Z^c2
753
+ const c7 = Fp.pow(Z, (c2 + _1n) / _2n); // 7. c7 = Z^((c2 + 1) / 2)
754
+ let sqrtRatio = (u, v) => {
755
+ let tv1 = c6; // 1. tv1 = c6
756
+ let tv2 = Fp.pow(v, c4); // 2. tv2 = v^c4
757
+ let tv3 = Fp.sqr(tv2); // 3. tv3 = tv2^2
758
+ tv3 = Fp.mul(tv3, v); // 4. tv3 = tv3 * v
759
+ let tv5 = Fp.mul(u, tv3); // 5. tv5 = u * tv3
760
+ tv5 = Fp.pow(tv5, c3); // 6. tv5 = tv5^c3
761
+ tv5 = Fp.mul(tv5, tv2); // 7. tv5 = tv5 * tv2
762
+ tv2 = Fp.mul(tv5, v); // 8. tv2 = tv5 * v
763
+ tv3 = Fp.mul(tv5, u); // 9. tv3 = tv5 * u
764
+ let tv4 = Fp.mul(tv3, tv2); // 10. tv4 = tv3 * tv2
765
+ tv5 = Fp.pow(tv4, c5); // 11. tv5 = tv4^c5
766
+ let isQR = Fp.eql(tv5, Fp.ONE); // 12. isQR = tv5 == 1
767
+ tv2 = Fp.mul(tv3, c7); // 13. tv2 = tv3 * c7
768
+ tv5 = Fp.mul(tv4, tv1); // 14. tv5 = tv4 * tv1
769
+ tv3 = Fp.cmov(tv2, tv3, isQR); // 15. tv3 = CMOV(tv2, tv3, isQR)
770
+ tv4 = Fp.cmov(tv5, tv4, isQR); // 16. tv4 = CMOV(tv5, tv4, isQR)
771
+ // 17. for i in (c1, c1 - 1, ..., 2):
772
+ for (let i = c1; i > _1n; i--) {
773
+ let tv5 = i - _2n; // 18. tv5 = i - 2
774
+ tv5 = _2n << (tv5 - _1n); // 19. tv5 = 2^tv5
775
+ let tvv5 = Fp.pow(tv4, tv5); // 20. tv5 = tv4^tv5
776
+ const e1 = Fp.eql(tvv5, Fp.ONE); // 21. e1 = tv5 == 1
777
+ tv2 = Fp.mul(tv3, tv1); // 22. tv2 = tv3 * tv1
778
+ tv1 = Fp.mul(tv1, tv1); // 23. tv1 = tv1 * tv1
779
+ tvv5 = Fp.mul(tv4, tv1); // 24. tv5 = tv4 * tv1
780
+ tv3 = Fp.cmov(tv2, tv3, e1); // 25. tv3 = CMOV(tv2, tv3, e1)
781
+ tv4 = Fp.cmov(tvv5, tv4, e1); // 26. tv4 = CMOV(tv5, tv4, e1)
782
+ }
783
+ return { isValid: isQR, value: tv3 };
784
+ };
785
+ if (Fp.ORDER % _4n === _3n) {
786
+ // sqrt_ratio_3mod4(u, v)
787
+ const c1 = (Fp.ORDER - _3n) / _4n; // 1. c1 = (q - 3) / 4 # Integer arithmetic
788
+ const c2 = Fp.sqrt(Fp.neg(Z)); // 2. c2 = sqrt(-Z)
789
+ sqrtRatio = (u, v) => {
790
+ let tv1 = Fp.sqr(v); // 1. tv1 = v^2
791
+ const tv2 = Fp.mul(u, v); // 2. tv2 = u * v
792
+ tv1 = Fp.mul(tv1, tv2); // 3. tv1 = tv1 * tv2
793
+ let y1 = Fp.pow(tv1, c1); // 4. y1 = tv1^c1
794
+ y1 = Fp.mul(y1, tv2); // 5. y1 = y1 * tv2
795
+ const y2 = Fp.mul(y1, c2); // 6. y2 = y1 * c2
796
+ const tv3 = Fp.mul(Fp.sqr(y1), v); // 7. tv3 = y1^2; 8. tv3 = tv3 * v
797
+ const isQR = Fp.eql(tv3, u); // 9. isQR = tv3 == u
798
+ let y = Fp.cmov(y2, y1, isQR); // 10. y = CMOV(y2, y1, isQR)
799
+ return { isValid: isQR, value: y }; // 11. return (isQR, y) isQR ? y : y*c2
800
+ };
801
+ }
802
+ // No curves uses that
803
+ // if (Fp.ORDER % _8n === _5n) // sqrt_ratio_5mod8
804
+ return sqrtRatio;
805
+ }
806
+ /**
807
+ * Simplified Shallue-van de Woestijne-Ulas Method
808
+ * https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2
809
+ */
810
+ function mapToCurveSimpleSWU(Fp, opts) {
811
+ (0, modular_ts_1.validateField)(Fp);
812
+ const { A, B, Z } = opts;
813
+ if (!Fp.isValid(A) || !Fp.isValid(B) || !Fp.isValid(Z))
814
+ throw new Error('mapToCurveSimpleSWU: invalid opts');
815
+ const sqrtRatio = SWUFpSqrtRatio(Fp, Z);
816
+ if (!Fp.isOdd)
817
+ throw new Error('Field does not have .isOdd()');
818
+ // Input: u, an element of F.
819
+ // Output: (x, y), a point on E.
820
+ return (u) => {
821
+ // prettier-ignore
822
+ let tv1, tv2, tv3, tv4, tv5, tv6, x, y;
823
+ tv1 = Fp.sqr(u); // 1. tv1 = u^2
824
+ tv1 = Fp.mul(tv1, Z); // 2. tv1 = Z * tv1
825
+ tv2 = Fp.sqr(tv1); // 3. tv2 = tv1^2
826
+ tv2 = Fp.add(tv2, tv1); // 4. tv2 = tv2 + tv1
827
+ tv3 = Fp.add(tv2, Fp.ONE); // 5. tv3 = tv2 + 1
828
+ tv3 = Fp.mul(tv3, B); // 6. tv3 = B * tv3
829
+ tv4 = Fp.cmov(Z, Fp.neg(tv2), !Fp.eql(tv2, Fp.ZERO)); // 7. tv4 = CMOV(Z, -tv2, tv2 != 0)
830
+ tv4 = Fp.mul(tv4, A); // 8. tv4 = A * tv4
831
+ tv2 = Fp.sqr(tv3); // 9. tv2 = tv3^2
832
+ tv6 = Fp.sqr(tv4); // 10. tv6 = tv4^2
833
+ tv5 = Fp.mul(tv6, A); // 11. tv5 = A * tv6
834
+ tv2 = Fp.add(tv2, tv5); // 12. tv2 = tv2 + tv5
835
+ tv2 = Fp.mul(tv2, tv3); // 13. tv2 = tv2 * tv3
836
+ tv6 = Fp.mul(tv6, tv4); // 14. tv6 = tv6 * tv4
837
+ tv5 = Fp.mul(tv6, B); // 15. tv5 = B * tv6
838
+ tv2 = Fp.add(tv2, tv5); // 16. tv2 = tv2 + tv5
839
+ x = Fp.mul(tv1, tv3); // 17. x = tv1 * tv3
840
+ const { isValid, value } = sqrtRatio(tv2, tv6); // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6)
841
+ y = Fp.mul(tv1, u); // 19. y = tv1 * u -> Z * u^3 * y1
842
+ y = Fp.mul(y, value); // 20. y = y * y1
843
+ x = Fp.cmov(x, tv3, isValid); // 21. x = CMOV(x, tv3, is_gx1_square)
844
+ y = Fp.cmov(y, value, isValid); // 22. y = CMOV(y, y1, is_gx1_square)
845
+ const e1 = Fp.isOdd(u) === Fp.isOdd(y); // 23. e1 = sgn0(u) == sgn0(y)
846
+ y = Fp.cmov(Fp.neg(y), y, e1); // 24. y = CMOV(-y, y, e1)
847
+ const tv4_inv = (0, modular_ts_1.FpInvertBatch)(Fp, [tv4], true)[0];
848
+ x = Fp.mul(x, tv4_inv); // 25. x = x / tv4
849
+ return { x, y };
850
+ };
851
+ }
852
+ /**
853
+ * Creates ECDSA for given elliptic curve Point and hash function.
854
+ */
855
+ function ecdsa(Point, hash, ecdsaOpts = {}) {
856
+ (0, utils_1.ahash)(hash);
857
+ (0, utils_ts_1._validateObject)(ecdsaOpts, {}, {
696
858
  hmac: 'function',
697
859
  lowS: 'boolean',
698
860
  randomBytes: 'function',
@@ -701,9 +863,17 @@ function ecdsa(Point, ecdsaOpts, curveOpts = {}) {
701
863
  });
702
864
  const randomBytes_ = ecdsaOpts.randomBytes || utils_ts_1.randomBytes;
703
865
  const hmac_ = ecdsaOpts.hmac ||
704
- ((key, ...msgs) => (0, hmac_js_1.hmac)(ecdsaOpts.hash, key, (0, utils_ts_1.concatBytes)(...msgs)));
866
+ ((key, ...msgs) => (0, hmac_js_1.hmac)(hash, key, (0, utils_ts_1.concatBytes)(...msgs)));
705
867
  const { Fp, Fn } = Point;
706
868
  const { ORDER: CURVE_ORDER, BITS: fnBits } = Fn;
869
+ const seedLen = (0, modular_ts_1.getMinHashLength)(CURVE_ORDER);
870
+ const lengths = {
871
+ secret: Fn.BYTES,
872
+ public: 1 + Fp.BYTES,
873
+ publicUncompressed: 1 + 2 * Fp.BYTES,
874
+ signature: 2 * Fn.BYTES,
875
+ seed: seedLen,
876
+ };
707
877
  function isBiggerThanHalfOrder(number) {
708
878
  const HALF = CURVE_ORDER >> _1n;
709
879
  return number > HALF;
@@ -728,23 +898,24 @@ function ecdsa(Point, ecdsaOpts, curveOpts = {}) {
728
898
  this.recovery = recovery;
729
899
  Object.freeze(this);
730
900
  }
731
- // pair (bytes of r, bytes of s)
732
- static fromCompact(hex) {
733
- const L = Fn.BYTES;
734
- const b = (0, utils_ts_1.ensureBytes)('compactSignature', hex, L * 2);
735
- return new Signature(Fn.fromBytes(b.subarray(0, L)), Fn.fromBytes(b.subarray(L, L * 2)));
901
+ static fromBytes(bytes, format = 'compact') {
902
+ if (format === 'compact') {
903
+ const L = Fn.BYTES;
904
+ (0, utils_ts_1.abytes)(bytes, L * 2);
905
+ const r = bytes.subarray(0, L);
906
+ const s = bytes.subarray(L, L * 2);
907
+ return new Signature(Fn.fromBytes(r), Fn.fromBytes(s));
908
+ }
909
+ if (format === 'der') {
910
+ (0, utils_ts_1.abytes)(bytes);
911
+ const { r, s } = exports.DER.toSig(bytes);
912
+ return new Signature(r, s);
913
+ }
914
+ throw new Error('invalid format');
736
915
  }
737
- // DER encoded ECDSA signature
738
- // https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script
739
- static fromDER(hex) {
740
- const { r, s } = exports.DER.toSig((0, utils_ts_1.ensureBytes)('DER', hex));
741
- return new Signature(r, s);
916
+ static fromHex(hex, format) {
917
+ return this.fromBytes((0, utils_ts_1.hexToBytes)(hex), format);
742
918
  }
743
- /**
744
- * @todo remove
745
- * @deprecated
746
- */
747
- assertValidity() { }
748
919
  addRecoveryBit(recovery) {
749
920
  return new Signature(this.r, this.s, recovery);
750
921
  }
@@ -788,21 +959,30 @@ function ecdsa(Point, ecdsaOpts, curveOpts = {}) {
788
959
  normalizeS() {
789
960
  return this.hasHighS() ? new Signature(this.r, Fn.neg(this.s), this.recovery) : this;
790
961
  }
791
- toBytes(format) {
962
+ toBytes(format = 'compact') {
792
963
  if (format === 'compact')
793
964
  return (0, utils_ts_1.concatBytes)(Fn.toBytes(this.r), Fn.toBytes(this.s));
794
965
  if (format === 'der')
795
966
  return (0, utils_ts_1.hexToBytes)(exports.DER.hexFromSig(this));
796
967
  throw new Error('invalid format');
797
968
  }
798
- // DER-encoded
969
+ toHex(format) {
970
+ return (0, utils_ts_1.bytesToHex)(this.toBytes(format));
971
+ }
972
+ // TODO: remove
973
+ assertValidity() { }
974
+ static fromCompact(hex) {
975
+ return Signature.fromBytes((0, utils_ts_1.ensureBytes)('sig', hex), 'compact');
976
+ }
977
+ static fromDER(hex) {
978
+ return Signature.fromBytes((0, utils_ts_1.ensureBytes)('sig', hex), 'der');
979
+ }
799
980
  toDERRawBytes() {
800
981
  return this.toBytes('der');
801
982
  }
802
983
  toDERHex() {
803
984
  return (0, utils_ts_1.bytesToHex)(this.toBytes('der'));
804
985
  }
805
- // padded bytes of r, then padded bytes of s
806
986
  toCompactRawBytes() {
807
987
  return this.toBytes('compact');
808
988
  }
@@ -810,76 +990,85 @@ function ecdsa(Point, ecdsaOpts, curveOpts = {}) {
810
990
  return (0, utils_ts_1.bytesToHex)(this.toBytes('compact'));
811
991
  }
812
992
  }
813
- const normPrivateKeyToScalar = _legacyHelperNormPriv(Fn, curveOpts.allowedPrivateKeyLengths, curveOpts.wrapPrivateKey);
814
- const utils = {
815
- isValidPrivateKey(privateKey) {
816
- try {
817
- normPrivateKeyToScalar(privateKey);
818
- return true;
819
- }
820
- catch (error) {
993
+ function isValidSecretKey(privateKey) {
994
+ try {
995
+ return !!_normFnElement(Fn, privateKey);
996
+ }
997
+ catch (error) {
998
+ return false;
999
+ }
1000
+ }
1001
+ function isValidPublicKey(publicKey, isCompressed) {
1002
+ try {
1003
+ const l = publicKey.length;
1004
+ if (isCompressed === true && l !== lengths.public)
821
1005
  return false;
822
- }
823
- },
824
- normPrivateKeyToScalar: normPrivateKeyToScalar,
825
- /**
826
- * Produces cryptographically secure private key from random of size
827
- * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible.
828
- */
829
- randomPrivateKey: () => {
830
- const n = CURVE_ORDER;
831
- return (0, modular_ts_1.mapHashToField)(randomBytes_((0, modular_ts_1.getMinHashLength)(n)), n);
832
- },
1006
+ if (isCompressed === false && l !== lengths.publicUncompressed)
1007
+ return false;
1008
+ return !!Point.fromBytes(publicKey);
1009
+ }
1010
+ catch (error) {
1011
+ return false;
1012
+ }
1013
+ }
1014
+ /**
1015
+ * Produces cryptographically secure secret key from random of size
1016
+ * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible.
1017
+ */
1018
+ function randomSecretKey(seed = randomBytes_(seedLen)) {
1019
+ return (0, modular_ts_1.mapHashToField)(seed, CURVE_ORDER);
1020
+ }
1021
+ const utils = {
1022
+ isValidSecretKey,
1023
+ isValidPublicKey,
1024
+ randomSecretKey,
1025
+ // TODO: remove
1026
+ isValidPrivateKey: isValidSecretKey,
1027
+ randomPrivateKey: randomSecretKey,
1028
+ normPrivateKeyToScalar: (key) => _normFnElement(Fn, key),
833
1029
  precompute(windowSize = 8, point = Point.BASE) {
834
1030
  return point.precompute(windowSize, false);
835
1031
  },
836
1032
  };
837
1033
  /**
838
- * Computes public key for a private key. Checks for validity of the private key.
839
- * @param privateKey private key
1034
+ * Computes public key for a secret key. Checks for validity of the secret key.
840
1035
  * @param isCompressed whether to return compact (default), or full key
841
1036
  * @returns Public key, full when isCompressed=false; short when isCompressed=true
842
1037
  */
843
- function getPublicKey(privateKey, isCompressed = true) {
844
- return Point.fromPrivateKey(privateKey).toBytes(isCompressed);
1038
+ function getPublicKey(secretKey, isCompressed = true) {
1039
+ return Point.BASE.multiply(_normFnElement(Fn, secretKey)).toBytes(isCompressed);
845
1040
  }
846
1041
  /**
847
1042
  * Quick and dirty check for item being public key. Does not validate hex, or being on-curve.
848
1043
  */
849
1044
  function isProbPub(item) {
1045
+ // TODO: remove
850
1046
  if (typeof item === 'bigint')
851
1047
  return false;
1048
+ // TODO: remove
852
1049
  if (item instanceof Point)
853
1050
  return true;
854
- const arr = (0, utils_ts_1.ensureBytes)('key', item);
855
- const length = arr.length;
856
- const L = Fp.BYTES;
857
- const LC = L + 1; // e.g. 33 for 32
858
- const LU = 2 * L + 1; // e.g. 65 for 32
859
- if (curveOpts.allowedPrivateKeyLengths || Fn.BYTES === LC) {
1051
+ if (Fn.allowedLengths || lengths.secret === lengths.public)
860
1052
  return undefined;
861
- }
862
- else {
863
- return length === LC || length === LU;
864
- }
1053
+ const l = (0, utils_ts_1.ensureBytes)('key', item).length;
1054
+ return l === lengths.public || l === lengths.publicUncompressed;
865
1055
  }
866
1056
  /**
867
1057
  * ECDH (Elliptic Curve Diffie Hellman).
868
- * Computes shared public key from private key and public key.
869
- * Checks: 1) private key validity 2) shared key is on-curve.
1058
+ * Computes shared public key from secret key A and public key B.
1059
+ * Checks: 1) secret key validity 2) shared key is on-curve.
870
1060
  * Does NOT hash the result.
871
- * @param privateA private key
872
- * @param publicB different public key
873
1061
  * @param isCompressed whether to return compact (default), or full key
874
1062
  * @returns shared public key
875
1063
  */
876
- function getSharedSecret(privateA, publicB, isCompressed = true) {
877
- if (isProbPub(privateA) === true)
1064
+ function getSharedSecret(secretKeyA, publicKeyB, isCompressed = true) {
1065
+ if (isProbPub(secretKeyA) === true)
878
1066
  throw new Error('first arg must be private key');
879
- if (isProbPub(publicB) === false)
1067
+ if (isProbPub(publicKeyB) === false)
880
1068
  throw new Error('second arg must be public key');
881
- const b = Point.fromHex(publicB); // check for being on-curve
882
- return b.multiply(normPrivateKeyToScalar(privateA)).toBytes(isCompressed);
1069
+ const s = _normFnElement(Fn, secretKeyA);
1070
+ const b = Point.fromHex(publicKeyB); // checks for being on-curve
1071
+ return b.multiply(s).toBytes(isCompressed);
883
1072
  }
884
1073
  // RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets.
885
1074
  // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int.
@@ -918,7 +1107,6 @@ function ecdsa(Point, ecdsaOpts, curveOpts = {}) {
918
1107
  function prepSig(msgHash, privateKey, opts = defaultSigOpts) {
919
1108
  if (['recovered', 'canonical'].some((k) => k in opts))
920
1109
  throw new Error('sign() legacy options not supported');
921
- const { hash } = ecdsaOpts;
922
1110
  let { lowS, prehash, extraEntropy: ent } = opts; // generates low-s sigs by default
923
1111
  if (lowS == null)
924
1112
  lowS = true; // RFC6979 3.2: we skip step A, because we already provide hash
@@ -930,17 +1118,21 @@ function ecdsa(Point, ecdsaOpts, curveOpts = {}) {
930
1118
  // with fnBits % 8 !== 0. Because of that, we unwrap it here as int2octets call.
931
1119
  // const bits2octets = (bits) => int2octets(bits2int_modN(bits))
932
1120
  const h1int = bits2int_modN(msgHash);
933
- const d = normPrivateKeyToScalar(privateKey); // validate private key, convert to bigint
1121
+ const d = _normFnElement(Fn, privateKey); // validate secret key, convert to bigint
934
1122
  const seedArgs = [int2octets(d), int2octets(h1int)];
935
1123
  // extraEntropy. RFC6979 3.6: additional k' (optional).
936
1124
  if (ent != null && ent !== false) {
937
1125
  // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
938
- const e = ent === true ? randomBytes_(Fp.BYTES) : ent; // generate random bytes OR pass as-is
1126
+ const e = ent === true ? randomBytes_(lengths.secret) : ent; // gen random bytes OR pass as-is
939
1127
  seedArgs.push((0, utils_ts_1.ensureBytes)('extraEntropy', e)); // check for being bytes
940
1128
  }
941
1129
  const seed = (0, utils_ts_1.concatBytes)(...seedArgs); // Step D of RFC6979 3.2
942
1130
  const m = h1int; // NOTE: no need to call bits2int second time here, it is inside truncateHash!
943
1131
  // Converts signature params into point w r/s, checks result for validity.
1132
+ // To transform k => Signature:
1133
+ // q = k⋅G
1134
+ // r = q.x mod n
1135
+ // s = k^-1(m + rd) mod n
944
1136
  // Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q−1] according to
945
1137
  // https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it:
946
1138
  // a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT
@@ -951,7 +1143,7 @@ function ecdsa(Point, ecdsaOpts, curveOpts = {}) {
951
1143
  if (!Fn.isValidNot0(k))
952
1144
  return; // Valid scalars (including k) must be in 1..N-1
953
1145
  const ik = Fn.inv(k); // k^-1 mod n
954
- const q = Point.BASE.multiply(k).toAffine(); // q = Gk
1146
+ const q = Point.BASE.multiply(k).toAffine(); // q = k⋅G
955
1147
  const r = Fn.create(q.x); // r = q.x mod n
956
1148
  if (r === _0n)
957
1149
  return;
@@ -971,21 +1163,17 @@ function ecdsa(Point, ecdsaOpts, curveOpts = {}) {
971
1163
  const defaultSigOpts = { lowS: ecdsaOpts.lowS, prehash: false };
972
1164
  const defaultVerOpts = { lowS: ecdsaOpts.lowS, prehash: false };
973
1165
  /**
974
- * Signs message hash with a private key.
1166
+ * Signs message hash with a secret key.
975
1167
  * ```
976
1168
  * sign(m, d, k) where
977
1169
  * (x, y) = G × k
978
1170
  * r = x mod n
979
1171
  * s = (m + dr)/k mod n
980
1172
  * ```
981
- * @param msgHash NOT message. msg needs to be hashed to `msgHash`, or use `prehash`.
982
- * @param privKey private key
983
- * @param opts lowS for non-malleable sigs. extraEntropy for mixing randomness into k. prehash will hash first arg.
984
- * @returns signature with recovery param
985
1173
  */
986
- function sign(msgHash, privKey, opts = defaultSigOpts) {
987
- const { seed, k2sig } = prepSig(msgHash, privKey, opts); // Steps A, D of RFC6979 3.2.
988
- const drbg = (0, utils_ts_1.createHmacDrbg)(ecdsaOpts.hash.outputLen, Fn.BYTES, hmac_);
1174
+ function sign(msgHash, secretKey, opts = defaultSigOpts) {
1175
+ const { seed, k2sig } = prepSig(msgHash, secretKey, opts); // Steps A, D of RFC6979 3.2.
1176
+ const drbg = (0, utils_ts_1.createHmacDrbg)(hash.outputLen, Fn.BYTES, hmac_);
989
1177
  return drbg(seed, k2sig); // Steps B, C, D, E, F, G
990
1178
  }
991
1179
  // Enable precomputes. Slows down first publicKey computation by 20ms.
@@ -1013,88 +1201,98 @@ function ecdsa(Point, ecdsaOpts, curveOpts = {}) {
1013
1201
  // TODO: remove
1014
1202
  if ('strict' in opts)
1015
1203
  throw new Error('options.strict was renamed to lowS');
1016
- if (format !== undefined && !['compact', 'der', 'js'].includes(format))
1017
- throw new Error('format must be "compact", "der" or "js"');
1018
- const isHex = typeof sg === 'string' || (0, utils_ts_1.isBytes)(sg);
1019
- const isObj = !isHex &&
1020
- !format &&
1021
- typeof sg === 'object' &&
1022
- sg !== null &&
1023
- typeof sg.r === 'bigint' &&
1024
- typeof sg.s === 'bigint';
1025
- if (!isHex && !isObj)
1026
- throw new Error('invalid signature, expected Uint8Array, hex string or Signature instance');
1027
1204
  let _sig = undefined;
1028
1205
  let P;
1029
- // deduce signature format
1030
- try {
1031
- // if (format === 'js') {
1032
- // if (sg != null && !isBytes(sg)) _sig = new Signature(sg.r, sg.s);
1033
- // } else if (format === 'compact') {
1034
- // _sig = Signature.fromCompact(sg);
1035
- // } else if (format === 'der') {
1036
- // _sig = Signature.fromDER(sg);
1037
- // } else {
1038
- // throw new Error('invalid format');
1039
- // }
1206
+ if (format === undefined) {
1207
+ // Try to deduce format
1208
+ const isHex = typeof sg === 'string' || (0, utils_ts_1.isBytes)(sg);
1209
+ const isObj = !isHex &&
1210
+ sg !== null &&
1211
+ typeof sg === 'object' &&
1212
+ typeof sg.r === 'bigint' &&
1213
+ typeof sg.s === 'bigint';
1214
+ if (!isHex && !isObj)
1215
+ throw new Error('invalid signature, expected Uint8Array, hex string or Signature instance');
1040
1216
  if (isObj) {
1041
- if (format === undefined || format === 'js') {
1042
- _sig = new Signature(sg.r, sg.s);
1043
- }
1044
- else {
1045
- throw new Error('invalid format');
1046
- }
1217
+ _sig = new Signature(sg.r, sg.s);
1047
1218
  }
1048
- if (isHex) {
1219
+ else if (isHex) {
1049
1220
  // TODO: remove this malleable check
1050
1221
  // Signature can be represented in 2 ways: compact (2*Fn.BYTES) & DER (variable-length).
1051
1222
  // Since DER can also be 2*Fn.BYTES bytes, we check for it first.
1052
1223
  try {
1053
- if (format !== 'compact')
1054
- _sig = Signature.fromDER(sg);
1224
+ _sig = Signature.fromDER(sg);
1055
1225
  }
1056
1226
  catch (derError) {
1057
1227
  if (!(derError instanceof exports.DER.Err))
1058
1228
  throw derError;
1059
1229
  }
1060
- if (!_sig && format !== 'der')
1061
- _sig = Signature.fromCompact(sg);
1230
+ if (!_sig) {
1231
+ try {
1232
+ _sig = Signature.fromCompact(sg);
1233
+ }
1234
+ catch (error) {
1235
+ return false;
1236
+ }
1237
+ }
1062
1238
  }
1063
- P = Point.fromHex(publicKey);
1064
1239
  }
1065
- catch (error) {
1066
- return false;
1240
+ else {
1241
+ if (format === 'compact' || format === 'der') {
1242
+ if (typeof sg !== 'string' && !(0, utils_ts_1.isBytes)(sg))
1243
+ throw new Error('"der" / "compact" format expects Uint8Array signature');
1244
+ _sig = Signature.fromBytes((0, utils_ts_1.ensureBytes)('sig', sg), format);
1245
+ }
1246
+ else if (format === 'js') {
1247
+ if (!(sg instanceof Signature))
1248
+ throw new Error('"js" format expects Signature instance');
1249
+ _sig = sg;
1250
+ }
1251
+ else {
1252
+ throw new Error('format must be "compact", "der" or "js"');
1253
+ }
1067
1254
  }
1068
1255
  if (!_sig)
1069
1256
  return false;
1070
- if (lowS && _sig.hasHighS())
1071
- return false;
1072
- // todo: optional.hash => hash
1073
- if (prehash)
1074
- msgHash = ecdsaOpts.hash(msgHash);
1075
- const { r, s } = _sig;
1076
- const h = bits2int_modN(msgHash); // Cannot use fields methods, since it is group element
1077
- const is = Fn.inv(s); // s^-1
1078
- const u1 = Fn.create(h * is); // u1 = hs^-1 mod n
1079
- const u2 = Fn.create(r * is); // u2 = rs^-1 mod n
1080
- const R = Point.BASE.multiplyUnsafe(u1).add(P.multiplyUnsafe(u2));
1081
- if (R.is0())
1257
+ try {
1258
+ P = Point.fromHex(publicKey);
1259
+ if (lowS && _sig.hasHighS())
1260
+ return false;
1261
+ // todo: optional.hash => hash
1262
+ if (prehash)
1263
+ msgHash = hash(msgHash);
1264
+ const { r, s } = _sig;
1265
+ const h = bits2int_modN(msgHash); // Cannot use fields methods, since it is group element
1266
+ const is = Fn.inv(s); // s^-1
1267
+ const u1 = Fn.create(h * is); // u1 = hs^-1 mod n
1268
+ const u2 = Fn.create(r * is); // u2 = rs^-1 mod n
1269
+ const R = Point.BASE.multiplyUnsafe(u1).add(P.multiplyUnsafe(u2));
1270
+ if (R.is0())
1271
+ return false;
1272
+ const v = Fn.create(R.x); // v = r.x mod n
1273
+ return v === r;
1274
+ }
1275
+ catch (e) {
1082
1276
  return false;
1083
- const v = Fn.create(R.x); // v = r.x mod n
1084
- return v === r;
1277
+ }
1278
+ }
1279
+ function keygen(seed) {
1280
+ const secretKey = utils.randomSecretKey(seed);
1281
+ return { secretKey, publicKey: getPublicKey(secretKey) };
1085
1282
  }
1086
- // TODO: clarify API for cloning .clone({hash: sha512}) ? .createWith({hash: sha512})?
1087
- // const clone = (hash: CHash): ECDSA => ecdsa(Point, { ...ecdsaOpts, ...getHash(hash) }, curveOpts);
1088
1283
  return Object.freeze({
1284
+ keygen,
1089
1285
  getPublicKey,
1090
- getSharedSecret,
1091
1286
  sign,
1092
1287
  verify,
1288
+ getSharedSecret,
1093
1289
  utils,
1094
1290
  Point,
1095
1291
  Signature,
1292
+ info: { type: 'weierstrass', lengths, publicKeyHasPrefix: true },
1096
1293
  });
1097
1294
  }
1295
+ // TODO: remove
1098
1296
  function _weierstrass_legacy_opts_to_new(c) {
1099
1297
  const CURVE = {
1100
1298
  a: c.a,
@@ -1106,14 +1304,19 @@ function _weierstrass_legacy_opts_to_new(c) {
1106
1304
  Gy: c.Gy,
1107
1305
  };
1108
1306
  const Fp = c.Fp;
1109
- const Fn = (0, modular_ts_1.Field)(CURVE.n, c.nBitLength);
1307
+ let allowedLengths = c.allowedPrivateKeyLengths
1308
+ ? Array.from(new Set(c.allowedPrivateKeyLengths.map((l) => Math.ceil(l / 2))))
1309
+ : undefined;
1310
+ const Fn = (0, modular_ts_1.Field)(CURVE.n, {
1311
+ BITS: c.nBitLength,
1312
+ allowedLengths: allowedLengths,
1313
+ modOnDecode: c.wrapPrivateKey,
1314
+ });
1110
1315
  const curveOpts = {
1111
1316
  Fp,
1112
1317
  Fn,
1113
- allowedPrivateKeyLengths: c.allowedPrivateKeyLengths,
1114
1318
  allowInfinityPoint: c.allowInfinityPoint,
1115
1319
  endo: c.endo,
1116
- wrapPrivateKey: c.wrapPrivateKey,
1117
1320
  isTorsionFree: c.isTorsionFree,
1118
1321
  clearCofactor: c.clearCofactor,
1119
1322
  fromBytes: c.fromBytes,
@@ -1124,15 +1327,15 @@ function _weierstrass_legacy_opts_to_new(c) {
1124
1327
  function _ecdsa_legacy_opts_to_new(c) {
1125
1328
  const { CURVE, curveOpts } = _weierstrass_legacy_opts_to_new(c);
1126
1329
  const ecdsaOpts = {
1127
- hash: c.hash,
1128
1330
  hmac: c.hmac,
1129
1331
  randomBytes: c.randomBytes,
1130
1332
  lowS: c.lowS,
1131
1333
  bits2int: c.bits2int,
1132
1334
  bits2int_modN: c.bits2int_modN,
1133
1335
  };
1134
- return { CURVE, curveOpts, ecdsaOpts };
1336
+ return { CURVE, curveOpts, hash: c.hash, ecdsaOpts };
1135
1337
  }
1338
+ // TODO: remove
1136
1339
  function _weierstrass_new_output_to_legacy(c, Point) {
1137
1340
  const { Fp, Fn } = Point;
1138
1341
  // TODO: remove
@@ -1140,16 +1343,16 @@ function _weierstrass_new_output_to_legacy(c, Point) {
1140
1343
  return (0, utils_ts_1.inRange)(num, _1n, Fn.ORDER);
1141
1344
  }
1142
1345
  const weierstrassEquation = _legacyHelperEquat(Fp, c.a, c.b);
1143
- const normPrivateKeyToScalar = _legacyHelperNormPriv(Fn, c.allowedPrivateKeyLengths, c.wrapPrivateKey);
1144
1346
  return Object.assign({}, {
1145
1347
  CURVE: c,
1146
1348
  Point: Point,
1147
1349
  ProjectivePoint: Point,
1148
- normPrivateKeyToScalar,
1350
+ normPrivateKeyToScalar: (key) => _normFnElement(Fn, key),
1149
1351
  weierstrassEquation,
1150
1352
  isWithinCurveOrder,
1151
1353
  });
1152
1354
  }
1355
+ // TODO: remove
1153
1356
  function _ecdsa_new_output_to_legacy(c, ecdsa) {
1154
1357
  return Object.assign({}, ecdsa, {
1155
1358
  ProjectivePoint: ecdsa.Point,
@@ -1158,133 +1361,9 @@ function _ecdsa_new_output_to_legacy(c, ecdsa) {
1158
1361
  }
1159
1362
  // _ecdsa_legacy
1160
1363
  function weierstrass(c) {
1161
- const { CURVE, curveOpts, ecdsaOpts } = _ecdsa_legacy_opts_to_new(c);
1364
+ const { CURVE, curveOpts, hash, ecdsaOpts } = _ecdsa_legacy_opts_to_new(c);
1162
1365
  const Point = weierstrassN(CURVE, curveOpts);
1163
- const signs = ecdsa(Point, ecdsaOpts, curveOpts);
1366
+ const signs = ecdsa(Point, hash, ecdsaOpts);
1164
1367
  return _ecdsa_new_output_to_legacy(c, signs);
1165
1368
  }
1166
- /**
1167
- * Implementation of the Shallue and van de Woestijne method for any weierstrass curve.
1168
- * TODO: check if there is a way to merge this with uvRatio in Edwards; move to modular.
1169
- * b = True and y = sqrt(u / v) if (u / v) is square in F, and
1170
- * b = False and y = sqrt(Z * (u / v)) otherwise.
1171
- * @param Fp
1172
- * @param Z
1173
- * @returns
1174
- */
1175
- function SWUFpSqrtRatio(Fp, Z) {
1176
- // Generic implementation
1177
- const q = Fp.ORDER;
1178
- let l = _0n;
1179
- for (let o = q - _1n; o % _2n === _0n; o /= _2n)
1180
- l += _1n;
1181
- const c1 = l; // 1. c1, the largest integer such that 2^c1 divides q - 1.
1182
- // We need 2n ** c1 and 2n ** (c1-1). We can't use **; but we can use <<.
1183
- // 2n ** c1 == 2n << (c1-1)
1184
- const _2n_pow_c1_1 = _2n << (c1 - _1n - _1n);
1185
- const _2n_pow_c1 = _2n_pow_c1_1 * _2n;
1186
- const c2 = (q - _1n) / _2n_pow_c1; // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic
1187
- const c3 = (c2 - _1n) / _2n; // 3. c3 = (c2 - 1) / 2 # Integer arithmetic
1188
- const c4 = _2n_pow_c1 - _1n; // 4. c4 = 2^c1 - 1 # Integer arithmetic
1189
- const c5 = _2n_pow_c1_1; // 5. c5 = 2^(c1 - 1) # Integer arithmetic
1190
- const c6 = Fp.pow(Z, c2); // 6. c6 = Z^c2
1191
- const c7 = Fp.pow(Z, (c2 + _1n) / _2n); // 7. c7 = Z^((c2 + 1) / 2)
1192
- let sqrtRatio = (u, v) => {
1193
- let tv1 = c6; // 1. tv1 = c6
1194
- let tv2 = Fp.pow(v, c4); // 2. tv2 = v^c4
1195
- let tv3 = Fp.sqr(tv2); // 3. tv3 = tv2^2
1196
- tv3 = Fp.mul(tv3, v); // 4. tv3 = tv3 * v
1197
- let tv5 = Fp.mul(u, tv3); // 5. tv5 = u * tv3
1198
- tv5 = Fp.pow(tv5, c3); // 6. tv5 = tv5^c3
1199
- tv5 = Fp.mul(tv5, tv2); // 7. tv5 = tv5 * tv2
1200
- tv2 = Fp.mul(tv5, v); // 8. tv2 = tv5 * v
1201
- tv3 = Fp.mul(tv5, u); // 9. tv3 = tv5 * u
1202
- let tv4 = Fp.mul(tv3, tv2); // 10. tv4 = tv3 * tv2
1203
- tv5 = Fp.pow(tv4, c5); // 11. tv5 = tv4^c5
1204
- let isQR = Fp.eql(tv5, Fp.ONE); // 12. isQR = tv5 == 1
1205
- tv2 = Fp.mul(tv3, c7); // 13. tv2 = tv3 * c7
1206
- tv5 = Fp.mul(tv4, tv1); // 14. tv5 = tv4 * tv1
1207
- tv3 = Fp.cmov(tv2, tv3, isQR); // 15. tv3 = CMOV(tv2, tv3, isQR)
1208
- tv4 = Fp.cmov(tv5, tv4, isQR); // 16. tv4 = CMOV(tv5, tv4, isQR)
1209
- // 17. for i in (c1, c1 - 1, ..., 2):
1210
- for (let i = c1; i > _1n; i--) {
1211
- let tv5 = i - _2n; // 18. tv5 = i - 2
1212
- tv5 = _2n << (tv5 - _1n); // 19. tv5 = 2^tv5
1213
- let tvv5 = Fp.pow(tv4, tv5); // 20. tv5 = tv4^tv5
1214
- const e1 = Fp.eql(tvv5, Fp.ONE); // 21. e1 = tv5 == 1
1215
- tv2 = Fp.mul(tv3, tv1); // 22. tv2 = tv3 * tv1
1216
- tv1 = Fp.mul(tv1, tv1); // 23. tv1 = tv1 * tv1
1217
- tvv5 = Fp.mul(tv4, tv1); // 24. tv5 = tv4 * tv1
1218
- tv3 = Fp.cmov(tv2, tv3, e1); // 25. tv3 = CMOV(tv2, tv3, e1)
1219
- tv4 = Fp.cmov(tvv5, tv4, e1); // 26. tv4 = CMOV(tv5, tv4, e1)
1220
- }
1221
- return { isValid: isQR, value: tv3 };
1222
- };
1223
- if (Fp.ORDER % _4n === _3n) {
1224
- // sqrt_ratio_3mod4(u, v)
1225
- const c1 = (Fp.ORDER - _3n) / _4n; // 1. c1 = (q - 3) / 4 # Integer arithmetic
1226
- const c2 = Fp.sqrt(Fp.neg(Z)); // 2. c2 = sqrt(-Z)
1227
- sqrtRatio = (u, v) => {
1228
- let tv1 = Fp.sqr(v); // 1. tv1 = v^2
1229
- const tv2 = Fp.mul(u, v); // 2. tv2 = u * v
1230
- tv1 = Fp.mul(tv1, tv2); // 3. tv1 = tv1 * tv2
1231
- let y1 = Fp.pow(tv1, c1); // 4. y1 = tv1^c1
1232
- y1 = Fp.mul(y1, tv2); // 5. y1 = y1 * tv2
1233
- const y2 = Fp.mul(y1, c2); // 6. y2 = y1 * c2
1234
- const tv3 = Fp.mul(Fp.sqr(y1), v); // 7. tv3 = y1^2; 8. tv3 = tv3 * v
1235
- const isQR = Fp.eql(tv3, u); // 9. isQR = tv3 == u
1236
- let y = Fp.cmov(y2, y1, isQR); // 10. y = CMOV(y2, y1, isQR)
1237
- return { isValid: isQR, value: y }; // 11. return (isQR, y) isQR ? y : y*c2
1238
- };
1239
- }
1240
- // No curves uses that
1241
- // if (Fp.ORDER % _8n === _5n) // sqrt_ratio_5mod8
1242
- return sqrtRatio;
1243
- }
1244
- /**
1245
- * Simplified Shallue-van de Woestijne-Ulas Method
1246
- * https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2
1247
- */
1248
- function mapToCurveSimpleSWU(Fp, opts) {
1249
- (0, modular_ts_1.validateField)(Fp);
1250
- const { A, B, Z } = opts;
1251
- if (!Fp.isValid(A) || !Fp.isValid(B) || !Fp.isValid(Z))
1252
- throw new Error('mapToCurveSimpleSWU: invalid opts');
1253
- const sqrtRatio = SWUFpSqrtRatio(Fp, Z);
1254
- if (!Fp.isOdd)
1255
- throw new Error('Field does not have .isOdd()');
1256
- // Input: u, an element of F.
1257
- // Output: (x, y), a point on E.
1258
- return (u) => {
1259
- // prettier-ignore
1260
- let tv1, tv2, tv3, tv4, tv5, tv6, x, y;
1261
- tv1 = Fp.sqr(u); // 1. tv1 = u^2
1262
- tv1 = Fp.mul(tv1, Z); // 2. tv1 = Z * tv1
1263
- tv2 = Fp.sqr(tv1); // 3. tv2 = tv1^2
1264
- tv2 = Fp.add(tv2, tv1); // 4. tv2 = tv2 + tv1
1265
- tv3 = Fp.add(tv2, Fp.ONE); // 5. tv3 = tv2 + 1
1266
- tv3 = Fp.mul(tv3, B); // 6. tv3 = B * tv3
1267
- tv4 = Fp.cmov(Z, Fp.neg(tv2), !Fp.eql(tv2, Fp.ZERO)); // 7. tv4 = CMOV(Z, -tv2, tv2 != 0)
1268
- tv4 = Fp.mul(tv4, A); // 8. tv4 = A * tv4
1269
- tv2 = Fp.sqr(tv3); // 9. tv2 = tv3^2
1270
- tv6 = Fp.sqr(tv4); // 10. tv6 = tv4^2
1271
- tv5 = Fp.mul(tv6, A); // 11. tv5 = A * tv6
1272
- tv2 = Fp.add(tv2, tv5); // 12. tv2 = tv2 + tv5
1273
- tv2 = Fp.mul(tv2, tv3); // 13. tv2 = tv2 * tv3
1274
- tv6 = Fp.mul(tv6, tv4); // 14. tv6 = tv6 * tv4
1275
- tv5 = Fp.mul(tv6, B); // 15. tv5 = B * tv6
1276
- tv2 = Fp.add(tv2, tv5); // 16. tv2 = tv2 + tv5
1277
- x = Fp.mul(tv1, tv3); // 17. x = tv1 * tv3
1278
- const { isValid, value } = sqrtRatio(tv2, tv6); // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6)
1279
- y = Fp.mul(tv1, u); // 19. y = tv1 * u -> Z * u^3 * y1
1280
- y = Fp.mul(y, value); // 20. y = y * y1
1281
- x = Fp.cmov(x, tv3, isValid); // 21. x = CMOV(x, tv3, is_gx1_square)
1282
- y = Fp.cmov(y, value, isValid); // 22. y = CMOV(y, y1, is_gx1_square)
1283
- const e1 = Fp.isOdd(u) === Fp.isOdd(y); // 23. e1 = sgn0(u) == sgn0(y)
1284
- y = Fp.cmov(Fp.neg(y), y, e1); // 24. y = CMOV(-y, y, e1)
1285
- const tv4_inv = (0, modular_ts_1.FpInvertBatch)(Fp, [tv4], true)[0];
1286
- x = Fp.mul(x, tv4_inv); // 25. x = x / tv4
1287
- return { x, y };
1288
- };
1289
- }
1290
1369
  //# sourceMappingURL=weierstrass.js.map