@noble/curves 1.9.1 → 1.9.2

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 (189) hide show
  1. package/README.md +56 -25
  2. package/_shortw_utils.d.ts +7 -5
  3. package/_shortw_utils.d.ts.map +1 -1
  4. package/_shortw_utils.js +2 -8
  5. package/_shortw_utils.js.map +1 -1
  6. package/abstract/bls.d.ts +60 -24
  7. package/abstract/bls.d.ts.map +1 -1
  8. package/abstract/bls.js +158 -109
  9. package/abstract/bls.js.map +1 -1
  10. package/abstract/curve.d.ts +44 -9
  11. package/abstract/curve.d.ts.map +1 -1
  12. package/abstract/curve.js +86 -7
  13. package/abstract/curve.js.map +1 -1
  14. package/abstract/edwards.d.ts +112 -25
  15. package/abstract/edwards.d.ts.map +1 -1
  16. package/abstract/edwards.js +138 -102
  17. package/abstract/edwards.js.map +1 -1
  18. package/abstract/fft.d.ts +12 -10
  19. package/abstract/fft.d.ts.map +1 -1
  20. package/abstract/fft.js +12 -13
  21. package/abstract/fft.js.map +1 -1
  22. package/abstract/hash-to-curve.d.ts +25 -11
  23. package/abstract/hash-to-curve.d.ts.map +1 -1
  24. package/abstract/hash-to-curve.js +17 -14
  25. package/abstract/hash-to-curve.js.map +1 -1
  26. package/abstract/modular.d.ts +24 -11
  27. package/abstract/modular.d.ts.map +1 -1
  28. package/abstract/modular.js +49 -20
  29. package/abstract/modular.js.map +1 -1
  30. package/abstract/montgomery.d.ts +1 -1
  31. package/abstract/montgomery.d.ts.map +1 -1
  32. package/abstract/montgomery.js +5 -4
  33. package/abstract/montgomery.js.map +1 -1
  34. package/abstract/poseidon.d.ts +5 -13
  35. package/abstract/poseidon.d.ts.map +1 -1
  36. package/abstract/poseidon.js +12 -7
  37. package/abstract/poseidon.js.map +1 -1
  38. package/abstract/tower.d.ts +20 -46
  39. package/abstract/tower.d.ts.map +1 -1
  40. package/abstract/tower.js +9 -3
  41. package/abstract/tower.js.map +1 -1
  42. package/abstract/utils.d.ts +1 -115
  43. package/abstract/utils.d.ts.map +1 -1
  44. package/abstract/utils.js +17 -371
  45. package/abstract/utils.js.map +1 -1
  46. package/abstract/weierstrass.d.ts +132 -76
  47. package/abstract/weierstrass.d.ts.map +1 -1
  48. package/abstract/weierstrass.js +462 -398
  49. package/abstract/weierstrass.js.map +1 -1
  50. package/bls12-381.d.ts +2 -0
  51. package/bls12-381.d.ts.map +1 -1
  52. package/bls12-381.js +504 -466
  53. package/bls12-381.js.map +1 -1
  54. package/bn254.d.ts +2 -0
  55. package/bn254.d.ts.map +1 -1
  56. package/bn254.js +44 -32
  57. package/bn254.js.map +1 -1
  58. package/ed25519.d.ts +8 -5
  59. package/ed25519.d.ts.map +1 -1
  60. package/ed25519.js +67 -54
  61. package/ed25519.js.map +1 -1
  62. package/ed448.d.ts +10 -6
  63. package/ed448.d.ts.map +1 -1
  64. package/ed448.js +80 -57
  65. package/ed448.js.map +1 -1
  66. package/esm/_shortw_utils.d.ts +7 -5
  67. package/esm/_shortw_utils.d.ts.map +1 -1
  68. package/esm/_shortw_utils.js +2 -8
  69. package/esm/_shortw_utils.js.map +1 -1
  70. package/esm/abstract/bls.d.ts +60 -24
  71. package/esm/abstract/bls.d.ts.map +1 -1
  72. package/esm/abstract/bls.js +158 -109
  73. package/esm/abstract/bls.js.map +1 -1
  74. package/esm/abstract/curve.d.ts +44 -9
  75. package/esm/abstract/curve.d.ts.map +1 -1
  76. package/esm/abstract/curve.js +83 -8
  77. package/esm/abstract/curve.js.map +1 -1
  78. package/esm/abstract/edwards.d.ts +112 -25
  79. package/esm/abstract/edwards.d.ts.map +1 -1
  80. package/esm/abstract/edwards.js +138 -104
  81. package/esm/abstract/edwards.js.map +1 -1
  82. package/esm/abstract/fft.d.ts +12 -10
  83. package/esm/abstract/fft.d.ts.map +1 -1
  84. package/esm/abstract/fft.js +10 -11
  85. package/esm/abstract/fft.js.map +1 -1
  86. package/esm/abstract/hash-to-curve.d.ts +25 -11
  87. package/esm/abstract/hash-to-curve.d.ts.map +1 -1
  88. package/esm/abstract/hash-to-curve.js +17 -14
  89. package/esm/abstract/hash-to-curve.js.map +1 -1
  90. package/esm/abstract/modular.d.ts +24 -11
  91. package/esm/abstract/modular.d.ts.map +1 -1
  92. package/esm/abstract/modular.js +48 -19
  93. package/esm/abstract/modular.js.map +1 -1
  94. package/esm/abstract/montgomery.d.ts +1 -1
  95. package/esm/abstract/montgomery.d.ts.map +1 -1
  96. package/esm/abstract/montgomery.js +5 -4
  97. package/esm/abstract/montgomery.js.map +1 -1
  98. package/esm/abstract/poseidon.d.ts +5 -13
  99. package/esm/abstract/poseidon.d.ts.map +1 -1
  100. package/esm/abstract/poseidon.js +12 -7
  101. package/esm/abstract/poseidon.js.map +1 -1
  102. package/esm/abstract/tower.d.ts +20 -46
  103. package/esm/abstract/tower.d.ts.map +1 -1
  104. package/esm/abstract/tower.js +9 -3
  105. package/esm/abstract/tower.js.map +1 -1
  106. package/esm/abstract/utils.d.ts +1 -115
  107. package/esm/abstract/utils.d.ts.map +1 -1
  108. package/esm/abstract/utils.js +3 -344
  109. package/esm/abstract/utils.js.map +1 -1
  110. package/esm/abstract/weierstrass.d.ts +132 -76
  111. package/esm/abstract/weierstrass.d.ts.map +1 -1
  112. package/esm/abstract/weierstrass.js +460 -400
  113. package/esm/abstract/weierstrass.js.map +1 -1
  114. package/esm/bls12-381.d.ts +2 -0
  115. package/esm/bls12-381.d.ts.map +1 -1
  116. package/esm/bls12-381.js +503 -465
  117. package/esm/bls12-381.js.map +1 -1
  118. package/esm/bn254.d.ts +2 -0
  119. package/esm/bn254.d.ts.map +1 -1
  120. package/esm/bn254.js +41 -29
  121. package/esm/bn254.js.map +1 -1
  122. package/esm/ed25519.d.ts +8 -5
  123. package/esm/ed25519.d.ts.map +1 -1
  124. package/esm/ed25519.js +62 -49
  125. package/esm/ed25519.js.map +1 -1
  126. package/esm/ed448.d.ts +10 -6
  127. package/esm/ed448.d.ts.map +1 -1
  128. package/esm/ed448.js +74 -51
  129. package/esm/ed448.js.map +1 -1
  130. package/esm/misc.d.ts.map +1 -1
  131. package/esm/misc.js +31 -26
  132. package/esm/misc.js.map +1 -1
  133. package/esm/nist.d.ts +7 -16
  134. package/esm/nist.d.ts.map +1 -1
  135. package/esm/nist.js +86 -97
  136. package/esm/nist.js.map +1 -1
  137. package/esm/p256.d.ts +3 -3
  138. package/esm/p384.d.ts +3 -3
  139. package/esm/p521.d.ts +3 -3
  140. package/esm/secp256k1.d.ts +6 -6
  141. package/esm/secp256k1.d.ts.map +1 -1
  142. package/esm/secp256k1.js +43 -40
  143. package/esm/secp256k1.js.map +1 -1
  144. package/esm/utils.d.ts +96 -0
  145. package/esm/utils.d.ts.map +1 -0
  146. package/esm/utils.js +279 -0
  147. package/esm/utils.js.map +1 -0
  148. package/misc.d.ts.map +1 -1
  149. package/misc.js +35 -30
  150. package/misc.js.map +1 -1
  151. package/nist.d.ts +7 -16
  152. package/nist.d.ts.map +1 -1
  153. package/nist.js +86 -97
  154. package/nist.js.map +1 -1
  155. package/p256.d.ts +3 -3
  156. package/p384.d.ts +3 -3
  157. package/p521.d.ts +3 -3
  158. package/package.json +14 -5
  159. package/secp256k1.d.ts +6 -6
  160. package/secp256k1.d.ts.map +1 -1
  161. package/secp256k1.js +46 -43
  162. package/secp256k1.js.map +1 -1
  163. package/src/_shortw_utils.ts +5 -15
  164. package/src/abstract/bls.ts +260 -145
  165. package/src/abstract/curve.ts +115 -13
  166. package/src/abstract/edwards.ts +279 -138
  167. package/src/abstract/fft.ts +30 -19
  168. package/src/abstract/hash-to-curve.ts +51 -27
  169. package/src/abstract/modular.ts +49 -28
  170. package/src/abstract/montgomery.ts +9 -7
  171. package/src/abstract/poseidon.ts +22 -18
  172. package/src/abstract/tower.ts +36 -67
  173. package/src/abstract/utils.ts +3 -378
  174. package/src/abstract/weierstrass.ts +700 -453
  175. package/src/bls12-381.ts +540 -489
  176. package/src/bn254.ts +47 -35
  177. package/src/ed25519.ts +80 -64
  178. package/src/ed448.ts +129 -92
  179. package/src/misc.ts +39 -34
  180. package/src/nist.ts +138 -127
  181. package/src/p256.ts +3 -3
  182. package/src/p384.ts +3 -3
  183. package/src/p521.ts +3 -3
  184. package/src/secp256k1.ts +58 -46
  185. package/src/utils.ts +328 -0
  186. package/utils.d.ts +96 -0
  187. package/utils.d.ts.map +1 -0
  188. package/utils.js +313 -0
  189. package/utils.js.map +1 -0
@@ -1,26 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DER = exports.DERErr = void 0;
4
+ exports._legacyHelperEquat = _legacyHelperEquat;
5
+ exports._legacyHelperNormPriv = _legacyHelperNormPriv;
6
+ exports.weierstrassN = weierstrassN;
4
7
  exports.weierstrassPoints = weierstrassPoints;
8
+ exports.ecdsa = ecdsa;
5
9
  exports.weierstrass = weierstrass;
6
10
  exports.SWUFpSqrtRatio = SWUFpSqrtRatio;
7
11
  exports.mapToCurveSimpleSWU = mapToCurveSimpleSWU;
8
12
  /**
9
13
  * Short Weierstrass curve methods. The formula is: y² = x³ + ax + b.
10
14
  *
11
- * ### Parameters
12
- *
13
- * To initialize a weierstrass curve, one needs to pass following params:
14
- *
15
- * * a: formula param
16
- * * b: formula param
17
- * * Fp: finite field of prime characteristic P; may be complex (Fp2). Arithmetics is done in field
18
- * * n: order of prime subgroup a.k.a total amount of valid curve points
19
- * * Gx: Base point (x, y) aka generator point. Gx = x coordinate
20
- * * Gy: ...y coordinate
21
- * * h: cofactor, usually 1. h*n = curve group order (n is only subgroup order)
22
- * * lowS: whether to enable (default) or disable "low-s" non-malleable signatures
23
- *
24
15
  * ### Design rationale for types
25
16
  *
26
17
  * * Interaction between classes from different curves should fail:
@@ -45,45 +36,16 @@ exports.mapToCurveSimpleSWU = mapToCurveSimpleSWU;
45
36
  * @module
46
37
  */
47
38
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
48
- // prettier-ignore
39
+ const hmac_js_1 = require("@noble/hashes/hmac.js");
40
+ const utils_ts_1 = require("../utils.js");
49
41
  const curve_ts_1 = require("./curve.js");
50
- // prettier-ignore
51
42
  const modular_ts_1 = require("./modular.js");
52
- // prettier-ignore
53
- const utils_ts_1 = require("./utils.js");
54
43
  function validateSigVerOpts(opts) {
55
44
  if (opts.lowS !== undefined)
56
45
  (0, utils_ts_1.abool)('lowS', opts.lowS);
57
46
  if (opts.prehash !== undefined)
58
47
  (0, utils_ts_1.abool)('prehash', opts.prehash);
59
48
  }
60
- function validatePointOpts(curve) {
61
- const opts = (0, curve_ts_1.validateBasic)(curve);
62
- (0, utils_ts_1.validateObject)(opts, {
63
- a: 'field',
64
- b: 'field',
65
- }, {
66
- allowInfinityPoint: 'boolean',
67
- allowedPrivateKeyLengths: 'array',
68
- clearCofactor: 'function',
69
- fromBytes: 'function',
70
- isTorsionFree: 'function',
71
- toBytes: 'function',
72
- wrapPrivateKey: 'boolean',
73
- });
74
- const { endo, Fp, a } = opts;
75
- if (endo) {
76
- if (!Fp.eql(a, Fp.ZERO)) {
77
- throw new Error('invalid endo: CURVE.a must be 0');
78
- }
79
- if (typeof endo !== 'object' ||
80
- typeof endo.beta !== 'bigint' ||
81
- typeof endo.splitScalar !== 'function') {
82
- throw new Error('invalid endo: expected "beta": bigint and "splitScalar": function');
83
- }
84
- }
85
- return Object.freeze({ ...opts });
86
- }
87
49
  class DERErr extends Error {
88
50
  constructor(m = '') {
89
51
  super(m);
@@ -201,40 +163,139 @@ exports.DER = {
201
163
  return tlv.encode(0x30, seq);
202
164
  },
203
165
  };
204
- function numToSizedHex(num, size) {
205
- return (0, utils_ts_1.bytesToHex)((0, utils_ts_1.numberToBytesBE)(num, size));
206
- }
207
166
  // Be friendly to bad ECMAScript parsers by not using bigint literals
208
167
  // prettier-ignore
209
168
  const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);
210
- function weierstrassPoints(opts) {
211
- const CURVE = validatePointOpts(opts);
212
- const { Fp } = CURVE; // All curves has same field / group length as for now, but they can differ
213
- const Fn = (0, modular_ts_1.Field)(CURVE.n, CURVE.nBitLength);
214
- const toBytes = CURVE.toBytes ||
215
- ((_c, point, _isCompressed) => {
216
- const a = point.toAffine();
217
- return (0, utils_ts_1.concatBytes)(Uint8Array.from([0x04]), Fp.toBytes(a.x), Fp.toBytes(a.y));
218
- });
219
- const fromBytes = CURVE.fromBytes ||
220
- ((bytes) => {
221
- // const head = bytes[0];
222
- const tail = bytes.subarray(1);
223
- // if (head !== 0x04) throw new Error('Only non-compressed encoding is supported');
224
- const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES));
225
- const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES));
226
- return { x, y };
227
- });
169
+ // TODO: remove
170
+ function _legacyHelperEquat(Fp, a, b) {
228
171
  /**
229
172
  * y² = x³ + ax + b: Short weierstrass curve formula. Takes x, returns y².
230
173
  * @returns y²
231
174
  */
232
175
  function weierstrassEquation(x) {
233
- const { a, b } = CURVE;
234
176
  const x2 = Fp.sqr(x); // x * x
235
177
  const x3 = Fp.mul(x2, x); // x² * x
236
178
  return Fp.add(Fp.add(x3, Fp.mul(x, a)), b); // x³ + a * x + b
237
179
  }
180
+ return weierstrassEquation;
181
+ }
182
+ function _legacyHelperNormPriv(Fn, allowedPrivateKeyLengths, wrapPrivateKey) {
183
+ const { BYTES: expected } = Fn;
184
+ // Validates if priv key is valid and converts it to bigint.
185
+ function normPrivateKeyToScalar(key) {
186
+ let num;
187
+ if (typeof key === 'bigint') {
188
+ num = key;
189
+ }
190
+ else {
191
+ let bytes = (0, utils_ts_1.ensureBytes)('private key', key);
192
+ if (allowedPrivateKeyLengths) {
193
+ if (!allowedPrivateKeyLengths.includes(bytes.length * 2))
194
+ throw new Error('invalid private key');
195
+ const padded = new Uint8Array(expected);
196
+ padded.set(bytes, padded.length - bytes.length);
197
+ bytes = padded;
198
+ }
199
+ try {
200
+ num = Fn.fromBytes(bytes);
201
+ }
202
+ catch (error) {
203
+ throw new Error(`invalid private key: expected ui8a of size ${expected}, got ${typeof key}`);
204
+ }
205
+ }
206
+ if (wrapPrivateKey)
207
+ num = Fn.create(num); // disabled by default, enabled for BLS
208
+ if (!Fn.isValidNot0(num))
209
+ throw new Error('invalid private key: out of range [1..N-1]');
210
+ return num;
211
+ }
212
+ return normPrivateKeyToScalar;
213
+ }
214
+ function weierstrassN(CURVE, curveOpts = {}) {
215
+ const { Fp, Fn } = (0, curve_ts_1._createCurveFields)('weierstrass', CURVE, curveOpts);
216
+ const { h: cofactor, n: CURVE_ORDER } = CURVE;
217
+ (0, utils_ts_1._validateObject)(curveOpts, {}, {
218
+ allowInfinityPoint: 'boolean',
219
+ clearCofactor: 'function',
220
+ isTorsionFree: 'function',
221
+ fromBytes: 'function',
222
+ toBytes: 'function',
223
+ endo: 'object',
224
+ wrapPrivateKey: 'boolean',
225
+ });
226
+ const { endo } = curveOpts;
227
+ if (endo) {
228
+ // validateObject(endo, { beta: 'bigint', splitScalar: 'function' });
229
+ if (!Fp.is0(CURVE.a) ||
230
+ typeof endo.beta !== 'bigint' ||
231
+ typeof endo.splitScalar !== 'function') {
232
+ throw new Error('invalid endo: expected "beta": bigint and "splitScalar": function');
233
+ }
234
+ }
235
+ function assertCompressionIsSupported() {
236
+ if (!Fp.isOdd)
237
+ throw new Error('compression is not supported: Field does not have .isOdd()');
238
+ }
239
+ // Implements IEEE P1363 point encoding
240
+ function pointToBytes(_c, point, isCompressed) {
241
+ const { x, y } = point.toAffine();
242
+ const bx = Fp.toBytes(x);
243
+ (0, utils_ts_1.abool)('isCompressed', isCompressed);
244
+ if (isCompressed) {
245
+ assertCompressionIsSupported();
246
+ const hasEvenY = !Fp.isOdd(y);
247
+ return (0, utils_ts_1.concatBytes)(pprefix(hasEvenY), bx);
248
+ }
249
+ else {
250
+ return (0, utils_ts_1.concatBytes)(Uint8Array.of(0x04), bx, Fp.toBytes(y));
251
+ }
252
+ }
253
+ function pointFromBytes(bytes) {
254
+ (0, utils_ts_1.abytes)(bytes);
255
+ const L = Fp.BYTES;
256
+ const LC = L + 1; // length compressed, e.g. 33 for 32-byte field
257
+ const LU = 2 * L + 1; // length uncompressed, e.g. 65 for 32-byte field
258
+ const length = bytes.length;
259
+ const head = bytes[0];
260
+ const tail = bytes.subarray(1);
261
+ // No actual validation is done here: use .assertValidity()
262
+ if (length === LC && (head === 0x02 || head === 0x03)) {
263
+ const x = Fp.fromBytes(tail);
264
+ if (!Fp.isValid(x))
265
+ throw new Error('bad point: is not on curve, wrong x');
266
+ const y2 = weierstrassEquation(x); // y² = x³ + ax + b
267
+ let y;
268
+ try {
269
+ y = Fp.sqrt(y2); // y = y² ^ (p+1)/4
270
+ }
271
+ catch (sqrtError) {
272
+ const err = sqrtError instanceof Error ? ': ' + sqrtError.message : '';
273
+ throw new Error('bad point: is not on curve, sqrt error' + err);
274
+ }
275
+ assertCompressionIsSupported();
276
+ const isYOdd = Fp.isOdd(y); // (y & _1n) === _1n;
277
+ const isHeadOdd = (head & 1) === 1; // ECDSA-specific
278
+ if (isHeadOdd !== isYOdd)
279
+ y = Fp.neg(y);
280
+ return { x, y };
281
+ }
282
+ else if (length === LU && head === 0x04) {
283
+ // TODO: more checks
284
+ const x = Fp.fromBytes(tail.subarray(L * 0, L * 1));
285
+ const y = Fp.fromBytes(tail.subarray(L * 1, L * 2));
286
+ if (!isValidXY(x, y))
287
+ throw new Error('bad point: is not on curve');
288
+ return { x, y };
289
+ }
290
+ else {
291
+ throw new Error(`bad point: got length ${length}, expected compressed=${LC} or uncompressed=${LU}`);
292
+ }
293
+ }
294
+ const toBytes = curveOpts.toBytes || pointToBytes;
295
+ const fromBytes = curveOpts.fromBytes || pointFromBytes;
296
+ const weierstrassEquation = _legacyHelperEquat(Fp, CURVE.a, CURVE.b);
297
+ // TODO: move top-level
298
+ /** Checks whether equation holds for given x, y: y² == x³ + ax + b */
238
299
  function isValidXY(x, y) {
239
300
  const left = Fp.sqr(y); // y²
240
301
  const right = weierstrassEquation(x); // x³ + ax + b
@@ -250,36 +311,11 @@ function weierstrassPoints(opts) {
250
311
  const _27b2 = Fp.mul(Fp.sqr(CURVE.b), BigInt(27));
251
312
  if (Fp.is0(Fp.add(_4a3, _27b2)))
252
313
  throw new Error('bad curve params: a or b');
253
- // Valid group elements reside in range 1..n-1
254
- function isWithinCurveOrder(num) {
255
- return (0, utils_ts_1.inRange)(num, _1n, CURVE.n);
256
- }
257
- // Validates if priv key is valid and converts it to bigint.
258
- // Supports options allowedPrivateKeyLengths and wrapPrivateKey.
259
- function normPrivateKeyToScalar(key) {
260
- const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n: N } = CURVE;
261
- if (lengths && typeof key !== 'bigint') {
262
- if ((0, utils_ts_1.isBytes)(key))
263
- key = (0, utils_ts_1.bytesToHex)(key);
264
- // Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes
265
- if (typeof key !== 'string' || !lengths.includes(key.length))
266
- throw new Error('invalid private key');
267
- key = key.padStart(nByteLength * 2, '0');
268
- }
269
- let num;
270
- try {
271
- num =
272
- typeof key === 'bigint'
273
- ? key
274
- : (0, utils_ts_1.bytesToNumberBE)((0, utils_ts_1.ensureBytes)('private key', key, nByteLength));
275
- }
276
- catch (error) {
277
- throw new Error('invalid private key, expected hex or ' + nByteLength + ' bytes, got ' + typeof key);
278
- }
279
- if (wrapPrivateKey)
280
- num = (0, modular_ts_1.mod)(num, N); // disabled by default, enabled for BLS
281
- (0, utils_ts_1.aInRange)('private key', num, _1n, N); // num in range [1..N-1]
282
- return num;
314
+ /** Asserts coordinate is valid: 0 <= n < Fp.ORDER. */
315
+ function acoord(title, n, banZero = false) {
316
+ if (!Fp.isValid(n) || (banZero && Fp.is0(n)))
317
+ throw new Error(`bad point coordinate ${title}`);
318
+ return n;
283
319
  }
284
320
  function aprjpoint(other) {
285
321
  if (!(other instanceof Point))
@@ -315,50 +351,48 @@ function weierstrassPoints(opts) {
315
351
  // (0, 1, 0) aka ZERO is invalid in most contexts.
316
352
  // In BLS, ZERO can be serialized, so we allow it.
317
353
  // (0, 0, 0) is invalid representation of ZERO.
318
- if (CURVE.allowInfinityPoint && !Fp.is0(p.py))
354
+ if (curveOpts.allowInfinityPoint && !Fp.is0(p.py))
319
355
  return;
320
356
  throw new Error('bad point: ZERO');
321
357
  }
322
358
  // Some 3rd-party test vectors require different wording between here & `fromCompressedHex`
323
359
  const { x, y } = p.toAffine();
324
- // Check if x, y are valid field elements
325
360
  if (!Fp.isValid(x) || !Fp.isValid(y))
326
- throw new Error('bad point: x or y not FE');
361
+ throw new Error('bad point: x or y not field elements');
327
362
  if (!isValidXY(x, y))
328
363
  throw new Error('bad point: equation left != right');
329
364
  if (!p.isTorsionFree())
330
365
  throw new Error('bad point: not in prime-order subgroup');
331
366
  return true;
332
367
  });
368
+ function finishEndo(endoBeta, k1p, k2p, k1neg, k2neg) {
369
+ k2p = new Point(Fp.mul(k2p.px, endoBeta), k2p.py, k2p.pz);
370
+ k1p = (0, curve_ts_1.negateCt)(k1neg, k1p);
371
+ k2p = (0, curve_ts_1.negateCt)(k2neg, k2p);
372
+ return k1p.add(k2p);
373
+ }
333
374
  /**
334
- * Projective Point works in 3d / projective (homogeneous) coordinates: (X, Y, Z) ∋ (x=X/Z, y=Y/Z)
335
- * Default Point works in 2d / affine coordinates: (x, y)
375
+ * Projective Point works in 3d / projective (homogeneous) coordinates:(X, Y, Z) ∋ (x=X/Z, y=Y/Z).
376
+ * Default Point works in 2d / affine coordinates: (x, y).
336
377
  * We're doing calculations in projective, because its operations don't require costly inversion.
337
378
  */
338
379
  class Point {
380
+ /** Does NOT validate if the point is valid. Use `.assertValidity()`. */
339
381
  constructor(px, py, pz) {
340
- if (px == null || !Fp.isValid(px))
341
- throw new Error('x required');
342
- if (py == null || !Fp.isValid(py) || Fp.is0(py))
343
- throw new Error('y required');
344
- if (pz == null || !Fp.isValid(pz))
345
- throw new Error('z required');
346
- this.px = px;
347
- this.py = py;
348
- this.pz = pz;
382
+ this.px = acoord('x', px);
383
+ this.py = acoord('y', py, true);
384
+ this.pz = acoord('z', pz);
349
385
  Object.freeze(this);
350
386
  }
351
- // Does not validate if the point is on-curve.
352
- // Use fromHex instead, or call assertValidity() later.
387
+ /** Does NOT validate if the point is valid. Use `.assertValidity()`. */
353
388
  static fromAffine(p) {
354
389
  const { x, y } = p || {};
355
390
  if (!p || !Fp.isValid(x) || !Fp.isValid(y))
356
391
  throw new Error('invalid affine point');
357
392
  if (p instanceof Point)
358
393
  throw new Error('projective point not allowed');
359
- const is0 = (i) => Fp.eql(i, Fp.ZERO);
360
- // fromAffine(x:0, y:0) would produce (x:0, y:0, z:1), but we need (x:0, y:1, z:0)
361
- if (is0(x) && is0(y))
394
+ // (0, 0) would've produced (0, 0, 1) - instead, we need (0, 1, 0)
395
+ if (Fp.is0(x) && Fp.is0(y))
362
396
  return Point.ZERO;
363
397
  return new Point(x, y, Fp.ONE);
364
398
  }
@@ -368,50 +402,56 @@ function weierstrassPoints(opts) {
368
402
  get y() {
369
403
  return this.toAffine().y;
370
404
  }
371
- /**
372
- * Takes a bunch of Projective Points but executes only one
373
- * inversion on all of them. Inversion is very slow operation,
374
- * so this improves performance massively.
375
- * Optimization: converts a list of projective points to a list of identical points with Z=1.
376
- */
377
405
  static normalizeZ(points) {
378
- const toInv = (0, modular_ts_1.FpInvertBatch)(Fp, points.map((p) => p.pz));
379
- return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine);
406
+ return (0, curve_ts_1.normalizeZ)(Point, 'pz', points);
380
407
  }
381
- /**
382
- * Converts hash string or Uint8Array to Point.
383
- * @param hex short/long ECDSA hex
384
- */
408
+ static fromBytes(bytes) {
409
+ (0, utils_ts_1.abytes)(bytes);
410
+ return Point.fromHex(bytes);
411
+ }
412
+ /** Converts hash string or Uint8Array to Point. */
385
413
  static fromHex(hex) {
386
414
  const P = Point.fromAffine(fromBytes((0, utils_ts_1.ensureBytes)('pointHex', hex)));
387
415
  P.assertValidity();
388
416
  return P;
389
417
  }
390
- // Multiplies generator point by privateKey.
418
+ /** Multiplies generator point by privateKey. */
391
419
  static fromPrivateKey(privateKey) {
420
+ const normPrivateKeyToScalar = _legacyHelperNormPriv(Fn, curveOpts.allowedPrivateKeyLengths, curveOpts.wrapPrivateKey);
392
421
  return Point.BASE.multiply(normPrivateKeyToScalar(privateKey));
393
422
  }
394
- // Multiscalar Multiplication
423
+ /** Multiscalar Multiplication */
395
424
  static msm(points, scalars) {
396
425
  return (0, curve_ts_1.pippenger)(Point, Fn, points, scalars);
397
426
  }
398
- // "Private method", don't use it directly
399
- _setWindowSize(windowSize) {
427
+ /**
428
+ *
429
+ * @param windowSize
430
+ * @param isLazy true will defer table computation until the first multiplication
431
+ * @returns
432
+ */
433
+ precompute(windowSize = 8, isLazy = true) {
400
434
  wnaf.setWindowSize(this, windowSize);
435
+ if (!isLazy)
436
+ this.multiply(_3n); // random number
437
+ return this;
401
438
  }
402
- // A point on curve is valid if it conforms to equation.
439
+ /** "Private method", don't use it directly */
440
+ _setWindowSize(windowSize) {
441
+ this.precompute(windowSize);
442
+ }
443
+ // TODO: return `this`
444
+ /** A point on curve is valid if it conforms to equation. */
403
445
  assertValidity() {
404
446
  assertValidMemo(this);
405
447
  }
406
448
  hasEvenY() {
407
449
  const { y } = this.toAffine();
408
- if (Fp.isOdd)
409
- return !Fp.isOdd(y);
410
- throw new Error("Field doesn't support isOdd");
450
+ if (!Fp.isOdd)
451
+ throw new Error("Field doesn't support isOdd");
452
+ return !Fp.isOdd(y);
411
453
  }
412
- /**
413
- * Compare one point to another.
414
- */
454
+ /** Compare one point to another. */
415
455
  equals(other) {
416
456
  aprjpoint(other);
417
457
  const { px: X1, py: Y1, pz: Z1 } = this;
@@ -420,9 +460,7 @@ function weierstrassPoints(opts) {
420
460
  const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1));
421
461
  return U1 && U2;
422
462
  }
423
- /**
424
- * Flips point to one corresponding to (x, -y) in Affine coordinates.
425
- */
463
+ /** Flips point to one corresponding to (x, -y) in Affine coordinates. */
426
464
  negate() {
427
465
  return new Point(this.px, Fp.neg(this.py), this.pz);
428
466
  }
@@ -527,47 +565,6 @@ function weierstrassPoints(opts) {
527
565
  is0() {
528
566
  return this.equals(Point.ZERO);
529
567
  }
530
- wNAF(n) {
531
- return wnaf.wNAFCached(this, n, Point.normalizeZ);
532
- }
533
- /**
534
- * Non-constant-time multiplication. Uses double-and-add algorithm.
535
- * It's faster, but should only be used when you don't care about
536
- * an exposed private key e.g. sig verification, which works over *public* keys.
537
- */
538
- multiplyUnsafe(sc) {
539
- const { endo, n: N } = CURVE;
540
- (0, utils_ts_1.aInRange)('scalar', sc, _0n, N);
541
- const I = Point.ZERO;
542
- if (sc === _0n)
543
- return I;
544
- if (this.is0() || sc === _1n)
545
- return this;
546
- // Case a: no endomorphism. Case b: has precomputes.
547
- if (!endo || wnaf.hasPrecomputes(this))
548
- return wnaf.wNAFCachedUnsafe(this, sc, Point.normalizeZ);
549
- // Case c: endomorphism
550
- /** See docs for {@link EndomorphismOpts} */
551
- let { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc);
552
- let k1p = I;
553
- let k2p = I;
554
- let d = this;
555
- while (k1 > _0n || k2 > _0n) {
556
- if (k1 & _1n)
557
- k1p = k1p.add(d);
558
- if (k2 & _1n)
559
- k2p = k2p.add(d);
560
- d = d.double();
561
- k1 >>= _1n;
562
- k2 >>= _1n;
563
- }
564
- if (k1neg)
565
- k1p = k1p.negate();
566
- if (k2neg)
567
- k2p = k2p.negate();
568
- k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
569
- return k1p.add(k2p);
570
- }
571
568
  /**
572
569
  * Constant time multiplication.
573
570
  * Uses wNAF method. Windowed method may be 10% faster,
@@ -578,22 +575,21 @@ function weierstrassPoints(opts) {
578
575
  * @returns New point
579
576
  */
580
577
  multiply(scalar) {
581
- const { endo, n: N } = CURVE;
582
- (0, utils_ts_1.aInRange)('scalar', scalar, _1n, N);
578
+ const { endo } = curveOpts;
579
+ if (!Fn.isValidNot0(scalar))
580
+ throw new Error('invalid scalar: out of range'); // 0 is invalid
583
581
  let point, fake; // Fake point is used to const-time mult
582
+ const mul = (n) => wnaf.wNAFCached(this, n, Point.normalizeZ);
584
583
  /** See docs for {@link EndomorphismOpts} */
585
584
  if (endo) {
586
585
  const { k1neg, k1, k2neg, k2 } = endo.splitScalar(scalar);
587
- let { p: k1p, f: f1p } = this.wNAF(k1);
588
- let { p: k2p, f: f2p } = this.wNAF(k2);
589
- k1p = wnaf.constTimeNegate(k1neg, k1p);
590
- k2p = wnaf.constTimeNegate(k2neg, k2p);
591
- k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
592
- point = k1p.add(k2p);
593
- fake = f1p.add(f2p);
586
+ const { p: k1p, f: k1f } = mul(k1);
587
+ const { p: k2p, f: k2f } = mul(k2);
588
+ fake = k1f.add(k2f);
589
+ point = finishEndo(endo.beta, k1p, k2p, k1neg, k2neg);
594
590
  }
595
591
  else {
596
- const { p, f } = this.wNAF(scalar);
592
+ const { p, f } = mul(scalar);
597
593
  point = p;
598
594
  fake = f;
599
595
  }
@@ -601,162 +597,131 @@ function weierstrassPoints(opts) {
601
597
  return Point.normalizeZ([point, fake])[0];
602
598
  }
603
599
  /**
604
- * Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly.
605
- * Not using Strauss-Shamir trick: precomputation tables are faster.
606
- * The trick could be useful if both P and Q are not G (not in our case).
607
- * @returns non-zero affine point
600
+ * Non-constant-time multiplication. Uses double-and-add algorithm.
601
+ * It's faster, but should only be used when you don't care about
602
+ * an exposed private key e.g. sig verification, which works over *public* keys.
608
603
  */
604
+ multiplyUnsafe(sc) {
605
+ const { endo } = curveOpts;
606
+ const p = this;
607
+ if (!Fn.isValid(sc))
608
+ throw new Error('invalid scalar: out of range'); // 0 is valid
609
+ if (sc === _0n || p.is0())
610
+ return Point.ZERO;
611
+ if (sc === _1n)
612
+ return p; // fast-path
613
+ if (wnaf.hasPrecomputes(this))
614
+ return this.multiply(sc);
615
+ if (endo) {
616
+ const { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc);
617
+ // `wNAFCachedUnsafe` is 30% slower
618
+ const { p1, p2 } = (0, curve_ts_1.mulEndoUnsafe)(Point, p, k1, k2);
619
+ return finishEndo(endo.beta, p1, p2, k1neg, k2neg);
620
+ }
621
+ else {
622
+ return wnaf.wNAFCachedUnsafe(p, sc);
623
+ }
624
+ }
609
625
  multiplyAndAddUnsafe(Q, a, b) {
610
- const G = Point.BASE; // No Strauss-Shamir trick: we have 10% faster G precomputes
611
- const mul = (P, a // Select faster multiply() method
612
- ) => (a === _0n || a === _1n || !P.equals(G) ? P.multiplyUnsafe(a) : P.multiply(a));
613
- const sum = mul(this, a).add(mul(Q, b));
626
+ const sum = this.multiplyUnsafe(a).add(Q.multiplyUnsafe(b));
614
627
  return sum.is0() ? undefined : sum;
615
628
  }
616
- // Converts Projective point to affine (x, y) coordinates.
617
- // Can accept precomputed Z^-1 - for example, from invertBatch.
618
- // (x, y, z) (x=x/z, y=y/z)
619
- toAffine(iz) {
620
- return toAffineMemo(this, iz);
629
+ /**
630
+ * Converts Projective point to affine (x, y) coordinates.
631
+ * @param invertedZ Z^-1 (inverted zero) - optional, precomputation is useful for invertBatch
632
+ */
633
+ toAffine(invertedZ) {
634
+ return toAffineMemo(this, invertedZ);
621
635
  }
636
+ /**
637
+ * Checks whether Point is free of torsion elements (is in prime subgroup).
638
+ * Always torsion-free for cofactor=1 curves.
639
+ */
622
640
  isTorsionFree() {
623
- const { h: cofactor, isTorsionFree } = CURVE;
641
+ const { isTorsionFree } = curveOpts;
624
642
  if (cofactor === _1n)
625
- return true; // No subgroups, always torsion-free
643
+ return true;
626
644
  if (isTorsionFree)
627
645
  return isTorsionFree(Point, this);
628
- throw new Error('isTorsionFree() has not been declared for the elliptic curve');
646
+ return wnaf.wNAFCachedUnsafe(this, CURVE_ORDER).is0();
629
647
  }
630
648
  clearCofactor() {
631
- const { h: cofactor, clearCofactor } = CURVE;
649
+ const { clearCofactor } = curveOpts;
632
650
  if (cofactor === _1n)
633
651
  return this; // Fast-path
634
652
  if (clearCofactor)
635
653
  return clearCofactor(Point, this);
636
- return this.multiplyUnsafe(CURVE.h);
654
+ return this.multiplyUnsafe(cofactor);
637
655
  }
638
- toRawBytes(isCompressed = true) {
656
+ toBytes(isCompressed = true) {
639
657
  (0, utils_ts_1.abool)('isCompressed', isCompressed);
640
658
  this.assertValidity();
641
659
  return toBytes(Point, this, isCompressed);
642
660
  }
661
+ /** @deprecated use `toBytes` */
662
+ toRawBytes(isCompressed = true) {
663
+ return this.toBytes(isCompressed);
664
+ }
643
665
  toHex(isCompressed = true) {
644
- (0, utils_ts_1.abool)('isCompressed', isCompressed);
645
- return (0, utils_ts_1.bytesToHex)(this.toRawBytes(isCompressed));
666
+ return (0, utils_ts_1.bytesToHex)(this.toBytes(isCompressed));
667
+ }
668
+ toString() {
669
+ return `<Point ${this.is0() ? 'ZERO' : this.toHex()}>`;
646
670
  }
647
671
  }
648
672
  // base / generator point
649
673
  Point.BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE);
650
674
  // zero / infinity / identity point
651
675
  Point.ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO); // 0, 1, 0
652
- const { endo, nBitLength } = CURVE;
653
- const wnaf = (0, curve_ts_1.wNAF)(Point, endo ? Math.ceil(nBitLength / 2) : nBitLength);
654
- return {
655
- CURVE,
656
- ProjectivePoint: Point,
657
- normPrivateKeyToScalar,
658
- weierstrassEquation,
659
- isWithinCurveOrder,
660
- };
676
+ // fields
677
+ Point.Fp = Fp;
678
+ Point.Fn = Fn;
679
+ const bits = Fn.BITS;
680
+ const wnaf = (0, curve_ts_1.wNAF)(Point, curveOpts.endo ? Math.ceil(bits / 2) : bits);
681
+ return Point;
661
682
  }
662
- function validateOpts(curve) {
663
- const opts = (0, curve_ts_1.validateBasic)(curve);
664
- (0, utils_ts_1.validateObject)(opts, {
665
- hash: 'hash',
683
+ // _legacyWeierstrass
684
+ /** @deprecated use `weierstrassN` */
685
+ function weierstrassPoints(c) {
686
+ const { CURVE, curveOpts } = _weierstrass_legacy_opts_to_new(c);
687
+ const Point = weierstrassN(CURVE, curveOpts);
688
+ return _weierstrass_new_output_to_legacy(c, Point);
689
+ }
690
+ // Points start with byte 0x02 when y is even; otherwise 0x03
691
+ function pprefix(hasEvenY) {
692
+ return Uint8Array.of(hasEvenY ? 0x02 : 0x03);
693
+ }
694
+ function ecdsa(Point, ecdsaOpts, curveOpts = {}) {
695
+ (0, utils_ts_1._validateObject)(ecdsaOpts, { hash: 'function' }, {
666
696
  hmac: 'function',
697
+ lowS: 'boolean',
667
698
  randomBytes: 'function',
668
- }, {
669
699
  bits2int: 'function',
670
700
  bits2int_modN: 'function',
671
- lowS: 'boolean',
672
- });
673
- return Object.freeze({ lowS: true, ...opts });
674
- }
675
- /**
676
- * Creates short weierstrass curve and ECDSA signature methods for it.
677
- * @example
678
- * import { Field } from '@noble/curves/abstract/modular';
679
- * // Before that, define BigInt-s: a, b, p, n, Gx, Gy
680
- * const curve = weierstrass({ a, b, Fp: Field(p), n, Gx, Gy, h: 1n })
681
- */
682
- function weierstrass(curveDef) {
683
- const CURVE = validateOpts(curveDef);
684
- const { Fp, n: CURVE_ORDER, nByteLength, nBitLength } = CURVE;
685
- const compressedLen = Fp.BYTES + 1; // e.g. 33 for 32
686
- const uncompressedLen = 2 * Fp.BYTES + 1; // e.g. 65 for 32
687
- function modN(a) {
688
- return (0, modular_ts_1.mod)(a, CURVE_ORDER);
689
- }
690
- function invN(a) {
691
- return (0, modular_ts_1.invert)(a, CURVE_ORDER);
692
- }
693
- const { ProjectivePoint: Point, normPrivateKeyToScalar, weierstrassEquation, isWithinCurveOrder, } = weierstrassPoints({
694
- ...CURVE,
695
- toBytes(_c, point, isCompressed) {
696
- const a = point.toAffine();
697
- const x = Fp.toBytes(a.x);
698
- const cat = utils_ts_1.concatBytes;
699
- (0, utils_ts_1.abool)('isCompressed', isCompressed);
700
- if (isCompressed) {
701
- return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x);
702
- }
703
- else {
704
- return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y));
705
- }
706
- },
707
- fromBytes(bytes) {
708
- const len = bytes.length;
709
- const head = bytes[0];
710
- const tail = bytes.subarray(1);
711
- // this.assertValidity() is done inside of fromHex
712
- if (len === compressedLen && (head === 0x02 || head === 0x03)) {
713
- const x = (0, utils_ts_1.bytesToNumberBE)(tail);
714
- if (!(0, utils_ts_1.inRange)(x, _1n, Fp.ORDER))
715
- throw new Error('Point is not on curve');
716
- const y2 = weierstrassEquation(x); // y² = x³ + ax + b
717
- let y;
718
- try {
719
- y = Fp.sqrt(y2); // y = y² ^ (p+1)/4
720
- }
721
- catch (sqrtError) {
722
- const suffix = sqrtError instanceof Error ? ': ' + sqrtError.message : '';
723
- throw new Error('Point is not on curve' + suffix);
724
- }
725
- const isYOdd = (y & _1n) === _1n;
726
- // ECDSA
727
- const isHeadOdd = (head & 1) === 1;
728
- if (isHeadOdd !== isYOdd)
729
- y = Fp.neg(y);
730
- return { x, y };
731
- }
732
- else if (len === uncompressedLen && head === 0x04) {
733
- const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES));
734
- const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES));
735
- return { x, y };
736
- }
737
- else {
738
- const cl = compressedLen;
739
- const ul = uncompressedLen;
740
- throw new Error('invalid Point, expected length of ' + cl + ', or uncompressed ' + ul + ', got ' + len);
741
- }
742
- },
743
701
  });
702
+ const randomBytes_ = ecdsaOpts.randomBytes || utils_ts_1.randomBytes;
703
+ const hmac_ = ecdsaOpts.hmac ||
704
+ ((key, ...msgs) => (0, hmac_js_1.hmac)(ecdsaOpts.hash, key, (0, utils_ts_1.concatBytes)(...msgs)));
705
+ const { Fp, Fn } = Point;
706
+ const { ORDER: CURVE_ORDER, BITS: fnBits } = Fn;
744
707
  function isBiggerThanHalfOrder(number) {
745
708
  const HALF = CURVE_ORDER >> _1n;
746
709
  return number > HALF;
747
710
  }
748
711
  function normalizeS(s) {
749
- return isBiggerThanHalfOrder(s) ? modN(-s) : s;
712
+ return isBiggerThanHalfOrder(s) ? Fn.neg(s) : s;
713
+ }
714
+ function aValidRS(title, num) {
715
+ if (!Fn.isValidNot0(num))
716
+ throw new Error(`invalid signature ${title}: out of range 1..CURVE.n`);
750
717
  }
751
- // slice bytes num
752
- const slcNum = (b, from, to) => (0, utils_ts_1.bytesToNumberBE)(b.slice(from, to));
753
718
  /**
754
719
  * ECDSA signature with its (r, s) properties. Supports DER & compact representations.
755
720
  */
756
721
  class Signature {
757
722
  constructor(r, s, recovery) {
758
- (0, utils_ts_1.aInRange)('r', r, _1n, CURVE_ORDER); // r in [1..N]
759
- (0, utils_ts_1.aInRange)('s', s, _1n, CURVE_ORDER); // s in [1..N]
723
+ aValidRS('r', r); // r in [1..N-1]
724
+ aValidRS('s', s); // s in [1..N-1]
760
725
  this.r = r;
761
726
  this.s = s;
762
727
  if (recovery != null)
@@ -765,9 +730,9 @@ function weierstrass(curveDef) {
765
730
  }
766
731
  // pair (bytes of r, bytes of s)
767
732
  static fromCompact(hex) {
768
- const l = nByteLength;
769
- hex = (0, utils_ts_1.ensureBytes)('compactSignature', hex, l * 2);
770
- return new Signature(slcNum(hex, 0, l), slcNum(hex, l, 2 * l));
733
+ const L = Fn.BYTES;
734
+ const b = (0, utils_ts_1.ensureBytes)('compactSignature', hex, L * 2);
735
+ return new Signature(Fn.fromBytes(b.subarray(0, L)), Fn.fromBytes(b.subarray(L, L * 2)));
771
736
  }
772
737
  // DER encoded ECDSA signature
773
738
  // https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script
@@ -783,22 +748,36 @@ function weierstrass(curveDef) {
783
748
  addRecoveryBit(recovery) {
784
749
  return new Signature(this.r, this.s, recovery);
785
750
  }
751
+ // ProjPointType<bigint>
786
752
  recoverPublicKey(msgHash) {
753
+ const FIELD_ORDER = Fp.ORDER;
787
754
  const { r, s, recovery: rec } = this;
788
- const h = bits2int_modN((0, utils_ts_1.ensureBytes)('msgHash', msgHash)); // Truncate hash
789
755
  if (rec == null || ![0, 1, 2, 3].includes(rec))
790
756
  throw new Error('recovery id invalid');
791
- const radj = rec === 2 || rec === 3 ? r + CURVE.n : r;
792
- if (radj >= Fp.ORDER)
757
+ // ECDSA recovery is hard for cofactor > 1 curves.
758
+ // In sign, `r = q.x mod n`, and here we recover q.x from r.
759
+ // While recovering q.x >= n, we need to add r+n for cofactor=1 curves.
760
+ // However, for cofactor>1, r+n may not get q.x:
761
+ // r+n*i would need to be done instead where i is unknown.
762
+ // To easily get i, we either need to:
763
+ // a. increase amount of valid recid values (4, 5...); OR
764
+ // b. prohibit non-prime-order signatures (recid > 1).
765
+ const hasCofactor = CURVE_ORDER * _2n < FIELD_ORDER;
766
+ if (hasCofactor && rec > 1)
767
+ throw new Error('recovery id is ambiguous for h>1 curve');
768
+ const radj = rec === 2 || rec === 3 ? r + CURVE_ORDER : r;
769
+ if (!Fp.isValid(radj))
793
770
  throw new Error('recovery id 2 or 3 invalid');
794
- const prefix = (rec & 1) === 0 ? '02' : '03';
795
- const R = Point.fromHex(prefix + numToSizedHex(radj, Fp.BYTES));
796
- const ir = invN(radj); // r^-1
797
- const u1 = modN(-h * ir); // -hr^-1
798
- const u2 = modN(s * ir); // sr^-1
799
- const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2); // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1)
800
- if (!Q)
801
- throw new Error('point at infinify'); // unsafe is fine: no priv data leaked
771
+ const x = Fp.toBytes(radj);
772
+ const R = Point.fromHex((0, utils_ts_1.concatBytes)(pprefix((rec & 1) === 0), x));
773
+ const ir = Fn.inv(radj); // r^-1
774
+ const h = bits2int_modN((0, utils_ts_1.ensureBytes)('msgHash', msgHash)); // Truncate hash
775
+ const u1 = Fn.create(-h * ir); // -hr^-1
776
+ const u2 = Fn.create(s * ir); // sr^-1
777
+ // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1). unsafe is fine: there is no private data.
778
+ const Q = Point.BASE.multiplyUnsafe(u1).add(R.multiplyUnsafe(u2));
779
+ if (Q.is0())
780
+ throw new Error('point at infinify');
802
781
  Q.assertValidity();
803
782
  return Q;
804
783
  }
@@ -807,24 +786,31 @@ function weierstrass(curveDef) {
807
786
  return isBiggerThanHalfOrder(this.s);
808
787
  }
809
788
  normalizeS() {
810
- return this.hasHighS() ? new Signature(this.r, modN(-this.s), this.recovery) : this;
789
+ return this.hasHighS() ? new Signature(this.r, Fn.neg(this.s), this.recovery) : this;
790
+ }
791
+ toBytes(format) {
792
+ if (format === 'compact')
793
+ return (0, utils_ts_1.concatBytes)(Fn.toBytes(this.r), Fn.toBytes(this.s));
794
+ if (format === 'der')
795
+ return (0, utils_ts_1.hexToBytes)(exports.DER.hexFromSig(this));
796
+ throw new Error('invalid format');
811
797
  }
812
798
  // DER-encoded
813
799
  toDERRawBytes() {
814
- return (0, utils_ts_1.hexToBytes)(this.toDERHex());
800
+ return this.toBytes('der');
815
801
  }
816
802
  toDERHex() {
817
- return exports.DER.hexFromSig(this);
803
+ return (0, utils_ts_1.bytesToHex)(this.toBytes('der'));
818
804
  }
819
805
  // padded bytes of r, then padded bytes of s
820
806
  toCompactRawBytes() {
821
- return (0, utils_ts_1.hexToBytes)(this.toCompactHex());
807
+ return this.toBytes('compact');
822
808
  }
823
809
  toCompactHex() {
824
- const l = nByteLength;
825
- return numToSizedHex(this.r, l) + numToSizedHex(this.s, l);
810
+ return (0, utils_ts_1.bytesToHex)(this.toBytes('compact'));
826
811
  }
827
812
  }
813
+ const normPrivateKeyToScalar = _legacyHelperNormPriv(Fn, curveOpts.allowedPrivateKeyLengths, curveOpts.wrapPrivateKey);
828
814
  const utils = {
829
815
  isValidPrivateKey(privateKey) {
830
816
  try {
@@ -841,21 +827,11 @@ function weierstrass(curveDef) {
841
827
  * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible.
842
828
  */
843
829
  randomPrivateKey: () => {
844
- const length = (0, modular_ts_1.getMinHashLength)(CURVE.n);
845
- return (0, modular_ts_1.mapHashToField)(CURVE.randomBytes(length), CURVE.n);
830
+ const n = CURVE_ORDER;
831
+ return (0, modular_ts_1.mapHashToField)(randomBytes_((0, modular_ts_1.getMinHashLength)(n)), n);
846
832
  },
847
- /**
848
- * Creates precompute table for an arbitrary EC point. Makes point "cached".
849
- * Allows to massively speed-up `point.multiply(scalar)`.
850
- * @returns cached point
851
- * @example
852
- * const fast = utils.precompute(8, ProjectivePoint.fromHex(someonesPubKey));
853
- * fast.multiply(privKey); // much faster ECDH now
854
- */
855
833
  precompute(windowSize = 8, point = Point.BASE) {
856
- point._setWindowSize(windowSize);
857
- point.multiply(BigInt(3)); // 3 is arbitrary, just need any number here
858
- return point;
834
+ return point.precompute(windowSize, false);
859
835
  },
860
836
  };
861
837
  /**
@@ -865,7 +841,7 @@ function weierstrass(curveDef) {
865
841
  * @returns Public key, full when isCompressed=false; short when isCompressed=true
866
842
  */
867
843
  function getPublicKey(privateKey, isCompressed = true) {
868
- return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed);
844
+ return Point.fromPrivateKey(privateKey).toBytes(isCompressed);
869
845
  }
870
846
  /**
871
847
  * Quick and dirty check for item being public key. Does not validate hex, or being on-curve.
@@ -876,15 +852,15 @@ function weierstrass(curveDef) {
876
852
  if (item instanceof Point)
877
853
  return true;
878
854
  const arr = (0, utils_ts_1.ensureBytes)('key', item);
879
- const len = arr.length;
880
- const fpl = Fp.BYTES;
881
- const compLen = fpl + 1; // e.g. 33 for 32
882
- const uncompLen = 2 * fpl + 1; // e.g. 65 for 32
883
- if (CURVE.allowedPrivateKeyLengths || nByteLength === compLen) {
855
+ const length = arr.length;
856
+ const L = Fp.BYTES;
857
+ const LC = L + 1; // e.g. 33 for 32
858
+ const LU = 2 * L + 1; // e.g. 65 for 32
859
+ if (curveOpts.allowedPrivateKeyLengths || Fn.BYTES === LC) {
884
860
  return undefined;
885
861
  }
886
862
  else {
887
- return len === compLen || len === uncompLen;
863
+ return length === LC || length === LU;
888
864
  }
889
865
  }
890
866
  /**
@@ -903,13 +879,13 @@ function weierstrass(curveDef) {
903
879
  if (isProbPub(publicB) === false)
904
880
  throw new Error('second arg must be public key');
905
881
  const b = Point.fromHex(publicB); // check for being on-curve
906
- return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed);
882
+ return b.multiply(normPrivateKeyToScalar(privateA)).toBytes(isCompressed);
907
883
  }
908
884
  // RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets.
909
885
  // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int.
910
886
  // bits2int can produce res>N, we can do mod(res, N) since the bitLen is the same.
911
887
  // int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors
912
- const bits2int = CURVE.bits2int ||
888
+ const bits2int = ecdsaOpts.bits2int ||
913
889
  function (bytes) {
914
890
  // Our custom check "just in case", for protection against DoS
915
891
  if (bytes.length > 8192)
@@ -917,22 +893,22 @@ function weierstrass(curveDef) {
917
893
  // For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m)
918
894
  // for some cases, since bytes.length * 8 is not actual bitLength.
919
895
  const num = (0, utils_ts_1.bytesToNumberBE)(bytes); // check for == u8 done here
920
- const delta = bytes.length * 8 - nBitLength; // truncate to nBitLength leftmost bits
896
+ const delta = bytes.length * 8 - fnBits; // truncate to nBitLength leftmost bits
921
897
  return delta > 0 ? num >> BigInt(delta) : num;
922
898
  };
923
- const bits2int_modN = CURVE.bits2int_modN ||
899
+ const bits2int_modN = ecdsaOpts.bits2int_modN ||
924
900
  function (bytes) {
925
- return modN(bits2int(bytes)); // can't use bytesToNumberBE here
901
+ return Fn.create(bits2int(bytes)); // can't use bytesToNumberBE here
926
902
  };
927
903
  // NOTE: pads output with zero as per spec
928
- const ORDER_MASK = (0, utils_ts_1.bitMask)(nBitLength);
904
+ const ORDER_MASK = (0, utils_ts_1.bitMask)(fnBits);
929
905
  /**
930
906
  * Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`.
931
907
  */
932
908
  function int2octets(num) {
933
- (0, utils_ts_1.aInRange)('num < 2^' + nBitLength, num, _0n, ORDER_MASK);
934
- // works with order, can have different size than numToField!
935
- return (0, utils_ts_1.numberToBytesBE)(num, nByteLength);
909
+ // IMPORTANT: the check ensures working for case `Fn.BYTES != Fn.BITS * 8`
910
+ (0, utils_ts_1.aInRange)('num < 2^' + fnBits, num, _0n, ORDER_MASK);
911
+ return Fn.toBytes(num);
936
912
  }
937
913
  // Steps A, D of RFC6979 3.2
938
914
  // Creates RFC6979 seed; converts msg/privKey to numbers.
@@ -942,7 +918,7 @@ function weierstrass(curveDef) {
942
918
  function prepSig(msgHash, privateKey, opts = defaultSigOpts) {
943
919
  if (['recovered', 'canonical'].some((k) => k in opts))
944
920
  throw new Error('sign() legacy options not supported');
945
- const { hash, randomBytes } = CURVE;
921
+ const { hash } = ecdsaOpts;
946
922
  let { lowS, prehash, extraEntropy: ent } = opts; // generates low-s sigs by default
947
923
  if (lowS == null)
948
924
  lowS = true; // RFC6979 3.2: we skip step A, because we already provide hash
@@ -951,7 +927,7 @@ function weierstrass(curveDef) {
951
927
  if (prehash)
952
928
  msgHash = (0, utils_ts_1.ensureBytes)('prehashed msgHash', hash(msgHash));
953
929
  // We can't later call bits2octets, since nested bits2int is broken for curves
954
- // with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call.
930
+ // with fnBits % 8 !== 0. Because of that, we unwrap it here as int2octets call.
955
931
  // const bits2octets = (bits) => int2octets(bits2int_modN(bits))
956
932
  const h1int = bits2int_modN(msgHash);
957
933
  const d = normPrivateKeyToScalar(privateKey); // validate private key, convert to bigint
@@ -959,26 +935,27 @@ function weierstrass(curveDef) {
959
935
  // extraEntropy. RFC6979 3.6: additional k' (optional).
960
936
  if (ent != null && ent !== false) {
961
937
  // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
962
- const e = ent === true ? randomBytes(Fp.BYTES) : ent; // generate random bytes OR pass as-is
938
+ const e = ent === true ? randomBytes_(Fp.BYTES) : ent; // generate random bytes OR pass as-is
963
939
  seedArgs.push((0, utils_ts_1.ensureBytes)('extraEntropy', e)); // check for being bytes
964
940
  }
965
941
  const seed = (0, utils_ts_1.concatBytes)(...seedArgs); // Step D of RFC6979 3.2
966
942
  const m = h1int; // NOTE: no need to call bits2int second time here, it is inside truncateHash!
967
943
  // Converts signature params into point w r/s, checks result for validity.
944
+ // Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q−1] according to
945
+ // https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it:
946
+ // a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT
968
947
  function k2sig(kBytes) {
969
948
  // RFC 6979 Section 3.2, step 3: k = bits2int(T)
949
+ // Important: all mod() calls here must be done over N
970
950
  const k = bits2int(kBytes); // Cannot use fields methods, since it is group element
971
- if (!isWithinCurveOrder(k))
972
- return; // Important: all mod() calls here must be done over N
973
- const ik = invN(k); // k^-1 mod n
951
+ if (!Fn.isValidNot0(k))
952
+ return; // Valid scalars (including k) must be in 1..N-1
953
+ const ik = Fn.inv(k); // k^-1 mod n
974
954
  const q = Point.BASE.multiply(k).toAffine(); // q = Gk
975
- const r = modN(q.x); // r = q.x mod n
955
+ const r = Fn.create(q.x); // r = q.x mod n
976
956
  if (r === _0n)
977
957
  return;
978
- // Can use scalar blinding b^-1(bm + bdr) where b [1,q−1] according to
979
- // https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it:
980
- // a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT
981
- const s = modN(ik * modN(m + r * d)); // Not using blinding here
958
+ const s = Fn.create(ik * Fn.create(m + r * d)); // Not using blinding here, see comment above
982
959
  if (s === _0n)
983
960
  return;
984
961
  let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n); // recovery bit (2 or 3, when q.x > n)
@@ -991,8 +968,8 @@ function weierstrass(curveDef) {
991
968
  }
992
969
  return { seed, k2sig };
993
970
  }
994
- const defaultSigOpts = { lowS: CURVE.lowS, prehash: false };
995
- const defaultVerOpts = { lowS: CURVE.lowS, prehash: false };
971
+ const defaultSigOpts = { lowS: ecdsaOpts.lowS, prehash: false };
972
+ const defaultVerOpts = { lowS: ecdsaOpts.lowS, prehash: false };
996
973
  /**
997
974
  * Signs message hash with a private key.
998
975
  * ```
@@ -1008,13 +985,11 @@ function weierstrass(curveDef) {
1008
985
  */
1009
986
  function sign(msgHash, privKey, opts = defaultSigOpts) {
1010
987
  const { seed, k2sig } = prepSig(msgHash, privKey, opts); // Steps A, D of RFC6979 3.2.
1011
- const C = CURVE;
1012
- const drbg = (0, utils_ts_1.createHmacDrbg)(C.hash.outputLen, C.nByteLength, C.hmac);
988
+ const drbg = (0, utils_ts_1.createHmacDrbg)(ecdsaOpts.hash.outputLen, Fn.BYTES, hmac_);
1013
989
  return drbg(seed, k2sig); // Steps B, C, D, E, F, G
1014
990
  }
1015
991
  // Enable precomputes. Slows down first publicKey computation by 20ms.
1016
- Point.BASE._setWindowSize(8);
1017
- // utils.precompute(8, ProjectivePoint.BASE)
992
+ Point.BASE.precompute(8);
1018
993
  /**
1019
994
  * Verifies a signature against message hash and public key.
1020
995
  * Rejects lowS signatures by default: to override,
@@ -1032,13 +1007,14 @@ function weierstrass(curveDef) {
1032
1007
  const sg = signature;
1033
1008
  msgHash = (0, utils_ts_1.ensureBytes)('msgHash', msgHash);
1034
1009
  publicKey = (0, utils_ts_1.ensureBytes)('publicKey', publicKey);
1035
- const { lowS, prehash, format } = opts;
1036
- // Verify opts, deduce signature format
1010
+ // Verify opts
1037
1011
  validateSigVerOpts(opts);
1012
+ const { lowS, prehash, format } = opts;
1013
+ // TODO: remove
1038
1014
  if ('strict' in opts)
1039
1015
  throw new Error('options.strict was renamed to lowS');
1040
- if (format !== undefined && format !== 'compact' && format !== 'der')
1041
- throw new Error('format must be compact or der');
1016
+ if (format !== undefined && !['compact', 'der', 'js'].includes(format))
1017
+ throw new Error('format must be "compact", "der" or "js"');
1042
1018
  const isHex = typeof sg === 'string' || (0, utils_ts_1.isBytes)(sg);
1043
1019
  const isObj = !isHex &&
1044
1020
  !format &&
@@ -1050,12 +1026,29 @@ function weierstrass(curveDef) {
1050
1026
  throw new Error('invalid signature, expected Uint8Array, hex string or Signature instance');
1051
1027
  let _sig = undefined;
1052
1028
  let P;
1029
+ // deduce signature format
1053
1030
  try {
1054
- if (isObj)
1055
- _sig = new Signature(sg.r, sg.s);
1031
+ // if (format === 'js') {
1032
+ // if (sg != null && !isBytes(sg)) _sig = new Signature(sg.r, sg.s);
1033
+ // } else if (format === 'compact') {
1034
+ // _sig = Signature.fromCompact(sg);
1035
+ // } else if (format === 'der') {
1036
+ // _sig = Signature.fromDER(sg);
1037
+ // } else {
1038
+ // throw new Error('invalid format');
1039
+ // }
1040
+ if (isObj) {
1041
+ if (format === undefined || format === 'js') {
1042
+ _sig = new Signature(sg.r, sg.s);
1043
+ }
1044
+ else {
1045
+ throw new Error('invalid format');
1046
+ }
1047
+ }
1056
1048
  if (isHex) {
1057
- // Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length).
1058
- // Since DER can also be 2*nByteLength bytes, we check for it first.
1049
+ // TODO: remove this malleable check
1050
+ // Signature can be represented in 2 ways: compact (2*Fn.BYTES) & DER (variable-length).
1051
+ // Since DER can also be 2*Fn.BYTES bytes, we check for it first.
1059
1052
  try {
1060
1053
  if (format !== 'compact')
1061
1054
  _sig = Signature.fromDER(sg);
@@ -1076,29 +1069,99 @@ function weierstrass(curveDef) {
1076
1069
  return false;
1077
1070
  if (lowS && _sig.hasHighS())
1078
1071
  return false;
1072
+ // todo: optional.hash => hash
1079
1073
  if (prehash)
1080
- msgHash = CURVE.hash(msgHash);
1074
+ msgHash = ecdsaOpts.hash(msgHash);
1081
1075
  const { r, s } = _sig;
1082
1076
  const h = bits2int_modN(msgHash); // Cannot use fields methods, since it is group element
1083
- const is = invN(s); // s^-1
1084
- const u1 = modN(h * is); // u1 = hs^-1 mod n
1085
- const u2 = modN(r * is); // u2 = rs^-1 mod n
1086
- const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2)?.toAffine(); // R = u1⋅G + u2⋅P
1087
- if (!R)
1077
+ const is = Fn.inv(s); // s^-1
1078
+ const u1 = Fn.create(h * is); // u1 = hs^-1 mod n
1079
+ const u2 = Fn.create(r * is); // u2 = rs^-1 mod n
1080
+ const R = Point.BASE.multiplyUnsafe(u1).add(P.multiplyUnsafe(u2));
1081
+ if (R.is0())
1088
1082
  return false;
1089
- const v = modN(R.x);
1083
+ const v = Fn.create(R.x); // v = r.x mod n
1090
1084
  return v === r;
1091
1085
  }
1092
- return {
1093
- CURVE,
1086
+ // TODO: clarify API for cloning .clone({hash: sha512}) ? .createWith({hash: sha512})?
1087
+ // const clone = (hash: CHash): ECDSA => ecdsa(Point, { ...ecdsaOpts, ...getHash(hash) }, curveOpts);
1088
+ return Object.freeze({
1094
1089
  getPublicKey,
1095
1090
  getSharedSecret,
1096
1091
  sign,
1097
1092
  verify,
1098
- ProjectivePoint: Point,
1099
- Signature,
1100
1093
  utils,
1094
+ Point,
1095
+ Signature,
1096
+ });
1097
+ }
1098
+ function _weierstrass_legacy_opts_to_new(c) {
1099
+ const CURVE = {
1100
+ a: c.a,
1101
+ b: c.b,
1102
+ p: c.Fp.ORDER,
1103
+ n: c.n,
1104
+ h: c.h,
1105
+ Gx: c.Gx,
1106
+ Gy: c.Gy,
1107
+ };
1108
+ const Fp = c.Fp;
1109
+ const Fn = (0, modular_ts_1.Field)(CURVE.n, c.nBitLength);
1110
+ const curveOpts = {
1111
+ Fp,
1112
+ Fn,
1113
+ allowedPrivateKeyLengths: c.allowedPrivateKeyLengths,
1114
+ allowInfinityPoint: c.allowInfinityPoint,
1115
+ endo: c.endo,
1116
+ wrapPrivateKey: c.wrapPrivateKey,
1117
+ isTorsionFree: c.isTorsionFree,
1118
+ clearCofactor: c.clearCofactor,
1119
+ fromBytes: c.fromBytes,
1120
+ toBytes: c.toBytes,
1121
+ };
1122
+ return { CURVE, curveOpts };
1123
+ }
1124
+ function _ecdsa_legacy_opts_to_new(c) {
1125
+ const { CURVE, curveOpts } = _weierstrass_legacy_opts_to_new(c);
1126
+ const ecdsaOpts = {
1127
+ hash: c.hash,
1128
+ hmac: c.hmac,
1129
+ randomBytes: c.randomBytes,
1130
+ lowS: c.lowS,
1131
+ bits2int: c.bits2int,
1132
+ bits2int_modN: c.bits2int_modN,
1101
1133
  };
1134
+ return { CURVE, curveOpts, ecdsaOpts };
1135
+ }
1136
+ function _weierstrass_new_output_to_legacy(c, Point) {
1137
+ const { Fp, Fn } = Point;
1138
+ // TODO: remove
1139
+ function isWithinCurveOrder(num) {
1140
+ return (0, utils_ts_1.inRange)(num, _1n, Fn.ORDER);
1141
+ }
1142
+ const weierstrassEquation = _legacyHelperEquat(Fp, c.a, c.b);
1143
+ const normPrivateKeyToScalar = _legacyHelperNormPriv(Fn, c.allowedPrivateKeyLengths, c.wrapPrivateKey);
1144
+ return Object.assign({}, {
1145
+ CURVE: c,
1146
+ Point: Point,
1147
+ ProjectivePoint: Point,
1148
+ normPrivateKeyToScalar,
1149
+ weierstrassEquation,
1150
+ isWithinCurveOrder,
1151
+ });
1152
+ }
1153
+ function _ecdsa_new_output_to_legacy(c, ecdsa) {
1154
+ return Object.assign({}, ecdsa, {
1155
+ ProjectivePoint: ecdsa.Point,
1156
+ CURVE: c,
1157
+ });
1158
+ }
1159
+ // _ecdsa_legacy
1160
+ function weierstrass(c) {
1161
+ const { CURVE, curveOpts, ecdsaOpts } = _ecdsa_legacy_opts_to_new(c);
1162
+ const Point = weierstrassN(CURVE, curveOpts);
1163
+ const signs = ecdsa(Point, ecdsaOpts, curveOpts);
1164
+ return _ecdsa_new_output_to_legacy(c, signs);
1102
1165
  }
1103
1166
  /**
1104
1167
  * Implementation of the Shallue and van de Woestijne method for any weierstrass curve.
@@ -1184,31 +1247,32 @@ function SWUFpSqrtRatio(Fp, Z) {
1184
1247
  */
1185
1248
  function mapToCurveSimpleSWU(Fp, opts) {
1186
1249
  (0, modular_ts_1.validateField)(Fp);
1187
- if (!Fp.isValid(opts.A) || !Fp.isValid(opts.B) || !Fp.isValid(opts.Z))
1250
+ const { A, B, Z } = opts;
1251
+ if (!Fp.isValid(A) || !Fp.isValid(B) || !Fp.isValid(Z))
1188
1252
  throw new Error('mapToCurveSimpleSWU: invalid opts');
1189
- const sqrtRatio = SWUFpSqrtRatio(Fp, opts.Z);
1253
+ const sqrtRatio = SWUFpSqrtRatio(Fp, Z);
1190
1254
  if (!Fp.isOdd)
1191
- throw new Error('Fp.isOdd is not implemented!');
1255
+ throw new Error('Field does not have .isOdd()');
1192
1256
  // Input: u, an element of F.
1193
1257
  // Output: (x, y), a point on E.
1194
1258
  return (u) => {
1195
1259
  // prettier-ignore
1196
1260
  let tv1, tv2, tv3, tv4, tv5, tv6, x, y;
1197
1261
  tv1 = Fp.sqr(u); // 1. tv1 = u^2
1198
- tv1 = Fp.mul(tv1, opts.Z); // 2. tv1 = Z * tv1
1262
+ tv1 = Fp.mul(tv1, Z); // 2. tv1 = Z * tv1
1199
1263
  tv2 = Fp.sqr(tv1); // 3. tv2 = tv1^2
1200
1264
  tv2 = Fp.add(tv2, tv1); // 4. tv2 = tv2 + tv1
1201
1265
  tv3 = Fp.add(tv2, Fp.ONE); // 5. tv3 = tv2 + 1
1202
- tv3 = Fp.mul(tv3, opts.B); // 6. tv3 = B * tv3
1203
- tv4 = Fp.cmov(opts.Z, Fp.neg(tv2), !Fp.eql(tv2, Fp.ZERO)); // 7. tv4 = CMOV(Z, -tv2, tv2 != 0)
1204
- tv4 = Fp.mul(tv4, opts.A); // 8. tv4 = A * tv4
1266
+ tv3 = Fp.mul(tv3, B); // 6. tv3 = B * tv3
1267
+ tv4 = Fp.cmov(Z, Fp.neg(tv2), !Fp.eql(tv2, Fp.ZERO)); // 7. tv4 = CMOV(Z, -tv2, tv2 != 0)
1268
+ tv4 = Fp.mul(tv4, A); // 8. tv4 = A * tv4
1205
1269
  tv2 = Fp.sqr(tv3); // 9. tv2 = tv3^2
1206
1270
  tv6 = Fp.sqr(tv4); // 10. tv6 = tv4^2
1207
- tv5 = Fp.mul(tv6, opts.A); // 11. tv5 = A * tv6
1271
+ tv5 = Fp.mul(tv6, A); // 11. tv5 = A * tv6
1208
1272
  tv2 = Fp.add(tv2, tv5); // 12. tv2 = tv2 + tv5
1209
1273
  tv2 = Fp.mul(tv2, tv3); // 13. tv2 = tv2 * tv3
1210
1274
  tv6 = Fp.mul(tv6, tv4); // 14. tv6 = tv6 * tv4
1211
- tv5 = Fp.mul(tv6, opts.B); // 15. tv5 = B * tv6
1275
+ tv5 = Fp.mul(tv6, B); // 15. tv5 = B * tv6
1212
1276
  tv2 = Fp.add(tv2, tv5); // 16. tv2 = tv2 + tv5
1213
1277
  x = Fp.mul(tv1, tv3); // 17. x = tv1 * tv3
1214
1278
  const { isValid, value } = sqrtRatio(tv2, tv6); // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6)