@noble/curves 0.4.0 → 0.5.0

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 (72) hide show
  1. package/README.md +203 -162
  2. package/lib/_shortw_utils.d.ts +75 -0
  3. package/lib/_shortw_utils.js +20 -0
  4. package/lib/{bls.d.ts → abstract/bls.d.ts} +2 -1
  5. package/lib/{bls.js → abstract/bls.js} +28 -27
  6. package/lib/{edwards.d.ts → abstract/edwards.d.ts} +17 -0
  7. package/lib/{edwards.js → abstract/edwards.js} +45 -4
  8. package/lib/{group.d.ts → abstract/group.d.ts} +2 -1
  9. package/lib/{group.js → abstract/group.js} +4 -3
  10. package/lib/{hashToCurve.d.ts → abstract/hash-to-curve.d.ts} +6 -0
  11. package/lib/{hashToCurve.js → abstract/hash-to-curve.js} +15 -2
  12. package/lib/{modular.d.ts → abstract/modular.d.ts} +10 -4
  13. package/lib/{modular.js → abstract/modular.js} +110 -19
  14. package/lib/{montgomery.d.ts → abstract/montgomery.d.ts} +2 -1
  15. package/lib/{montgomery.js → abstract/montgomery.js} +17 -8
  16. package/lib/{utils.d.ts → abstract/utils.d.ts} +1 -1
  17. package/lib/{utils.js → abstract/utils.js} +1 -1
  18. package/lib/{weierstrass.d.ts → abstract/weierstrass.d.ts} +28 -16
  19. package/lib/{weierstrass.js → abstract/weierstrass.js} +261 -127
  20. package/lib/bls12-381.d.ts +66 -0
  21. package/lib/bls12-381.js +1132 -0
  22. package/lib/bn.d.ts +7 -0
  23. package/lib/bn.js +24 -0
  24. package/lib/ed25519.d.ts +48 -0
  25. package/lib/ed25519.js +322 -0
  26. package/lib/ed448.d.ts +3 -0
  27. package/lib/ed448.js +128 -0
  28. package/lib/esm/_shortw_utils.js +15 -0
  29. package/lib/esm/{bls.js → abstract/bls.js} +25 -24
  30. package/lib/esm/{edwards.js → abstract/edwards.js} +45 -4
  31. package/lib/esm/{group.js → abstract/group.js} +4 -3
  32. package/lib/esm/{hashToCurve.js → abstract/hash-to-curve.js} +13 -1
  33. package/lib/esm/{modular.js → abstract/modular.js} +108 -18
  34. package/lib/esm/{montgomery.js → abstract/montgomery.js} +17 -8
  35. package/lib/esm/{utils.js → abstract/utils.js} +1 -1
  36. package/lib/esm/{weierstrass.js → abstract/weierstrass.js} +255 -123
  37. package/lib/esm/bls12-381.js +1129 -0
  38. package/lib/esm/bn.js +21 -0
  39. package/lib/esm/ed25519.js +318 -0
  40. package/lib/esm/ed448.js +125 -0
  41. package/lib/esm/index.js +2 -0
  42. package/lib/esm/jubjub.js +52 -0
  43. package/lib/esm/p192.js +21 -0
  44. package/lib/esm/p224.js +21 -0
  45. package/lib/esm/p256.js +39 -0
  46. package/lib/esm/p384.js +44 -0
  47. package/lib/esm/p521.js +58 -0
  48. package/lib/esm/pasta.js +29 -0
  49. package/lib/esm/secp256k1.js +290 -0
  50. package/lib/esm/stark.js +222 -0
  51. package/lib/index.d.ts +0 -0
  52. package/lib/index.js +2 -0
  53. package/lib/jubjub.d.ts +7 -0
  54. package/lib/jubjub.js +57 -0
  55. package/lib/p192.d.ts +130 -0
  56. package/lib/p192.js +24 -0
  57. package/lib/p224.d.ts +130 -0
  58. package/lib/p224.js +24 -0
  59. package/lib/p256.d.ts +130 -0
  60. package/lib/p256.js +42 -0
  61. package/lib/p384.d.ts +130 -0
  62. package/lib/p384.js +47 -0
  63. package/lib/p521.d.ts +131 -0
  64. package/lib/p521.js +61 -0
  65. package/lib/pasta.d.ts +4 -0
  66. package/lib/pasta.js +32 -0
  67. package/lib/secp256k1.d.ts +96 -0
  68. package/lib/secp256k1.js +294 -0
  69. package/lib/stark.d.ts +72 -0
  70. package/lib/stark.js +243 -0
  71. package/package.json +146 -50
  72. package/index.js +0 -1
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
3
- // Implementation of Short Weierstrass curve. The formula is: y² = x³ + ax + b
3
+ // Short Weierstrass curve. The formula is: y² = x³ + ax + b
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.weierstrass = exports.weierstrassPoints = void 0;
5
+ exports.mapToCurveSimpleSWU = exports.SWUFpSqrtRatio = exports.weierstrass = exports.weierstrassPoints = void 0;
6
6
  // TODO: sync vs async naming
7
7
  // TODO: default randomBytes
8
8
  // Differences from @noble/secp256k1 1.7:
@@ -13,7 +13,7 @@ exports.weierstrass = exports.weierstrassPoints = void 0;
13
13
  const mod = require("./modular.js");
14
14
  const utils_js_1 = require("./utils.js");
15
15
  const utils = require("./utils.js");
16
- const hashToCurve_js_1 = require("./hashToCurve.js");
16
+ const hash_to_curve_js_1 = require("./hash-to-curve.js");
17
17
  const group_js_1 = require("./group.js");
18
18
  // DER encoding utilities
19
19
  class DERError extends Error {
@@ -58,9 +58,7 @@ function parseDERSignature(data) {
58
58
  // Be friendly to bad ECMAScript parsers by not using bigint literals like 123n
59
59
  const _0n = BigInt(0);
60
60
  const _1n = BigInt(1);
61
- const _2n = BigInt(2);
62
61
  const _3n = BigInt(3);
63
- const _8n = BigInt(8);
64
62
  function validatePointOpts(curve) {
65
63
  const opts = utils.validateOpts(curve);
66
64
  const Fp = opts.Fp;
@@ -91,7 +89,7 @@ function validatePointOpts(curve) {
91
89
  throw new Error('Invalid fromBytes function');
92
90
  // Requires including hashToCurve file
93
91
  if (opts.htfDefaults !== undefined)
94
- (0, hashToCurve_js_1.validateHTFOpts)(opts.htfDefaults);
92
+ (0, hash_to_curve_js_1.validateHTFOpts)(opts.htfDefaults);
95
93
  // Set defaults
96
94
  return Object.freeze({ ...opts });
97
95
  }
@@ -117,8 +115,8 @@ function weierstrassPoints(opts) {
117
115
  function weierstrassEquation(x) {
118
116
  const { a, b } = CURVE;
119
117
  const x2 = Fp.square(x); // x * x
120
- const x3 = Fp.multiply(x2, x); // x2 * x
121
- return Fp.add(Fp.add(x3, Fp.multiply(x, a)), b); // x3 + a * x + b
118
+ const x3 = Fp.mul(x2, x); // x2 * x
119
+ return Fp.add(Fp.add(x3, Fp.mul(x, a)), b); // x3 + a * x + b
122
120
  }
123
121
  function isWithinCurveOrder(num) {
124
122
  return _0n < num && num < CURVE.n;
@@ -161,11 +159,11 @@ function weierstrassPoints(opts) {
161
159
  throw new TypeError('Expected valid private scalar: 0 < scalar < curve.n');
162
160
  }
163
161
  /**
164
- * Jacobian Point works in 3d / jacobi coordinates: (x, y, z) ∋ (x=x/z², y=y/z³)
162
+ * Projective Point works in 3d / projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z)
165
163
  * Default Point works in 2d / affine coordinates: (x, y)
166
- * We're doing calculations in jacobi, because its operations don't require costly inversion.
164
+ * We're doing calculations in projective, because its operations don't require costly inversion.
167
165
  */
168
- class JacobianPoint {
166
+ class ProjectivePoint {
169
167
  constructor(x, y, z) {
170
168
  this.x = x;
171
169
  this.y = y;
@@ -173,15 +171,15 @@ function weierstrassPoints(opts) {
173
171
  }
174
172
  static fromAffine(p) {
175
173
  if (!(p instanceof Point)) {
176
- throw new TypeError('JacobianPoint#fromAffine: expected Point');
174
+ throw new TypeError('ProjectivePoint#fromAffine: expected Point');
177
175
  }
178
176
  // fromAffine(x:0, y:0) would produce (x:0, y:0, z:1), but we need (x:0, y:1, z:0)
179
177
  if (p.equals(Point.ZERO))
180
- return JacobianPoint.ZERO;
181
- return new JacobianPoint(p.x, p.y, Fp.ONE);
178
+ return ProjectivePoint.ZERO;
179
+ return new ProjectivePoint(p.x, p.y, Fp.ONE);
182
180
  }
183
181
  /**
184
- * Takes a bunch of Jacobian Points but executes only one
182
+ * Takes a bunch of Projective Points but executes only one
185
183
  * invert on all of them. invert is very slow operation,
186
184
  * so this improves performance massively.
187
185
  */
@@ -190,98 +188,122 @@ function weierstrassPoints(opts) {
190
188
  return points.map((p, i) => p.toAffine(toInv[i]));
191
189
  }
192
190
  static normalizeZ(points) {
193
- return JacobianPoint.toAffineBatch(points).map(JacobianPoint.fromAffine);
191
+ return ProjectivePoint.toAffineBatch(points).map(ProjectivePoint.fromAffine);
194
192
  }
195
193
  /**
196
194
  * Compare one point to another.
197
195
  */
198
196
  equals(other) {
199
- if (!(other instanceof JacobianPoint))
200
- throw new TypeError('JacobianPoint expected');
197
+ assertPrjPoint(other);
201
198
  const { x: X1, y: Y1, z: Z1 } = this;
202
199
  const { x: X2, y: Y2, z: Z2 } = other;
203
- const Z1Z1 = Fp.square(Z1); // Z1 * Z1
204
- const Z2Z2 = Fp.square(Z2); // Z2 * Z2
205
- const U1 = Fp.multiply(X1, Z2Z2); // X1 * Z2Z2
206
- const U2 = Fp.multiply(X2, Z1Z1); // X2 * Z1Z1
207
- const S1 = Fp.multiply(Fp.multiply(Y1, Z2), Z2Z2); // Y1 * Z2 * Z2Z2
208
- const S2 = Fp.multiply(Fp.multiply(Y2, Z1), Z1Z1); // Y2 * Z1 * Z1Z1
209
- return Fp.equals(U1, U2) && Fp.equals(S1, S2);
200
+ const U1 = Fp.equals(Fp.mul(X1, Z2), Fp.mul(X2, Z1));
201
+ const U2 = Fp.equals(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1));
202
+ return U1 && U2;
210
203
  }
211
204
  /**
212
205
  * Flips point to one corresponding to (x, -y) in Affine coordinates.
213
206
  */
214
207
  negate() {
215
- return new JacobianPoint(this.x, Fp.negate(this.y), this.z);
208
+ return new ProjectivePoint(this.x, Fp.negate(this.y), this.z);
216
209
  }
217
- // Fast algo for doubling 2 Jacobian Points.
218
- // From: https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-2007-bl
219
- // Cost: 1M + 8S + 1*a + 10add + 2*2 + 1*3 + 1*8.
210
+ doubleAdd() {
211
+ return this.add(this);
212
+ }
213
+ // Renes-Costello-Batina exception-free doubling formula.
214
+ // There is 30% faster Jacobian formula, but it is not complete.
215
+ // https://eprint.iacr.org/2015/1060, algorithm 3
216
+ // Cost: 8M + 3S + 3*a + 2*b3 + 15add.
220
217
  double() {
218
+ const { a, b } = CURVE;
219
+ const b3 = Fp.mul(b, 3n);
221
220
  const { x: X1, y: Y1, z: Z1 } = this;
222
- const { a } = CURVE;
223
- // Faster algorithm: when a=0
224
- // From: https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
225
- // Cost: 2M + 5S + 6add + 3*2 + 1*3 + 1*8.
226
- if (Fp.isZero(a)) {
227
- const A = Fp.square(X1); // X1 * X1
228
- const B = Fp.square(Y1); // Y1 * Y1
229
- const C = Fp.square(B); // B * B
230
- const x1b = Fp.addN(X1, B); // X1 + B
231
- const D = Fp.multiply(Fp.subtractN(Fp.subtractN(Fp.square(x1b), A), C), _2n); // ((x1b * x1b) - A - C) * 2
232
- const E = Fp.multiply(A, _3n); // A * 3
233
- const F = Fp.square(E); // E * E
234
- const X3 = Fp.subtract(F, Fp.multiplyN(D, _2n)); // F - 2 * D
235
- const Y3 = Fp.subtract(Fp.multiplyN(E, Fp.subtractN(D, X3)), Fp.multiplyN(C, _8n)); // E * (D - X3) - 8 * C;
236
- const Z3 = Fp.multiply(Fp.multiplyN(Y1, _2n), Z1); // 2 * Y1 * Z1
237
- return new JacobianPoint(X3, Y3, Z3);
238
- }
239
- const XX = Fp.square(X1); // X1 * X1
240
- const YY = Fp.square(Y1); // Y1 * Y1
241
- const YYYY = Fp.square(YY); // YY * YY
242
- const ZZ = Fp.square(Z1); // Z1 * Z1
243
- const tmp1 = Fp.add(X1, YY); // X1 + YY
244
- const S = Fp.multiply(Fp.subtractN(Fp.subtractN(Fp.square(tmp1), XX), YYYY), _2n); // 2*((X1+YY)^2-XX-YYYY)
245
- const M = Fp.add(Fp.multiplyN(XX, _3n), Fp.multiplyN(Fp.square(ZZ), a)); // 3 * XX + a * ZZ^2
246
- const T = Fp.subtract(Fp.square(M), Fp.multiplyN(S, _2n)); // M^2-2*S
247
- const X3 = T;
248
- const Y3 = Fp.subtract(Fp.multiplyN(M, Fp.subtractN(S, T)), Fp.multiplyN(YYYY, _8n)); // M*(S-T)-8*YYYY
249
- const y1az1 = Fp.add(Y1, Z1); // (Y1+Z1)
250
- const Z3 = Fp.subtract(Fp.subtractN(Fp.square(y1az1), YY), ZZ); // (Y1+Z1)^2-YY-ZZ
251
- return new JacobianPoint(X3, Y3, Z3);
252
- }
253
- // Fast algo for adding 2 Jacobian Points.
254
- // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#addition-add-1998-cmo-2
255
- // Cost: 12M + 4S + 6add + 1*2
256
- // Note: 2007 Bernstein-Lange (11M + 5S + 9add + 4*2) is actually 10% slower.
221
+ let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
222
+ let t0 = Fp.mul(X1, X1); // step 1
223
+ let t1 = Fp.mul(Y1, Y1);
224
+ let t2 = Fp.mul(Z1, Z1);
225
+ let t3 = Fp.mul(X1, Y1);
226
+ t3 = Fp.add(t3, t3); // step 5
227
+ Z3 = Fp.mul(X1, Z1);
228
+ Z3 = Fp.add(Z3, Z3);
229
+ X3 = Fp.mul(a, Z3);
230
+ Y3 = Fp.mul(b3, t2);
231
+ Y3 = Fp.add(X3, Y3); // step 10
232
+ X3 = Fp.sub(t1, Y3);
233
+ Y3 = Fp.add(t1, Y3);
234
+ Y3 = Fp.mul(X3, Y3);
235
+ X3 = Fp.mul(t3, X3);
236
+ Z3 = Fp.mul(b3, Z3); // step 15
237
+ t2 = Fp.mul(a, t2);
238
+ t3 = Fp.sub(t0, t2);
239
+ t3 = Fp.mul(a, t3);
240
+ t3 = Fp.add(t3, Z3);
241
+ Z3 = Fp.add(t0, t0); // step 20
242
+ t0 = Fp.add(Z3, t0);
243
+ t0 = Fp.add(t0, t2);
244
+ t0 = Fp.mul(t0, t3);
245
+ Y3 = Fp.add(Y3, t0);
246
+ t2 = Fp.mul(Y1, Z1); // step 25
247
+ t2 = Fp.add(t2, t2);
248
+ t0 = Fp.mul(t2, t3);
249
+ X3 = Fp.sub(X3, t0);
250
+ Z3 = Fp.mul(t2, t1);
251
+ Z3 = Fp.add(Z3, Z3); // step 30
252
+ Z3 = Fp.add(Z3, Z3);
253
+ return new ProjectivePoint(X3, Y3, Z3);
254
+ }
255
+ // Renes-Costello-Batina exception-free addition formula.
256
+ // There is 30% faster Jacobian formula, but it is not complete.
257
+ // https://eprint.iacr.org/2015/1060, algorithm 1
258
+ // Cost: 12M + 0S + 3*a + 3*b3 + 23add.
257
259
  add(other) {
258
- if (!(other instanceof JacobianPoint))
259
- throw new TypeError('JacobianPoint expected');
260
+ assertPrjPoint(other);
260
261
  const { x: X1, y: Y1, z: Z1 } = this;
261
262
  const { x: X2, y: Y2, z: Z2 } = other;
262
- if (Fp.isZero(X2) || Fp.isZero(Y2))
263
- return this;
264
- if (Fp.isZero(X1) || Fp.isZero(Y1))
265
- return other;
266
- // We're using same code in equals()
267
- const Z1Z1 = Fp.square(Z1); // Z1Z1 = Z1^2
268
- const Z2Z2 = Fp.square(Z2); // Z2Z2 = Z2^2;
269
- const U1 = Fp.multiply(X1, Z2Z2); // X1 * Z2Z2
270
- const U2 = Fp.multiply(X2, Z1Z1); // X2 * Z1Z1
271
- const S1 = Fp.multiply(Fp.multiply(Y1, Z2), Z2Z2); // Y1 * Z2 * Z2Z2
272
- const S2 = Fp.multiply(Fp.multiply(Y2, Z1), Z1Z1); // Y2 * Z1 * Z1Z1
273
- const H = Fp.subtractN(U2, U1); // H = U2 - U1
274
- const r = Fp.subtractN(S2, S1); // S2 - S1
275
- // H = 0 meaning it's the same point.
276
- if (Fp.isZero(H))
277
- return Fp.isZero(r) ? this.double() : JacobianPoint.ZERO;
278
- const HH = Fp.square(H); // HH = H2
279
- const HHH = Fp.multiply(H, HH); // HHH = H * HH
280
- const V = Fp.multiply(U1, HH); // V = U1 * HH
281
- const X3 = Fp.subtract(Fp.subtractN(Fp.squareN(r), HHH), Fp.multiplyN(V, _2n)); // X3 = r^2 - HHH - 2 * V;
282
- const Y3 = Fp.subtract(Fp.multiplyN(r, Fp.subtractN(V, X3)), Fp.multiplyN(S1, HHH)); // Y3 = r * (V - X3) - S1 * HHH;
283
- const Z3 = Fp.multiply(Fp.multiply(Z1, Z2), H); // Z3 = Z1 * Z2 * H;
284
- return new JacobianPoint(X3, Y3, Z3);
263
+ let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
264
+ const a = CURVE.a;
265
+ const b3 = Fp.mul(CURVE.b, 3n);
266
+ let t0 = Fp.mul(X1, X2); // step 1
267
+ let t1 = Fp.mul(Y1, Y2);
268
+ let t2 = Fp.mul(Z1, Z2);
269
+ let t3 = Fp.add(X1, Y1);
270
+ let t4 = Fp.add(X2, Y2); // step 5
271
+ t3 = Fp.mul(t3, t4);
272
+ t4 = Fp.add(t0, t1);
273
+ t3 = Fp.sub(t3, t4);
274
+ t4 = Fp.add(X1, Z1);
275
+ let t5 = Fp.add(X2, Z2); // step 10
276
+ t4 = Fp.mul(t4, t5);
277
+ t5 = Fp.add(t0, t2);
278
+ t4 = Fp.sub(t4, t5);
279
+ t5 = Fp.add(Y1, Z1);
280
+ X3 = Fp.add(Y2, Z2); // step 15
281
+ t5 = Fp.mul(t5, X3);
282
+ X3 = Fp.add(t1, t2);
283
+ t5 = Fp.sub(t5, X3);
284
+ Z3 = Fp.mul(a, t4);
285
+ X3 = Fp.mul(b3, t2); // step 20
286
+ Z3 = Fp.add(X3, Z3);
287
+ X3 = Fp.sub(t1, Z3);
288
+ Z3 = Fp.add(t1, Z3);
289
+ Y3 = Fp.mul(X3, Z3);
290
+ t1 = Fp.add(t0, t0); // step 25
291
+ t1 = Fp.add(t1, t0);
292
+ t2 = Fp.mul(a, t2);
293
+ t4 = Fp.mul(b3, t4);
294
+ t1 = Fp.add(t1, t2);
295
+ t2 = Fp.sub(t0, t2); // step 30
296
+ t2 = Fp.mul(a, t2);
297
+ t4 = Fp.add(t4, t2);
298
+ t0 = Fp.mul(t1, t4);
299
+ Y3 = Fp.add(Y3, t0);
300
+ t0 = Fp.mul(t5, t4); // step 35
301
+ X3 = Fp.mul(t3, X3);
302
+ X3 = Fp.sub(X3, t0);
303
+ t0 = Fp.mul(t3, t1);
304
+ Z3 = Fp.mul(t5, Z3);
305
+ Z3 = Fp.add(Z3, t0); // step 40
306
+ return new ProjectivePoint(X3, Y3, Z3);
285
307
  }
286
308
  subtract(other) {
287
309
  return this.add(other.negate());
@@ -292,7 +314,7 @@ function weierstrassPoints(opts) {
292
314
  * an exposed private key e.g. sig verification, which works over *public* keys.
293
315
  */
294
316
  multiplyUnsafe(scalar) {
295
- const P0 = JacobianPoint.ZERO;
317
+ const P0 = ProjectivePoint.ZERO;
296
318
  if (typeof scalar === 'bigint' && scalar === _0n)
297
319
  return P0;
298
320
  // Will throw on 0
@@ -319,14 +341,14 @@ function weierstrassPoints(opts) {
319
341
  k1p = k1p.negate();
320
342
  if (k2neg)
321
343
  k2p = k2p.negate();
322
- k2p = new JacobianPoint(Fp.multiply(k2p.x, CURVE.endo.beta), k2p.y, k2p.z);
344
+ k2p = new ProjectivePoint(Fp.mul(k2p.x, CURVE.endo.beta), k2p.y, k2p.z);
323
345
  return k1p.add(k2p);
324
346
  }
325
347
  /**
326
348
  * Implements w-ary non-adjacent form for calculating ec multiplication.
327
349
  */
328
350
  wNAF(n, affinePoint) {
329
- if (!affinePoint && this.equals(JacobianPoint.BASE))
351
+ if (!affinePoint && this.equals(ProjectivePoint.BASE))
330
352
  affinePoint = Point.BASE;
331
353
  const W = (affinePoint && affinePoint._WINDOW_SIZE) || 1;
332
354
  // Calculate precomputes on a first run, reuse them after
@@ -334,7 +356,7 @@ function weierstrassPoints(opts) {
334
356
  if (!precomputes) {
335
357
  precomputes = wnaf.precomputeWindow(this, W);
336
358
  if (affinePoint && W !== 1) {
337
- precomputes = JacobianPoint.normalizeZ(precomputes);
359
+ precomputes = ProjectivePoint.normalizeZ(precomputes);
338
360
  pointPrecomputes.set(affinePoint, precomputes);
339
361
  }
340
362
  }
@@ -360,7 +382,7 @@ function weierstrassPoints(opts) {
360
382
  let { p: k2p, f: f2p } = this.wNAF(k2, affinePoint);
361
383
  k1p = wnaf.constTimeNegate(k1neg, k1p);
362
384
  k2p = wnaf.constTimeNegate(k2neg, k2p);
363
- k2p = new JacobianPoint(Fp.multiply(k2p.x, CURVE.endo.beta), k2p.y, k2p.z);
385
+ k2p = new ProjectivePoint(Fp.mul(k2p.x, CURVE.endo.beta), k2p.y, k2p.z);
364
386
  point = k1p.add(k2p);
365
387
  fake = f1p.add(f2p);
366
388
  }
@@ -370,25 +392,21 @@ function weierstrassPoints(opts) {
370
392
  fake = f;
371
393
  }
372
394
  // Normalize `z` for both points, but return only real one
373
- return JacobianPoint.normalizeZ([point, fake])[0];
395
+ return ProjectivePoint.normalizeZ([point, fake])[0];
374
396
  }
375
- // Converts Jacobian point to affine (x, y) coordinates.
397
+ // Converts Projective point to affine (x, y) coordinates.
376
398
  // Can accept precomputed Z^-1 - for example, from invertBatch.
377
- // (x, y, z) ∋ (x=x/z², y=y/z³)
378
- // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#scaling-z
399
+ // (x, y, z) ∋ (x=x/z, y=y/z)
379
400
  toAffine(invZ) {
380
401
  const { x, y, z } = this;
381
- const is0 = this.equals(JacobianPoint.ZERO);
402
+ const is0 = this.equals(ProjectivePoint.ZERO);
382
403
  // If invZ was 0, we return zero point. However we still want to execute
383
404
  // all operations, so we replace invZ with a random number, 1.
384
405
  if (invZ == null)
385
406
  invZ = is0 ? Fp.ONE : Fp.invert(z);
386
- const iz1 = invZ;
387
- const iz2 = Fp.square(iz1); // iz1 * iz1
388
- const iz3 = Fp.multiply(iz2, iz1); // iz2 * iz1
389
- const ax = Fp.multiply(x, iz2); // x * iz2
390
- const ay = Fp.multiply(y, iz3); // y * iz3
391
- const zz = Fp.multiply(z, iz1); // z * iz1
407
+ const ax = Fp.mul(x, invZ);
408
+ const ay = Fp.mul(y, invZ);
409
+ const zz = Fp.mul(z, invZ);
392
410
  if (is0)
393
411
  return Point.ZERO;
394
412
  if (!Fp.equals(zz, Fp.ONE))
@@ -399,7 +417,7 @@ function weierstrassPoints(opts) {
399
417
  if (CURVE.h === _1n)
400
418
  return true; // No subgroups, always torsion fee
401
419
  if (CURVE.isTorsionFree)
402
- return CURVE.isTorsionFree(JacobianPoint, this);
420
+ return CURVE.isTorsionFree(ProjectivePoint, this);
403
421
  // is multiplyUnsafe(CURVE.n) is always ok, same as for edwards?
404
422
  throw new Error('Unsupported!');
405
423
  }
@@ -409,13 +427,17 @@ function weierstrassPoints(opts) {
409
427
  if (CURVE.h === _1n)
410
428
  return this; // Fast-path
411
429
  if (CURVE.clearCofactor)
412
- return CURVE.clearCofactor(JacobianPoint, this);
430
+ return CURVE.clearCofactor(ProjectivePoint, this);
413
431
  return this.multiplyUnsafe(CURVE.h);
414
432
  }
415
433
  }
416
- JacobianPoint.BASE = new JacobianPoint(CURVE.Gx, CURVE.Gy, Fp.ONE);
417
- JacobianPoint.ZERO = new JacobianPoint(Fp.ZERO, Fp.ONE, Fp.ZERO);
418
- const wnaf = (0, group_js_1.wNAF)(JacobianPoint, CURVE.endo ? nBitLength / 2 : nBitLength);
434
+ ProjectivePoint.BASE = new ProjectivePoint(CURVE.Gx, CURVE.Gy, Fp.ONE);
435
+ ProjectivePoint.ZERO = new ProjectivePoint(Fp.ZERO, Fp.ONE, Fp.ZERO);
436
+ const wnaf = (0, group_js_1.wNAF)(ProjectivePoint, CURVE.endo ? nBitLength / 2 : nBitLength);
437
+ function assertPrjPoint(other) {
438
+ if (!(other instanceof ProjectivePoint))
439
+ throw new TypeError('ProjectivePoint expected');
440
+ }
419
441
  // Stores precomputed values for points.
420
442
  const pointPrecomputes = new WeakMap();
421
443
  /**
@@ -490,27 +512,27 @@ function weierstrassPoints(opts) {
490
512
  }
491
513
  // Adds point to itself
492
514
  double() {
493
- return JacobianPoint.fromAffine(this).double().toAffine();
515
+ return ProjectivePoint.fromAffine(this).double().toAffine();
494
516
  }
495
517
  // Adds point to other point
496
518
  add(other) {
497
- return JacobianPoint.fromAffine(this).add(JacobianPoint.fromAffine(other)).toAffine();
519
+ return ProjectivePoint.fromAffine(this).add(ProjectivePoint.fromAffine(other)).toAffine();
498
520
  }
499
521
  // Subtracts other point from the point
500
522
  subtract(other) {
501
523
  return this.add(other.negate());
502
524
  }
503
525
  multiply(scalar) {
504
- return JacobianPoint.fromAffine(this).multiply(scalar, this).toAffine();
526
+ return ProjectivePoint.fromAffine(this).multiply(scalar, this).toAffine();
505
527
  }
506
528
  multiplyUnsafe(scalar) {
507
- return JacobianPoint.fromAffine(this).multiplyUnsafe(scalar).toAffine();
529
+ return ProjectivePoint.fromAffine(this).multiplyUnsafe(scalar).toAffine();
508
530
  }
509
531
  clearCofactor() {
510
- return JacobianPoint.fromAffine(this).clearCofactor().toAffine();
532
+ return ProjectivePoint.fromAffine(this).clearCofactor().toAffine();
511
533
  }
512
534
  isTorsionFree() {
513
- return JacobianPoint.fromAffine(this).isTorsionFree();
535
+ return ProjectivePoint.fromAffine(this).isTorsionFree();
514
536
  }
515
537
  /**
516
538
  * Efficiently calculate `aP + bQ`.
@@ -519,11 +541,11 @@ function weierstrassPoints(opts) {
519
541
  * @returns non-zero affine point
520
542
  */
521
543
  multiplyAndAddUnsafe(Q, a, b) {
522
- const P = JacobianPoint.fromAffine(this);
544
+ const P = ProjectivePoint.fromAffine(this);
523
545
  const aP = a === _0n || a === _1n || this !== Point.BASE ? P.multiplyUnsafe(a) : P.multiply(a);
524
- const bQ = JacobianPoint.fromAffine(Q).multiplyUnsafe(b);
546
+ const bQ = ProjectivePoint.fromAffine(Q).multiplyUnsafe(b);
525
547
  const sum = aP.add(bQ);
526
- return sum.equals(JacobianPoint.ZERO) ? undefined : sum.toAffine();
548
+ return sum.equals(ProjectivePoint.ZERO) ? undefined : sum.toAffine();
527
549
  }
528
550
  // Encodes byte string to elliptic curve
529
551
  // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3
@@ -531,7 +553,7 @@ function weierstrassPoints(opts) {
531
553
  if (!CURVE.mapToCurve)
532
554
  throw new Error('No mapToCurve defined for curve');
533
555
  msg = (0, utils_js_1.ensureBytes)(msg);
534
- const u = (0, hashToCurve_js_1.hash_to_field)(msg, 2, { ...CURVE.htfDefaults, ...options });
556
+ const u = (0, hash_to_curve_js_1.hash_to_field)(msg, 2, { ...CURVE.htfDefaults, ...options });
535
557
  const { x: x0, y: y0 } = CURVE.mapToCurve(u[0]);
536
558
  const { x: x1, y: y1 } = CURVE.mapToCurve(u[1]);
537
559
  const p = new Point(x0, y0).add(new Point(x1, y1)).clearCofactor();
@@ -542,7 +564,7 @@ function weierstrassPoints(opts) {
542
564
  if (!CURVE.mapToCurve)
543
565
  throw new Error('No mapToCurve defined for curve');
544
566
  msg = (0, utils_js_1.ensureBytes)(msg);
545
- const u = (0, hashToCurve_js_1.hash_to_field)(msg, 1, { ...CURVE.htfDefaults, ...options });
567
+ const u = (0, hash_to_curve_js_1.hash_to_field)(msg, 1, { ...CURVE.htfDefaults, ...options });
546
568
  const { x, y } = CURVE.mapToCurve(u[0]);
547
569
  return new Point(x, y).clearCofactor();
548
570
  }
@@ -557,7 +579,7 @@ function weierstrassPoints(opts) {
557
579
  Point.ZERO = new Point(Fp.ZERO, Fp.ZERO);
558
580
  return {
559
581
  Point: Point,
560
- JacobianPoint: JacobianPoint,
582
+ ProjectivePoint: ProjectivePoint,
561
583
  normalizePrivateKey,
562
584
  weierstrassEquation,
563
585
  isWithinCurveOrder,
@@ -635,7 +657,7 @@ function weierstrass(curveDef) {
635
657
  // 0 is disallowed by arbitrary reasons. Probably because infinity point?
636
658
  return _0n < num && num < Fp.ORDER;
637
659
  }
638
- const { Point, JacobianPoint, normalizePrivateKey, weierstrassEquation, isWithinCurveOrder } = weierstrassPoints({
660
+ const { Point, ProjectivePoint, normalizePrivateKey, weierstrassEquation, isWithinCurveOrder } = weierstrassPoints({
639
661
  ...CURVE,
640
662
  toBytes(c, point, isCompressed) {
641
663
  if (isCompressed) {
@@ -958,18 +980,19 @@ function weierstrass(curveDef) {
958
980
  * @returns Signature with its point on curve Q OR undefined if params were invalid
959
981
  */
960
982
  function kmdToSig(kBytes, m, d, lowS = true) {
983
+ const { n } = CURVE;
961
984
  const k = truncateHash(kBytes, true);
962
985
  if (!isWithinCurveOrder(k))
963
986
  return;
964
987
  // Important: all mod() calls in the function must be done over `n`
965
- const { n } = CURVE;
988
+ const kinv = mod.invert(k, n);
966
989
  const q = Point.BASE.multiply(k);
967
990
  // r = x mod n
968
991
  const r = mod.mod(q.x, n);
969
992
  if (r === _0n)
970
993
  return;
971
994
  // s = (1/k * (m + dr) mod n
972
- const s = mod.mod(mod.invert(k, n) * mod.mod(m + d * r, n), n);
995
+ const s = mod.mod(kinv * mod.mod(m + mod.mod(d * r, n), n), n);
973
996
  if (s === _0n)
974
997
  return;
975
998
  let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n);
@@ -1049,7 +1072,7 @@ function weierstrass(curveDef) {
1049
1072
  // R = u1⋅G - u2⋅P
1050
1073
  const u1 = mod.mod(h * sinv, n);
1051
1074
  const u2 = mod.mod(r * sinv, n);
1052
- // Some implementations compare R.x in jacobian, without inversion.
1075
+ // Some implementations compare R.x in projective, without inversion.
1053
1076
  // The speed-up is <5%, so we don't complicate the code.
1054
1077
  const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2);
1055
1078
  if (!R)
@@ -1064,9 +1087,120 @@ function weierstrass(curveDef) {
1064
1087
  sign,
1065
1088
  verify,
1066
1089
  Point,
1067
- JacobianPoint,
1090
+ ProjectivePoint,
1068
1091
  Signature,
1069
1092
  utils,
1070
1093
  };
1071
1094
  }
1072
1095
  exports.weierstrass = weierstrass;
1096
+ // Implementation of the Shallue and van de Woestijne method for any Weierstrass curve
1097
+ // TODO: check if there is a way to merge this with uvRation in Edwards && move to modular?
1098
+ // b = True and y = sqrt(u / v) if (u / v) is square in F, and
1099
+ // b = False and y = sqrt(Z * (u / v)) otherwise.
1100
+ function SWUFpSqrtRatio(Fp, Z) {
1101
+ // Generic implementation
1102
+ const q = Fp.ORDER;
1103
+ let l = 0n;
1104
+ for (let o = q - 1n; o % 2n === 0n; o /= 2n)
1105
+ l += 1n;
1106
+ const c1 = l; // 1. c1, the largest integer such that 2^c1 divides q - 1.
1107
+ const c2 = (q - 1n) / 2n ** c1; // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic
1108
+ const c3 = (c2 - 1n) / 2n; // 3. c3 = (c2 - 1) / 2 # Integer arithmetic
1109
+ const c4 = 2n ** c1 - 1n; // 4. c4 = 2^c1 - 1 # Integer arithmetic
1110
+ const c5 = 2n ** (c1 - 1n); // 5. c5 = 2^(c1 - 1) # Integer arithmetic
1111
+ const c6 = Fp.pow(Z, c2); // 6. c6 = Z^c2
1112
+ const c7 = Fp.pow(Z, (c2 + 1n) / 2n); // 7. c7 = Z^((c2 + 1) / 2)
1113
+ let sqrtRatio = (u, v) => {
1114
+ let tv1 = c6; // 1. tv1 = c6
1115
+ let tv2 = Fp.pow(v, c4); // 2. tv2 = v^c4
1116
+ let tv3 = Fp.square(tv2); // 3. tv3 = tv2^2
1117
+ tv3 = Fp.mul(tv3, v); // 4. tv3 = tv3 * v
1118
+ let tv5 = Fp.mul(u, tv3); // 5. tv5 = u * tv3
1119
+ tv5 = Fp.pow(tv5, c3); // 6. tv5 = tv5^c3
1120
+ tv5 = Fp.mul(tv5, tv2); // 7. tv5 = tv5 * tv2
1121
+ tv2 = Fp.mul(tv5, v); // 8. tv2 = tv5 * v
1122
+ tv3 = Fp.mul(tv5, u); // 9. tv3 = tv5 * u
1123
+ let tv4 = Fp.mul(tv3, tv2); // 10. tv4 = tv3 * tv2
1124
+ tv5 = Fp.pow(tv4, c5); // 11. tv5 = tv4^c5
1125
+ let isQR = Fp.equals(tv5, Fp.ONE); // 12. isQR = tv5 == 1
1126
+ tv2 = Fp.mul(tv3, c7); // 13. tv2 = tv3 * c7
1127
+ tv5 = Fp.mul(tv4, tv1); // 14. tv5 = tv4 * tv1
1128
+ tv3 = Fp.cmov(tv2, tv3, isQR); // 15. tv3 = CMOV(tv2, tv3, isQR)
1129
+ tv4 = Fp.cmov(tv5, tv4, isQR); // 16. tv4 = CMOV(tv5, tv4, isQR)
1130
+ // 17. for i in (c1, c1 - 1, ..., 2):
1131
+ for (let i = c1; i > 1; i--) {
1132
+ let tv5 = 2n ** (i - 2n); // 18. tv5 = i - 2; 19. tv5 = 2^tv5
1133
+ let tvv5 = Fp.pow(tv4, tv5); // 20. tv5 = tv4^tv5
1134
+ const e1 = Fp.equals(tvv5, Fp.ONE); // 21. e1 = tv5 == 1
1135
+ tv2 = Fp.mul(tv3, tv1); // 22. tv2 = tv3 * tv1
1136
+ tv1 = Fp.mul(tv1, tv1); // 23. tv1 = tv1 * tv1
1137
+ tvv5 = Fp.mul(tv4, tv1); // 24. tv5 = tv4 * tv1
1138
+ tv3 = Fp.cmov(tv2, tv3, e1); // 25. tv3 = CMOV(tv2, tv3, e1)
1139
+ tv4 = Fp.cmov(tvv5, tv4, e1); // 26. tv4 = CMOV(tv5, tv4, e1)
1140
+ }
1141
+ return { isValid: isQR, value: tv3 };
1142
+ };
1143
+ if (Fp.ORDER % 4n === 3n) {
1144
+ // sqrt_ratio_3mod4(u, v)
1145
+ const c1 = (Fp.ORDER - 3n) / 4n; // 1. c1 = (q - 3) / 4 # Integer arithmetic
1146
+ const c2 = Fp.sqrt(Fp.negate(Z)); // 2. c2 = sqrt(-Z)
1147
+ sqrtRatio = (u, v) => {
1148
+ let tv1 = Fp.square(v); // 1. tv1 = v^2
1149
+ const tv2 = Fp.mul(u, v); // 2. tv2 = u * v
1150
+ tv1 = Fp.mul(tv1, tv2); // 3. tv1 = tv1 * tv2
1151
+ let y1 = Fp.pow(tv1, c1); // 4. y1 = tv1^c1
1152
+ y1 = Fp.mul(y1, tv2); // 5. y1 = y1 * tv2
1153
+ const y2 = Fp.mul(y1, c2); // 6. y2 = y1 * c2
1154
+ const tv3 = Fp.mul(Fp.square(y1), v); // 7. tv3 = y1^2; 8. tv3 = tv3 * v
1155
+ const isQR = Fp.equals(tv3, u); // 9. isQR = tv3 == u
1156
+ let y = Fp.cmov(y2, y1, isQR); // 10. y = CMOV(y2, y1, isQR)
1157
+ return { isValid: isQR, value: y }; // 11. return (isQR, y) isQR ? y : y*c2
1158
+ };
1159
+ }
1160
+ // No curves uses that
1161
+ // if (Fp.ORDER % 8n === 5n) // sqrt_ratio_5mod8
1162
+ return sqrtRatio;
1163
+ }
1164
+ exports.SWUFpSqrtRatio = SWUFpSqrtRatio;
1165
+ // From draft-irtf-cfrg-hash-to-curve-16
1166
+ function mapToCurveSimpleSWU(Fp, opts) {
1167
+ mod.validateField(Fp);
1168
+ if (!Fp.isValid(opts.A) || !Fp.isValid(opts.B) || !Fp.isValid(opts.Z))
1169
+ throw new Error('mapToCurveSimpleSWU: invalid opts');
1170
+ const sqrtRatio = SWUFpSqrtRatio(Fp, opts.Z);
1171
+ if (!Fp.isOdd)
1172
+ throw new Error('Fp.isOdd is not implemented!');
1173
+ // Input: u, an element of F.
1174
+ // Output: (x, y), a point on E.
1175
+ return (u) => {
1176
+ // prettier-ignore
1177
+ let tv1, tv2, tv3, tv4, tv5, tv6, x, y;
1178
+ tv1 = Fp.square(u); // 1. tv1 = u^2
1179
+ tv1 = Fp.mul(tv1, opts.Z); // 2. tv1 = Z * tv1
1180
+ tv2 = Fp.square(tv1); // 3. tv2 = tv1^2
1181
+ tv2 = Fp.add(tv2, tv1); // 4. tv2 = tv2 + tv1
1182
+ tv3 = Fp.add(tv2, Fp.ONE); // 5. tv3 = tv2 + 1
1183
+ tv3 = Fp.mul(tv3, opts.B); // 6. tv3 = B * tv3
1184
+ tv4 = Fp.cmov(opts.Z, Fp.negate(tv2), !Fp.equals(tv2, Fp.ZERO)); // 7. tv4 = CMOV(Z, -tv2, tv2 != 0)
1185
+ tv4 = Fp.mul(tv4, opts.A); // 8. tv4 = A * tv4
1186
+ tv2 = Fp.square(tv3); // 9. tv2 = tv3^2
1187
+ tv6 = Fp.square(tv4); // 10. tv6 = tv4^2
1188
+ tv5 = Fp.mul(tv6, opts.A); // 11. tv5 = A * tv6
1189
+ tv2 = Fp.add(tv2, tv5); // 12. tv2 = tv2 + tv5
1190
+ tv2 = Fp.mul(tv2, tv3); // 13. tv2 = tv2 * tv3
1191
+ tv6 = Fp.mul(tv6, tv4); // 14. tv6 = tv6 * tv4
1192
+ tv5 = Fp.mul(tv6, opts.B); // 15. tv5 = B * tv6
1193
+ tv2 = Fp.add(tv2, tv5); // 16. tv2 = tv2 + tv5
1194
+ x = Fp.mul(tv1, tv3); // 17. x = tv1 * tv3
1195
+ const { isValid, value } = sqrtRatio(tv2, tv6); // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6)
1196
+ y = Fp.mul(tv1, u); // 19. y = tv1 * u -> Z * u^3 * y1
1197
+ y = Fp.mul(y, value); // 20. y = y * y1
1198
+ x = Fp.cmov(x, tv3, isValid); // 21. x = CMOV(x, tv3, is_gx1_square)
1199
+ y = Fp.cmov(y, value, isValid); // 22. y = CMOV(y, y1, is_gx1_square)
1200
+ const e1 = Fp.isOdd(u) === Fp.isOdd(y); // 23. e1 = sgn0(u) == sgn0(y)
1201
+ y = Fp.cmov(Fp.negate(y), y, e1); // 24. y = CMOV(-y, y, e1)
1202
+ x = Fp.div(x, tv4); // 25. x = x / tv4
1203
+ return { x, y };
1204
+ };
1205
+ }
1206
+ exports.mapToCurveSimpleSWU = mapToCurveSimpleSWU;