@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,5 +1,5 @@
1
1
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2
- // Implementation of Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y²
2
+ // Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y²
3
3
  // Differences from @noble/ed25519 1.7:
4
4
  // 1. Different field element lengths in ed448:
5
5
  // EDDSA (RFC8032) is 456 bits / 57 bytes, ECDH (RFC7748) is 448 bits / 56 bytes
@@ -10,6 +10,7 @@
10
10
  import * as mod from './modular.js';
11
11
  import { bytesToHex, concatBytes, ensureBytes, numberToBytesLE, bytesToNumberLE, hashToPrivateScalar, validateOpts as utilOpts, } from './utils.js'; // TODO: import * as u from './utils.js'?
12
12
  import { wNAF } from './group.js';
13
+ import { hash_to_field, validateHTFOpts } from './hash-to-curve.js';
13
14
  // Be friendly to bad ECMAScript parsers by not using bigint literals like 123n
14
15
  const _0n = BigInt(0);
15
16
  const _1n = BigInt(1);
@@ -28,12 +29,20 @@ function validateOpts(curve) {
28
29
  if (typeof opts[fn] !== 'function')
29
30
  throw new Error(`Invalid ${fn} function`);
30
31
  }
31
- for (const fn of ['adjustScalarBytes', 'domain', 'uvRatio']) {
32
+ for (const fn of [
33
+ 'adjustScalarBytes',
34
+ 'domain',
35
+ 'uvRatio',
36
+ 'mapToCurve',
37
+ 'clearCofactor',
38
+ ]) {
32
39
  if (opts[fn] === undefined)
33
40
  continue; // Optional
34
41
  if (typeof opts[fn] !== 'function')
35
42
  throw new Error(`Invalid ${fn} function`);
36
43
  }
44
+ if (opts.htfDefaults !== undefined)
45
+ validateHTFOpts(opts.htfDefaults);
37
46
  // Set defaults
38
47
  return Object.freeze({ ...opts });
39
48
  }
@@ -153,7 +162,7 @@ export function twistedEdwards(curveDef) {
153
162
  const B = modP((Y1 + X1) * (Y2 - X2));
154
163
  const F = modP(B - A);
155
164
  if (F === _0n)
156
- return this.double(); // Same point.
165
+ return this.double(); // Same point. Tests say it doesn't affect timing
157
166
  const C = modP(Z1 * _2n * T2);
158
167
  const D = modP(T1 * _2n * Z2);
159
168
  const E = D + C;
@@ -170,7 +179,6 @@ export function twistedEdwards(curveDef) {
170
179
  const C = modP(T1 * d * T2); // C = T1*d*T2
171
180
  const D = modP(Z1 * Z2); // D = Z1*Z2
172
181
  const E = modP((X1 + Y1) * (X2 + Y2) - A - B); // E = (X1+Y1)*(X2+Y2)-A-B
173
- // TODO: do we need to check for same point here? Looks like working without it
174
182
  const F = D - C; // F = D-C
175
183
  const G = D + C; // G = D+C
176
184
  const H = modP(B - a * A); // H = B-a*A
@@ -244,6 +252,15 @@ export function twistedEdwards(curveDef) {
244
252
  throw new Error('invZ was invalid');
245
253
  return new Point(ax, ay);
246
254
  }
255
+ clearCofactor() {
256
+ if (CURVE.h === _1n)
257
+ return this; // Fast-path
258
+ // clear_cofactor(P) := h_eff * P
259
+ // hEff = h for ed25519/ed448. Maybe worth moving to params?
260
+ if (CURVE.clearCofactor)
261
+ return CURVE.clearCofactor(ExtendedPoint, this);
262
+ return this.multiplyUnsafe(CURVE.h);
263
+ }
247
264
  }
248
265
  ExtendedPoint.BASE = new ExtendedPoint(CURVE.Gx, CURVE.Gy, _1n, modP(CURVE.Gx * CURVE.Gy));
249
266
  ExtendedPoint.ZERO = new ExtendedPoint(_0n, _1n, _1n, _0n);
@@ -352,6 +369,30 @@ export function twistedEdwards(curveDef) {
352
369
  multiply(scalar) {
353
370
  return ExtendedPoint.fromAffine(this).multiply(scalar, this).toAffine();
354
371
  }
372
+ clearCofactor() {
373
+ return ExtendedPoint.fromAffine(this).clearCofactor().toAffine();
374
+ }
375
+ // Encodes byte string to elliptic curve
376
+ // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3
377
+ static hashToCurve(msg, options) {
378
+ if (!CURVE.mapToCurve)
379
+ throw new Error('No mapToCurve defined for curve');
380
+ msg = ensureBytes(msg);
381
+ const u = hash_to_field(msg, 2, { ...CURVE.htfDefaults, ...options });
382
+ const { x: x0, y: y0 } = CURVE.mapToCurve(u[0]);
383
+ const { x: x1, y: y1 } = CURVE.mapToCurve(u[1]);
384
+ const p = new Point(x0, y0).add(new Point(x1, y1)).clearCofactor();
385
+ return p;
386
+ }
387
+ // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-3
388
+ static encodeToCurve(msg, options) {
389
+ if (!CURVE.mapToCurve)
390
+ throw new Error('No mapToCurve defined for curve');
391
+ msg = ensureBytes(msg);
392
+ const u = hash_to_field(msg, 1, { ...CURVE.htfDefaults, ...options });
393
+ const { x, y } = CURVE.mapToCurve(u[0]);
394
+ return new Point(x, y).clearCofactor();
395
+ }
355
396
  }
356
397
  // Base point aka generator
357
398
  // public_key = Point.BASE * private_key
@@ -1,5 +1,5 @@
1
- /*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2
- // Default group related functions
1
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2
+ // Abelian group utilities
3
3
  const _0n = BigInt(0);
4
4
  const _1n = BigInt(1);
5
5
  // Not big, but pretty complex and it is easy to break stuff. To avoid too much copy paste
@@ -52,8 +52,9 @@ export function wNAF(c, bits) {
52
52
  },
53
53
  /**
54
54
  * Implements w-ary non-adjacent form for calculating ec multiplication.
55
- * @param n
55
+ * @param W window size
56
56
  * @param affinePoint optional 2d point to save cached precompute windows on it.
57
+ * @param n bits
57
58
  * @returns real and fake (for const-time) points
58
59
  */
59
60
  wNAF(W, precomputes, n) {
@@ -1,3 +1,4 @@
1
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
1
2
  import { concatBytes } from './utils.js';
2
3
  import * as mod from './modular.js';
3
4
  export function validateHTFOpts(opts) {
@@ -15,6 +16,7 @@ export function validateHTFOpts(opts) {
15
16
  throw new Error('Invalid htf/hash function');
16
17
  }
17
18
  // UTF8 to ui8a
19
+ // TODO: looks broken, ASCII only, why not TextEncoder/TextDecoder? it is in hashes anyway
18
20
  export function stringToBytes(str) {
19
21
  const bytes = new Uint8Array(str.length);
20
22
  for (let i = 0; i < str.length; i++)
@@ -56,7 +58,7 @@ export function expand_message_xmd(msg, DST, lenInBytes, H) {
56
58
  if (DST.length > 255)
57
59
  DST = H(concatBytes(stringToBytes('H2C-OVERSIZE-DST-'), DST));
58
60
  const b_in_bytes = H.outputLen;
59
- const r_in_bytes = b_in_bytes * 2;
61
+ const r_in_bytes = H.blockLen;
60
62
  const ell = Math.ceil(lenInBytes / b_in_bytes);
61
63
  if (ell > 255)
62
64
  throw new Error('Invalid xmd length');
@@ -103,3 +105,13 @@ export function hash_to_field(msg, count, options) {
103
105
  }
104
106
  return u;
105
107
  }
108
+ export function isogenyMap(field, map) {
109
+ // Make same order as in spec
110
+ const COEFF = map.map((i) => Array.from(i).reverse());
111
+ return (x, y) => {
112
+ const [xNum, xDen, yNum, yDen] = COEFF.map((val) => val.reduce((acc, i) => field.add(field.mul(acc, x), i)));
113
+ x = field.div(xNum, xDen); // xNum / xDen
114
+ y = field.mul(y, field.div(yNum, yDen)); // y * (yNum / yDev)
115
+ return { x, y };
116
+ };
117
+ }
@@ -1,9 +1,12 @@
1
- /*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
1
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2
2
  import * as utils from './utils.js';
3
- // Utilities for modular arithmetics
4
- const _0n = BigInt(0);
5
- const _1n = BigInt(1);
6
- const _2n = BigInt(2);
3
+ // Utilities for modular arithmetics and finite fields
4
+ // prettier-ignore
5
+ const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
6
+ // prettier-ignore
7
+ const _4n = BigInt(4), _5n = BigInt(5), _7n = BigInt(7), _8n = BigInt(8);
8
+ // prettier-ignore
9
+ const _9n = BigInt(9), _16n = BigInt(16);
7
10
  // Calculates a modulo b
8
11
  export function mod(a, b) {
9
12
  const result = a % b;
@@ -74,16 +77,16 @@ export function legendre(num, fieldPrime) {
74
77
  }
75
78
  /**
76
79
  * Calculates square root of a number in a finite field.
80
+ * √a mod P
77
81
  */
78
82
  // TODO: rewrite as generic Fp function && remove bls versions
79
83
  export function sqrt(number, modulo) {
80
84
  // prettier-ignore
81
- const _3n = BigInt(3), _4n = BigInt(4), _5n = BigInt(5), _8n = BigInt(8);
82
85
  const n = number;
83
86
  const P = modulo;
84
87
  const p1div4 = (P + _1n) / _4n;
85
88
  // P ≡ 3 (mod 4)
86
- // sqrt n = n^((P+1)/4)
89
+ // n = n^((P+1)/4)
87
90
  if (P % _4n === _3n) {
88
91
  // Not all roots possible!
89
92
  // const ORDER =
@@ -139,8 +142,8 @@ export const isNegativeLE = (num, modulo) => (mod(num, modulo) & _1n) === _1n;
139
142
  // prettier-ignore
140
143
  const FIELD_FIELDS = [
141
144
  'create', 'isValid', 'isZero', 'negate', 'invert', 'sqrt', 'square',
142
- 'equals', 'add', 'subtract', 'multiply', 'pow', 'div',
143
- 'addN', 'subtractN', 'multiplyN', 'squareN'
145
+ 'equals', 'add', 'sub', 'mul', 'pow', 'div',
146
+ 'addN', 'subN', 'mulN', 'squareN'
144
147
  ];
145
148
  export function validateField(field) {
146
149
  for (const i of ['ORDER', 'MASK']) {
@@ -170,7 +173,7 @@ export function FpPow(f, num, power) {
170
173
  let d = num;
171
174
  while (power > _0n) {
172
175
  if (power & _1n)
173
- p = f.multiply(p, d);
176
+ p = f.mul(p, d);
174
177
  d = f.square(d);
175
178
  power >>= 1n;
176
179
  }
@@ -183,7 +186,7 @@ export function FpInvertBatch(f, nums) {
183
186
  if (f.isZero(num))
184
187
  return acc;
185
188
  tmp[i] = acc;
186
- return f.multiply(acc, num);
189
+ return f.mul(acc, num);
187
190
  }, f.ONE);
188
191
  // Invert last element
189
192
  const inverted = f.invert(lastMultiplied);
@@ -191,13 +194,13 @@ export function FpInvertBatch(f, nums) {
191
194
  nums.reduceRight((acc, num, i) => {
192
195
  if (f.isZero(num))
193
196
  return acc;
194
- tmp[i] = f.multiply(acc, tmp[i]);
195
- return f.multiply(acc, num);
197
+ tmp[i] = f.mul(acc, tmp[i]);
198
+ return f.mul(acc, num);
196
199
  }, inverted);
197
200
  return tmp;
198
201
  }
199
202
  export function FpDiv(f, lhs, rhs) {
200
- return f.multiply(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.invert(rhs));
203
+ return f.mul(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.invert(rhs));
201
204
  }
202
205
  // NOTE: very fragile, always bench. Major performance points:
203
206
  // - NonNormalized ops
@@ -229,18 +232,21 @@ export function Fp(ORDER, bitLen, isLE = false, redef = {}) {
229
232
  equals: (lhs, rhs) => lhs === rhs,
230
233
  square: (num) => mod(num * num, ORDER),
231
234
  add: (lhs, rhs) => mod(lhs + rhs, ORDER),
232
- subtract: (lhs, rhs) => mod(lhs - rhs, ORDER),
233
- multiply: (lhs, rhs) => mod(lhs * rhs, ORDER),
235
+ sub: (lhs, rhs) => mod(lhs - rhs, ORDER),
236
+ mul: (lhs, rhs) => mod(lhs * rhs, ORDER),
234
237
  pow: (num, power) => FpPow(f, num, power),
235
238
  div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER),
236
239
  // Same as above, but doesn't normalize
237
240
  squareN: (num) => num * num,
238
241
  addN: (lhs, rhs) => lhs + rhs,
239
- subtractN: (lhs, rhs) => lhs - rhs,
240
- multiplyN: (lhs, rhs) => lhs * rhs,
242
+ subN: (lhs, rhs) => lhs - rhs,
243
+ mulN: (lhs, rhs) => lhs * rhs,
241
244
  invert: (num) => invert(num, ORDER),
242
245
  sqrt: redef.sqrt || sqrtP,
243
246
  invertBatch: (lst) => FpInvertBatch(f, lst),
247
+ // TODO: do we really need constant cmov?
248
+ // We don't have const-time bigints anyway, so probably will be not very useful
249
+ cmov: (a, b, c) => (c ? b : a),
244
250
  toBytes: (num) => isLE ? utils.numberToBytesLE(num, BYTES) : utils.numberToBytesBE(num, BYTES),
245
251
  fromBytes: (bytes) => {
246
252
  if (bytes.length !== BYTES)
@@ -250,3 +256,87 @@ export function Fp(ORDER, bitLen, isLE = false, redef = {}) {
250
256
  });
251
257
  return Object.freeze(f);
252
258
  }
259
+ // TODO: re-use in bls/generic sqrt for field/etc?
260
+ // Something like sqrtUnsafe which always returns value, but sqrt throws exception if non-square
261
+ // From draft-irtf-cfrg-hash-to-curve-16
262
+ export function FpSqrt(Fp) {
263
+ // NOTE: it requires another sqrt for constant precomputes, but no need for roots of unity,
264
+ // probably we can simply bls code using it
265
+ const q = Fp.ORDER;
266
+ const squareConst = (q - _1n) / _2n;
267
+ // is_square(x) := { True, if x^((q - 1) / 2) is 0 or 1 in F;
268
+ // { False, otherwise.
269
+ let isSquare = (x) => {
270
+ const p = Fp.pow(x, squareConst);
271
+ return Fp.equals(p, Fp.ZERO) || Fp.equals(p, Fp.ONE);
272
+ };
273
+ // Constant-time Tonelli-Shanks algorithm
274
+ let l = _0n;
275
+ for (let o = q - _1n; o % _2n === _0n; o /= _2n)
276
+ l += _1n;
277
+ const c1 = l; // 1. c1, the largest integer such that 2^c1 divides q - 1.
278
+ const c2 = (q - _1n) / _2n ** c1; // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic
279
+ const c3 = (c2 - _1n) / _2n; // 3. c3 = (c2 - 1) / 2 # Integer arithmetic
280
+ // 4. c4, a non-square value in F
281
+ // 5. c5 = c4^c2 in F
282
+ let c4 = Fp.ONE;
283
+ while (isSquare(c4))
284
+ c4 = Fp.add(c4, Fp.ONE);
285
+ const c5 = Fp.pow(c4, c2);
286
+ let sqrt = (x) => {
287
+ let z = Fp.pow(x, c3); // 1. z = x^c3
288
+ let t = Fp.square(z); // 2. t = z * z
289
+ t = Fp.mul(t, x); // 3. t = t * x
290
+ z = Fp.mul(z, x); // 4. z = z * x
291
+ let b = t; // 5. b = t
292
+ let c = c5; // 6. c = c5
293
+ // 7. for i in (c1, c1 - 1, ..., 2):
294
+ for (let i = c1; i > 1; i--) {
295
+ // 8. for j in (1, 2, ..., i - 2):
296
+ // 9. b = b * b
297
+ for (let j = _1n; j < i - _1n; i++)
298
+ b = Fp.square(b);
299
+ const e = Fp.equals(b, Fp.ONE); // 10. e = b == 1
300
+ const zt = Fp.mul(z, c); // 11. zt = z * c
301
+ z = Fp.cmov(zt, z, e); // 12. z = CMOV(zt, z, e)
302
+ c = Fp.square(c); // 13. c = c * c
303
+ let tt = Fp.mul(t, c); // 14. tt = t * c
304
+ t = Fp.cmov(tt, t, e); // 15. t = CMOV(tt, t, e)
305
+ b = t; // 16. b = t
306
+ }
307
+ return z; // 17. return z
308
+ };
309
+ if (q % _4n === _3n) {
310
+ const c1 = (q + _1n) / _4n; // 1. c1 = (q + 1) / 4 # Integer arithmetic
311
+ sqrt = (x) => Fp.pow(x, c1);
312
+ }
313
+ else if (q % _8n === _5n) {
314
+ const c1 = Fp.sqrt(Fp.negate(Fp.ONE)); // 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F
315
+ const c2 = (q + _3n) / _8n; // 2. c2 = (q + 3) / 8 # Integer arithmetic
316
+ sqrt = (x) => {
317
+ let tv1 = Fp.pow(x, c2); // 1. tv1 = x^c2
318
+ let tv2 = Fp.mul(tv1, c1); // 2. tv2 = tv1 * c1
319
+ let e = Fp.equals(Fp.square(tv1), x); // 3. e = (tv1^2) == x
320
+ return Fp.cmov(tv2, tv1, e); // 4. z = CMOV(tv2, tv1, e)
321
+ };
322
+ }
323
+ else if (Fp.ORDER % _16n === _9n) {
324
+ const c1 = Fp.sqrt(Fp.negate(Fp.ONE)); // 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F
325
+ const c2 = Fp.sqrt(c1); // 2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F
326
+ const c3 = Fp.sqrt(Fp.negate(c1)); // 3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F
327
+ const c4 = (Fp.ORDER + _7n) / _16n; // 4. c4 = (q + 7) / 16 # Integer arithmetic
328
+ sqrt = (x) => {
329
+ let tv1 = Fp.pow(x, c4); // 1. tv1 = x^c4
330
+ let tv2 = Fp.mul(c1, tv1); // 2. tv2 = c1 * tv1
331
+ const tv3 = Fp.mul(c2, tv1); // 3. tv3 = c2 * tv1
332
+ let tv4 = Fp.mul(c3, tv1); // 4. tv4 = c3 * tv1
333
+ const e1 = Fp.equals(Fp.square(tv2), x); // 5. e1 = (tv2^2) == x
334
+ const e2 = Fp.equals(Fp.square(tv3), x); // 6. e2 = (tv3^2) == x
335
+ tv1 = Fp.cmov(tv1, tv2, e1); // 7. tv1 = CMOV(tv1, tv2, e1) # Select tv2 if (tv2^2) == x
336
+ tv2 = Fp.cmov(tv4, tv3, e2); // 8. tv2 = CMOV(tv4, tv3, e2) # Select tv3 if (tv3^2) == x
337
+ const e3 = Fp.equals(Fp.square(tv2), x); // 9. e3 = (tv2^2) == x
338
+ return Fp.cmov(tv1, tv2, e3); // 10. z = CMOV(tv1, tv2, e3) # Select the sqrt from tv1 and tv2
339
+ };
340
+ }
341
+ return { sqrt, isSquare };
342
+ }
@@ -1,3 +1,4 @@
1
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
1
2
  import * as mod from './modular.js';
2
3
  import { ensureBytes, numberToBytesLE, bytesToNumberLE,
3
4
  // nLength,
@@ -161,8 +162,14 @@ export function montgomery(curveDef) {
161
162
  throw new Error(`Expected ${montgomeryBytes} or ${fieldLen} bytes, got ${bytes.length}`);
162
163
  return bytesToNumberLE(adjustScalarBytes(bytes));
163
164
  }
164
- // Multiply point u by scalar
165
- function scalarMult(u, scalar) {
165
+ /**
166
+ * Computes shared secret between private key "scalar" and public key's "u" (x) coordinate.
167
+ * We can get 'y' coordinate from 'u',
168
+ * but Point.fromHex also wants 'x' coordinate oddity flag,
169
+ * and we cannot get 'x' without knowing 'v'.
170
+ * Need to add generic conversion between twisted edwards and complimentary curve for JubJub.
171
+ */
172
+ function scalarMult(scalar, u) {
166
173
  const pointU = decodeUCoordinate(u);
167
174
  const _scalar = decodeScalar(scalar);
168
175
  const pu = montgomeryLadder(pointU, _scalar);
@@ -172,17 +179,19 @@ export function montgomery(curveDef) {
172
179
  throw new Error('Invalid private or public key received');
173
180
  return encodeUCoordinate(pu);
174
181
  }
175
- // Multiply base point by scalar
182
+ /**
183
+ * Computes public key from private.
184
+ * Executes scalar multiplication of curve's base point by scalar.
185
+ * @param scalar private key
186
+ * @returns new public key
187
+ */
176
188
  function scalarMultBase(scalar) {
177
- return scalarMult(CURVE.Gu, scalar);
189
+ return scalarMult(scalar, CURVE.Gu);
178
190
  }
179
191
  return {
180
- // NOTE: we can get 'y' coordinate from 'u', but Point.fromHex also wants 'x' coordinate oddity flag, and we cannot get 'x' without knowing 'v'
181
- // Need to add generic conversion between twisted edwards and complimentary curve for JubJub
182
192
  scalarMult,
183
193
  scalarMultBase,
184
- // NOTE: these function work on complimentary montgomery curve
185
- // getSharedSecret: (privateKey: Hex, publicKey: Hex) => scalarMult(publicKey, privateKey),
194
+ getSharedSecret: (privateKey, publicKey) => scalarMult(privateKey, publicKey),
186
195
  getPublicKey: (privateKey) => scalarMultBase(privateKey),
187
196
  Gu: CURVE.Gu,
188
197
  };
@@ -1,4 +1,4 @@
1
- /*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
1
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2
2
  import * as mod from './modular.js';
3
3
  const _0n = BigInt(0);
4
4
  const _1n = BigInt(1);