@noble/curves 0.8.0 → 0.8.1

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