@noble/curves 0.5.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +49 -8
  2. package/lib/_shortw_utils.d.ts +11 -26
  3. package/lib/abstract/bls.d.ts +51 -35
  4. package/lib/abstract/bls.js +77 -139
  5. package/lib/abstract/{group.d.ts → curve.d.ts} +31 -1
  6. package/lib/abstract/{group.js → curve.js} +39 -2
  7. package/lib/abstract/edwards.d.ts +30 -81
  8. package/lib/abstract/edwards.js +225 -420
  9. package/lib/abstract/hash-to-curve.d.ts +25 -6
  10. package/lib/abstract/hash-to-curve.js +40 -12
  11. package/lib/abstract/modular.d.ts +20 -7
  12. package/lib/abstract/modular.js +80 -51
  13. package/lib/abstract/montgomery.js +3 -4
  14. package/lib/abstract/poseidon.d.ts +29 -0
  15. package/lib/abstract/poseidon.js +115 -0
  16. package/lib/abstract/utils.d.ts +5 -34
  17. package/lib/abstract/utils.js +23 -63
  18. package/lib/abstract/weierstrass.d.ts +56 -79
  19. package/lib/abstract/weierstrass.js +509 -641
  20. package/lib/bls12-381.d.ts +1 -0
  21. package/lib/bls12-381.js +75 -65
  22. package/lib/bn.js +1 -1
  23. package/lib/ed25519.d.ts +7 -5
  24. package/lib/ed25519.js +87 -84
  25. package/lib/ed448.d.ts +3 -0
  26. package/lib/ed448.js +88 -84
  27. package/lib/esm/abstract/bls.js +77 -139
  28. package/lib/esm/abstract/{group.js → curve.js} +37 -1
  29. package/lib/esm/abstract/edwards.js +223 -418
  30. package/lib/esm/abstract/hash-to-curve.js +38 -11
  31. package/lib/esm/abstract/modular.js +77 -50
  32. package/lib/esm/abstract/montgomery.js +4 -7
  33. package/lib/esm/abstract/poseidon.js +109 -0
  34. package/lib/esm/abstract/utils.js +21 -59
  35. package/lib/esm/abstract/weierstrass.js +508 -640
  36. package/lib/esm/bls12-381.js +86 -76
  37. package/lib/esm/bn.js +1 -1
  38. package/lib/esm/ed25519.js +85 -83
  39. package/lib/esm/ed448.js +86 -83
  40. package/lib/esm/jubjub.js +6 -5
  41. package/lib/esm/p256.js +11 -9
  42. package/lib/esm/p384.js +11 -9
  43. package/lib/esm/p521.js +13 -12
  44. package/lib/esm/secp256k1.js +118 -157
  45. package/lib/esm/stark.js +104 -39
  46. package/lib/jubjub.d.ts +3 -2
  47. package/lib/jubjub.js +6 -5
  48. package/lib/p192.d.ts +22 -52
  49. package/lib/p224.d.ts +22 -52
  50. package/lib/p256.d.ts +25 -52
  51. package/lib/p256.js +13 -10
  52. package/lib/p384.d.ts +25 -52
  53. package/lib/p384.js +13 -10
  54. package/lib/p521.d.ts +25 -52
  55. package/lib/p521.js +15 -13
  56. package/lib/secp256k1.d.ts +26 -42
  57. package/lib/secp256k1.js +118 -157
  58. package/lib/stark.d.ts +36 -21
  59. package/lib/stark.js +107 -39
  60. package/package.json +14 -9
@@ -1,27 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.bls = void 0;
4
- /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
5
- // Barreto-Lynn-Scott Curves. A family of pairing friendly curves, with embedding degree = 12 or 24
6
- // NOTE: only 12 supported for now
7
- // Constructed from pair of weierstrass curves, based pairing logic
8
- const mod = require("./modular.js");
4
+ const modular_js_1 = require("./modular.js");
9
5
  const utils_js_1 = require("./utils.js");
10
- // Types
11
- const utils_js_2 = require("./utils.js");
12
- const hash_to_curve_js_1 = require("./hash-to-curve.js");
6
+ const htf = require("./hash-to-curve.js");
13
7
  const weierstrass_js_1 = require("./weierstrass.js");
14
8
  function bls(CURVE) {
15
9
  // Fields looks pretty specific for curve, so for now we need to pass them with options
16
- const Fp = CURVE.Fp;
17
- const Fr = CURVE.Fr;
18
- const Fp2 = CURVE.Fp2;
19
- const Fp6 = CURVE.Fp6;
20
- const Fp12 = CURVE.Fp12;
10
+ const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE;
21
11
  const BLS_X_LEN = (0, utils_js_1.bitLen)(CURVE.x);
12
+ const groupLen = 32; // TODO: calculate; hardcoded for now
22
13
  // Pre-compute coefficients for sparse multiplication
23
14
  // Point addition and point double calculations is reused for coefficients
24
- function calcPairingPrecomputes(x, y) {
15
+ function calcPairingPrecomputes(p) {
16
+ const { x, y } = p;
25
17
  // prettier-ignore
26
18
  const Qx = x, Qy = y, Qz = Fp2.ONE;
27
19
  // prettier-ignore
@@ -29,18 +21,18 @@ function bls(CURVE) {
29
21
  let ell_coeff = [];
30
22
  for (let i = BLS_X_LEN - 2; i >= 0; i--) {
31
23
  // Double
32
- let t0 = Fp2.square(Ry); // Ry²
33
- let t1 = Fp2.square(Rz); // Rz²
24
+ let t0 = Fp2.sqr(Ry); // Ry²
25
+ let t1 = Fp2.sqr(Rz); // Rz²
34
26
  let t2 = Fp2.multiplyByB(Fp2.mul(t1, 3n)); // 3 * T1 * B
35
27
  let t3 = Fp2.mul(t2, 3n); // 3 * T2
36
- let t4 = Fp2.sub(Fp2.sub(Fp2.square(Fp2.add(Ry, Rz)), t1), t0); // (Ry + Rz)² - T1 - T0
28
+ let t4 = Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(Ry, Rz)), t1), t0); // (Ry + Rz)² - T1 - T0
37
29
  ell_coeff.push([
38
30
  Fp2.sub(t2, t0),
39
- Fp2.mul(Fp2.square(Rx), 3n),
40
- Fp2.negate(t4), // -T4
31
+ Fp2.mul(Fp2.sqr(Rx), 3n),
32
+ Fp2.neg(t4), // -T4
41
33
  ]);
42
34
  Rx = Fp2.div(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), 2n); // ((T0 - T3) * Rx * Ry) / 2
43
- Ry = Fp2.sub(Fp2.square(Fp2.div(Fp2.add(t0, t3), 2n)), Fp2.mul(Fp2.square(t2), 3n)); // ((T0 + T3) / 2)² - 3 * T2²
35
+ Ry = Fp2.sub(Fp2.sqr(Fp2.div(Fp2.add(t0, t3), 2n)), Fp2.mul(Fp2.sqr(t2), 3n)); // ((T0 + T3) / 2)² - 3 * T2²
44
36
  Rz = Fp2.mul(t0, t4); // T0 * T4
45
37
  if ((0, utils_js_1.bitGet)(CURVE.x, i)) {
46
38
  // Addition
@@ -48,13 +40,13 @@ function bls(CURVE) {
48
40
  let t1 = Fp2.sub(Rx, Fp2.mul(Qx, Rz)); // Rx - Qx * Rz
49
41
  ell_coeff.push([
50
42
  Fp2.sub(Fp2.mul(t0, Qx), Fp2.mul(t1, Qy)),
51
- Fp2.negate(t0),
43
+ Fp2.neg(t0),
52
44
  t1, // T1
53
45
  ]);
54
- let t2 = Fp2.square(t1); // T1²
46
+ let t2 = Fp2.sqr(t1); // T1²
55
47
  let t3 = Fp2.mul(t2, t1); // T2 * T1
56
48
  let t4 = Fp2.mul(t2, Rx); // T2 * Rx
57
- let t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, 2n)), Fp2.mul(Fp2.square(t0), Rz)); // T3 - 2 * T4 + T0² * Rz
49
+ let t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, 2n)), Fp2.mul(Fp2.sqr(t0), Rz)); // T3 - 2 * T4 + T0² * Rz
58
50
  Rx = Fp2.mul(t1, t5); // T1 * T5
59
51
  Ry = Fp2.sub(Fp2.mul(Fp2.sub(t4, t5), t0), Fp2.mul(t3, Ry)); // (T4 - T5) * T0 - T3 * Ry
60
52
  Rz = Fp2.mul(Rz, t3); // Rz * T3
@@ -63,175 +55,121 @@ function bls(CURVE) {
63
55
  return ell_coeff;
64
56
  }
65
57
  function millerLoop(ell, g1) {
58
+ const { x } = CURVE;
66
59
  const Px = g1[0];
67
60
  const Py = g1[1];
68
61
  let f12 = Fp12.ONE;
69
62
  for (let j = 0, i = BLS_X_LEN - 2; i >= 0; i--, j++) {
70
63
  const E = ell[j];
71
64
  f12 = Fp12.multiplyBy014(f12, E[0], Fp2.mul(E[1], Px), Fp2.mul(E[2], Py));
72
- if ((0, utils_js_1.bitGet)(CURVE.x, i)) {
65
+ if ((0, utils_js_1.bitGet)(x, i)) {
73
66
  j += 1;
74
67
  const F = ell[j];
75
68
  f12 = Fp12.multiplyBy014(f12, F[0], Fp2.mul(F[1], Px), Fp2.mul(F[2], Py));
76
69
  }
77
70
  if (i !== 0)
78
- f12 = Fp12.square(f12);
71
+ f12 = Fp12.sqr(f12);
79
72
  }
80
73
  return Fp12.conjugate(f12);
81
74
  }
82
- // bls12-381 is a construction of two curves:
83
- // 1. Fp: (x, y)
84
- // 2. Fp₂: ((x₁, x₂+i), (y₁, y₂+i)) - (complex numbers)
85
- //
86
- // Bilinear Pairing (ate pairing) is used to combine both elements into a paired one:
87
- // Fp₁₂ = e(Fp, Fp2)
88
- // where Fp₁₂ = 12-degree polynomial
89
- // Pairing is used to verify signatures.
90
- //
91
- // We are using Fp for private keys (shorter) and Fp2 for signatures (longer).
92
- // Some projects may prefer to swap this relation, it is not supported for now.
93
- const htfDefaults = { ...CURVE.htfDefaults };
94
- function isWithinCurveOrder(num) {
95
- return 0 < num && num < CURVE.r;
96
- }
97
75
  const utils = {
98
- hexToBytes: utils_js_2.hexToBytes,
99
- bytesToHex: utils_js_2.bytesToHex,
100
- mod: mod.mod,
101
- stringToBytes: hash_to_curve_js_1.stringToBytes,
76
+ hexToBytes: utils_js_1.hexToBytes,
77
+ bytesToHex: utils_js_1.bytesToHex,
78
+ stringToBytes: htf.stringToBytes,
102
79
  // TODO: do we need to export it here?
103
- hashToField: (msg, count, options = {}) => (0, hash_to_curve_js_1.hash_to_field)(msg, count, { ...CURVE.htfDefaults, ...options }),
104
- expandMessageXMD: (msg, DST, lenInBytes, H = CURVE.hash) => (0, hash_to_curve_js_1.expand_message_xmd)(msg, DST, lenInBytes, H),
105
- /**
106
- * Can take 40 or more bytes of uniform input e.g. from CSPRNG or KDF
107
- * and convert them into private key, with the modulo bias being negligible.
108
- * As per FIPS 186 B.1.1.
109
- * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
110
- * @param hash hash output from sha512, or a similar function
111
- * @returns valid private key
112
- */
113
- hashToPrivateKey: (hash) => {
114
- hash = (0, utils_js_1.ensureBytes)(hash);
115
- if (hash.length < 40 || hash.length > 1024)
116
- throw new Error('Expected 40-1024 bytes of private key as per FIPS 186');
117
- // hashToPrivateScalar(hash, CURVE.r)
118
- // NOTE: doesn't add +/-1
119
- const num = mod.mod((0, utils_js_1.bytesToNumberBE)(hash), CURVE.r);
120
- // This should never happen
121
- if (num === 0n || num === 1n)
122
- throw new Error('Invalid private key');
123
- return (0, utils_js_1.numberToBytesBE)(num, 32);
124
- },
125
- randomBytes: (bytesLength = 32) => CURVE.randomBytes(bytesLength),
126
- // NIST SP 800-56A rev 3, section 5.6.1.2.2
127
- // https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
128
- randomPrivateKey: () => utils.hashToPrivateKey(utils.randomBytes(40)),
129
- getDSTLabel: () => htfDefaults.DST,
130
- setDSTLabel(newLabel) {
131
- // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3.1
132
- if (typeof newLabel !== 'string' || newLabel.length > 2048 || newLabel.length === 0) {
133
- throw new TypeError('Invalid DST');
134
- }
135
- htfDefaults.DST = newLabel;
136
- },
80
+ hashToField: (msg, count, options = {}) => htf.hash_to_field(msg, count, { ...CURVE.htfDefaults, ...options }),
81
+ expandMessageXMD: (msg, DST, lenInBytes, H = CURVE.hash) => htf.expand_message_xmd(msg, DST, lenInBytes, H),
82
+ hashToPrivateKey: (hash) => Fr.toBytes((0, modular_js_1.hashToPrivateScalar)(hash, CURVE.r)),
83
+ randomBytes: (bytesLength = groupLen) => CURVE.randomBytes(bytesLength),
84
+ randomPrivateKey: () => utils.hashToPrivateKey(utils.randomBytes(groupLen + 8)),
137
85
  };
138
- function normalizePrivKey(key) {
139
- let int;
140
- if (key instanceof Uint8Array && key.length === 32)
141
- int = (0, utils_js_1.bytesToNumberBE)(key);
142
- else if (typeof key === 'string' && key.length === 64)
143
- int = BigInt(`0x${key}`);
144
- else if (typeof key === 'number' && key > 0 && Number.isSafeInteger(key))
145
- int = BigInt(key);
146
- else if (typeof key === 'bigint' && key > 0n)
147
- int = key;
148
- else
149
- throw new TypeError('Expected valid private key');
150
- int = mod.mod(int, CURVE.r);
151
- if (!isWithinCurveOrder(int))
152
- throw new Error('Private key must be 0 < key < CURVE.r');
153
- return int;
154
- }
155
86
  // Point on G1 curve: (x, y)
156
87
  const G1 = (0, weierstrass_js_1.weierstrassPoints)({
157
88
  n: Fr.ORDER,
158
89
  ...CURVE.G1,
159
90
  });
91
+ const G1HashToCurve = htf.hashToCurve(G1.ProjectivePoint, CURVE.G1.mapToCurve, {
92
+ ...CURVE.htfDefaults,
93
+ ...CURVE.G1.htfDefaults,
94
+ });
160
95
  function pairingPrecomputes(point) {
161
96
  const p = point;
162
97
  if (p._PPRECOMPUTES)
163
98
  return p._PPRECOMPUTES;
164
- p._PPRECOMPUTES = calcPairingPrecomputes(p.x, p.y);
99
+ p._PPRECOMPUTES = calcPairingPrecomputes(point.toAffine());
165
100
  return p._PPRECOMPUTES;
166
101
  }
167
- function clearPairingPrecomputes(point) {
168
- const p = point;
169
- p._PPRECOMPUTES = undefined;
170
- }
171
- clearPairingPrecomputes;
172
- function millerLoopG1(Q, P) {
173
- return millerLoop(pairingPrecomputes(P), [Q.x, Q.y]);
174
- }
102
+ // TODO: export
103
+ // function clearPairingPrecomputes(point: G2) {
104
+ // const p = point as G2 & withPairingPrecomputes;
105
+ // p._PPRECOMPUTES = undefined;
106
+ // }
175
107
  // Point on G2 curve (complex numbers): (x₁, x₂+i), (y₁, y₂+i)
176
108
  const G2 = (0, weierstrass_js_1.weierstrassPoints)({
177
109
  n: Fr.ORDER,
178
110
  ...CURVE.G2,
179
111
  });
112
+ const C = G2.ProjectivePoint; // TODO: fix
113
+ const G2HashToCurve = htf.hashToCurve(C, CURVE.G2.mapToCurve, {
114
+ ...CURVE.htfDefaults,
115
+ ...CURVE.G2.htfDefaults,
116
+ });
180
117
  const { Signature } = CURVE.G2;
181
118
  // Calculates bilinear pairing
182
- function pairing(P, Q, withFinalExponent = true) {
183
- if (P.equals(G1.Point.ZERO) || Q.equals(G2.Point.ZERO))
184
- throw new Error('No pairings at point of Infinity');
185
- P.assertValidity();
119
+ function pairing(Q, P, withFinalExponent = true) {
120
+ if (Q.equals(G1.ProjectivePoint.ZERO) || P.equals(G2.ProjectivePoint.ZERO))
121
+ throw new Error('pairing is not available for ZERO point');
186
122
  Q.assertValidity();
123
+ P.assertValidity();
187
124
  // Performance: 9ms for millerLoop and ~14ms for exp.
188
- const looped = millerLoopG1(P, Q);
125
+ const Qa = Q.toAffine();
126
+ const looped = millerLoop(pairingPrecomputes(P), [Qa.x, Qa.y]);
189
127
  return withFinalExponent ? Fp12.finalExponentiate(looped) : looped;
190
128
  }
191
129
  function normP1(point) {
192
- return point instanceof G1.Point ? point : G1.Point.fromHex(point);
130
+ return point instanceof G1.ProjectivePoint ? point : G1.ProjectivePoint.fromHex(point);
193
131
  }
194
132
  function normP2(point) {
195
- return point instanceof G2.Point ? point : Signature.decode(point);
133
+ return point instanceof G2.ProjectivePoint ? point : Signature.decode(point);
196
134
  }
197
- function normP2Hash(point) {
198
- return point instanceof G2.Point ? point : G2.Point.hashToCurve(point);
135
+ function normP2Hash(point, htfOpts) {
136
+ return point instanceof G2.ProjectivePoint
137
+ ? point
138
+ : G2HashToCurve.hashToCurve(point, htfOpts);
199
139
  }
200
140
  // Multiplies generator by private key.
201
141
  // P = pk x G
202
142
  function getPublicKey(privateKey) {
203
- return G1.Point.fromPrivateKey(privateKey).toRawBytes(true);
143
+ return G1.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true);
204
144
  }
205
- function sign(message, privateKey) {
206
- const msgPoint = normP2Hash(message);
145
+ function sign(message, privateKey, htfOpts) {
146
+ const msgPoint = normP2Hash(message, htfOpts);
207
147
  msgPoint.assertValidity();
208
- const sigPoint = msgPoint.multiply(normalizePrivKey(privateKey));
209
- if (message instanceof G2.Point)
148
+ const sigPoint = msgPoint.multiply(G1.normalizePrivateKey(privateKey));
149
+ if (message instanceof G2.ProjectivePoint)
210
150
  return sigPoint;
211
151
  return Signature.encode(sigPoint);
212
152
  }
213
153
  // Checks if pairing of public key & hash is equal to pairing of generator & signature.
214
154
  // e(P, H(m)) == e(G, S)
215
- function verify(signature, message, publicKey) {
155
+ function verify(signature, message, publicKey, htfOpts) {
216
156
  const P = normP1(publicKey);
217
- const Hm = normP2Hash(message);
218
- const G = G1.Point.BASE;
157
+ const Hm = normP2Hash(message, htfOpts);
158
+ const G = G1.ProjectivePoint.BASE;
219
159
  const S = normP2(signature);
220
160
  // Instead of doing 2 exponentiations, we use property of billinear maps
221
161
  // and do one exp after multiplying 2 points.
222
162
  const ePHm = pairing(P.negate(), Hm, false);
223
163
  const eGS = pairing(G, S, false);
224
164
  const exp = Fp12.finalExponentiate(Fp12.mul(eGS, ePHm));
225
- return Fp12.equals(exp, Fp12.ONE);
165
+ return Fp12.eql(exp, Fp12.ONE);
226
166
  }
227
167
  function aggregatePublicKeys(publicKeys) {
228
168
  if (!publicKeys.length)
229
169
  throw new Error('Expected non-empty array');
230
- const agg = publicKeys
231
- .map(normP1)
232
- .reduce((sum, p) => sum.add(G1.ProjectivePoint.fromAffine(p)), G1.ProjectivePoint.ZERO);
233
- const aggAffine = agg.toAffine();
234
- if (publicKeys[0] instanceof G1.Point) {
170
+ const agg = publicKeys.map(normP1).reduce((sum, p) => sum.add(p), G1.ProjectivePoint.ZERO);
171
+ const aggAffine = agg; //.toAffine();
172
+ if (publicKeys[0] instanceof G1.ProjectivePoint) {
235
173
  aggAffine.assertValidity();
236
174
  return aggAffine;
237
175
  }
@@ -241,11 +179,9 @@ function bls(CURVE) {
241
179
  function aggregateSignatures(signatures) {
242
180
  if (!signatures.length)
243
181
  throw new Error('Expected non-empty array');
244
- const agg = signatures
245
- .map(normP2)
246
- .reduce((sum, s) => sum.add(G2.ProjectivePoint.fromAffine(s)), G2.ProjectivePoint.ZERO);
247
- const aggAffine = agg.toAffine();
248
- if (signatures[0] instanceof G2.Point) {
182
+ const agg = signatures.map(normP2).reduce((sum, s) => sum.add(s), G2.ProjectivePoint.ZERO);
183
+ const aggAffine = agg; //.toAffine();
184
+ if (signatures[0] instanceof G2.ProjectivePoint) {
249
185
  aggAffine.assertValidity();
250
186
  return aggAffine;
251
187
  }
@@ -253,33 +189,34 @@ function bls(CURVE) {
253
189
  }
254
190
  // https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407
255
191
  // e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))
256
- function verifyBatch(signature, messages, publicKeys) {
192
+ function verifyBatch(signature, messages, publicKeys, htfOpts) {
193
+ // @ts-ignore
194
+ // console.log('verifyBatch', bytesToHex(signature as any), messages, publicKeys.map(bytesToHex));
257
195
  if (!messages.length)
258
196
  throw new Error('Expected non-empty messages array');
259
197
  if (publicKeys.length !== messages.length)
260
198
  throw new Error('Pubkey count should equal msg count');
261
199
  const sig = normP2(signature);
262
- const nMessages = messages.map(normP2Hash);
200
+ const nMessages = messages.map((i) => normP2Hash(i, htfOpts));
263
201
  const nPublicKeys = publicKeys.map(normP1);
264
202
  try {
265
203
  const paired = [];
266
204
  for (const message of new Set(nMessages)) {
267
- const groupPublicKey = nMessages.reduce((groupPublicKey, subMessage, i) => subMessage === message ? groupPublicKey.add(nPublicKeys[i]) : groupPublicKey, G1.Point.ZERO);
205
+ const groupPublicKey = nMessages.reduce((groupPublicKey, subMessage, i) => subMessage === message ? groupPublicKey.add(nPublicKeys[i]) : groupPublicKey, G1.ProjectivePoint.ZERO);
268
206
  // const msg = message instanceof PointG2 ? message : await PointG2.hashToCurve(message);
269
207
  // Possible to batch pairing for same msg with different groupPublicKey here
270
208
  paired.push(pairing(groupPublicKey, message, false));
271
209
  }
272
- paired.push(pairing(G1.Point.BASE.negate(), sig, false));
210
+ paired.push(pairing(G1.ProjectivePoint.BASE.negate(), sig, false));
273
211
  const product = paired.reduce((a, b) => Fp12.mul(a, b), Fp12.ONE);
274
212
  const exp = Fp12.finalExponentiate(product);
275
- return Fp12.equals(exp, Fp12.ONE);
213
+ return Fp12.eql(exp, Fp12.ONE);
276
214
  }
277
215
  catch {
278
216
  return false;
279
217
  }
280
218
  }
281
- // Pre-compute points. Refer to README.
282
- G1.Point.BASE._setWindowSize(4);
219
+ G1.ProjectivePoint.BASE._setWindowSize(4);
283
220
  return {
284
221
  CURVE,
285
222
  Fr,
@@ -292,6 +229,7 @@ function bls(CURVE) {
292
229
  Signature,
293
230
  millerLoop,
294
231
  calcPairingPrecomputes,
232
+ hashToCurve: { G1: G1HashToCurve, G2: G2HashToCurve },
295
233
  pairing,
296
234
  getPublicKey,
297
235
  sign,
@@ -1,15 +1,25 @@
1
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2
+ import { Field } from './modular.js';
3
+ export declare type AffinePoint<T> = {
4
+ x: T;
5
+ y: T;
6
+ } & {
7
+ z?: never;
8
+ t?: never;
9
+ };
1
10
  export interface Group<T extends Group<T>> {
2
11
  double(): T;
3
12
  negate(): T;
4
13
  add(other: T): T;
5
14
  subtract(other: T): T;
6
15
  equals(other: T): boolean;
7
- multiply(scalar: number | bigint): T;
16
+ multiply(scalar: bigint): T;
8
17
  }
9
18
  export declare type GroupConstructor<T> = {
10
19
  BASE: T;
11
20
  ZERO: T;
12
21
  };
22
+ export declare type Mapper<T> = (i: T[]) => T[];
13
23
  export declare function wNAF<T extends Group<T>>(c: GroupConstructor<T>, bits: number): {
14
24
  constTimeNegate: (condition: boolean, item: T) => T;
15
25
  unsafeLadder(elm: T, n: bigint): T;
@@ -31,4 +41,24 @@ export declare function wNAF<T extends Group<T>>(c: GroupConstructor<T>, bits: n
31
41
  p: T;
32
42
  f: T;
33
43
  };
44
+ wNAFCached(P: T, precomputesMap: Map<T, T[]>, n: bigint, transform: Mapper<T>): {
45
+ p: T;
46
+ f: T;
47
+ };
48
+ };
49
+ export declare type AbstractCurve<T> = {
50
+ Fp: Field<T>;
51
+ n: bigint;
52
+ nBitLength?: number;
53
+ nByteLength?: number;
54
+ h: bigint;
55
+ hEff?: bigint;
56
+ Gx: T;
57
+ Gy: T;
58
+ wrapPrivateKey?: boolean;
59
+ allowInfinityPoint?: boolean;
34
60
  };
61
+ export declare function validateAbsOpts<FP, T>(curve: AbstractCurve<FP> & T): Readonly<{
62
+ readonly nBitLength: number;
63
+ readonly nByteLength: number;
64
+ } & AbstractCurve<FP> & T>;
@@ -1,11 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.wNAF = void 0;
3
+ exports.validateAbsOpts = exports.wNAF = void 0;
4
4
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
5
5
  // Abelian group utilities
6
+ const modular_js_1 = require("./modular.js");
6
7
  const _0n = BigInt(0);
7
8
  const _1n = BigInt(1);
8
- // Not big, but pretty complex and it is easy to break stuff. To avoid too much copy paste
9
+ // Elliptic curve multiplication of Point by scalar. Complicated and fragile. Uses wNAF method.
10
+ // Windowed method is 10% faster, but takes 2x longer to generate & consumes 2x memory.
9
11
  function wNAF(c, bits) {
10
12
  const constTimeNegate = (condition, item) => {
11
13
  const neg = item.negate();
@@ -107,6 +109,41 @@ function wNAF(c, bits) {
107
109
  // which makes it less const-time: around 1 bigint multiply.
108
110
  return { p, f };
109
111
  },
112
+ wNAFCached(P, precomputesMap, n, transform) {
113
+ // @ts-ignore
114
+ const W = P._WINDOW_SIZE || 1;
115
+ // Calculate precomputes on a first run, reuse them after
116
+ let comp = precomputesMap.get(P);
117
+ if (!comp) {
118
+ comp = this.precomputeWindow(P, W);
119
+ if (W !== 1) {
120
+ precomputesMap.set(P, transform(comp));
121
+ }
122
+ }
123
+ return this.wNAF(W, comp, n);
124
+ },
110
125
  };
111
126
  }
112
127
  exports.wNAF = wNAF;
128
+ function validateAbsOpts(curve) {
129
+ (0, modular_js_1.validateField)(curve.Fp);
130
+ for (const i of ['n', 'h']) {
131
+ const val = curve[i];
132
+ if (typeof val !== 'bigint')
133
+ throw new Error(`Invalid curve param ${i}=${val} (${typeof val})`);
134
+ }
135
+ if (!curve.Fp.isValid(curve.Gx))
136
+ throw new Error('Invalid generator X coordinate Fp element');
137
+ if (!curve.Fp.isValid(curve.Gy))
138
+ throw new Error('Invalid generator Y coordinate Fp element');
139
+ for (const i of ['nBitLength', 'nByteLength']) {
140
+ const val = curve[i];
141
+ if (val === undefined)
142
+ continue; // Optional
143
+ if (!Number.isSafeInteger(val))
144
+ throw new Error(`Invalid param ${i}=${val} (${typeof val})`);
145
+ }
146
+ // Set defaults
147
+ return Object.freeze({ ...(0, modular_js_1.nLength)(curve.n, curve.nBitLength), ...curve });
148
+ }
149
+ exports.validateAbsOpts = validateAbsOpts;
@@ -1,18 +1,9 @@
1
- /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2
- import * as mod from './modular.js';
3
- import { BasicCurve, Hex, PrivKey } from './utils.js';
4
- import { Group, GroupConstructor } from './group.js';
5
- import { htfOpts } from './hash-to-curve.js';
6
- export declare type CHash = {
7
- (message: Uint8Array | string): Uint8Array;
8
- blockLen: number;
9
- outputLen: number;
10
- create(): any;
11
- };
12
- export declare type CurveType = BasicCurve<bigint> & {
1
+ import { FHash, Hex } from './utils.js';
2
+ import { Group, GroupConstructor, AbstractCurve, AffinePoint } from './curve.js';
3
+ export declare type CurveType = AbstractCurve<bigint> & {
13
4
  a: bigint;
14
5
  d: bigint;
15
- hash: CHash;
6
+ hash: FHash;
16
7
  randomBytes: (bytesLength?: number) => Uint8Array;
17
8
  adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array;
18
9
  domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array;
@@ -20,18 +11,13 @@ export declare type CurveType = BasicCurve<bigint> & {
20
11
  isValid: boolean;
21
12
  value: bigint;
22
13
  };
23
- preHash?: CHash;
24
- clearCofactor?: (c: ExtendedPointConstructor, point: ExtendedPointType) => ExtendedPointType;
25
- htfDefaults?: htfOpts;
26
- mapToCurve?: (scalar: bigint[]) => {
27
- x: bigint;
28
- y: bigint;
29
- };
14
+ preHash?: FHash;
15
+ mapToCurve?: (scalar: bigint[]) => AffinePoint<bigint>;
30
16
  };
31
17
  declare function validateOpts(curve: CurveType): Readonly<{
32
18
  readonly nBitLength: number;
33
19
  readonly nByteLength: number;
34
- readonly Fp: mod.Field<bigint>;
20
+ readonly Fp: import("./modular.js").Field<bigint>;
35
21
  readonly n: bigint;
36
22
  readonly h: bigint;
37
23
  readonly hEff?: bigint | undefined;
@@ -41,7 +27,7 @@ declare function validateOpts(curve: CurveType): Readonly<{
41
27
  readonly allowInfinityPoint?: boolean | undefined;
42
28
  readonly a: bigint;
43
29
  readonly d: bigint;
44
- readonly hash: CHash;
30
+ readonly hash: FHash;
45
31
  readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
46
32
  readonly adjustScalarBytes?: ((bytes: Uint8Array) => Uint8Array) | undefined;
47
33
  readonly domain?: ((data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array) | undefined;
@@ -49,78 +35,41 @@ declare function validateOpts(curve: CurveType): Readonly<{
49
35
  isValid: boolean;
50
36
  value: bigint;
51
37
  }) | undefined;
52
- readonly preHash?: CHash | undefined;
53
- readonly clearCofactor?: ((c: ExtendedPointConstructor, point: ExtendedPointType) => ExtendedPointType) | undefined;
54
- readonly htfDefaults?: htfOpts | undefined;
55
- readonly mapToCurve?: ((scalar: bigint[]) => {
56
- x: bigint;
57
- y: bigint;
58
- }) | undefined;
38
+ readonly preHash?: FHash | undefined;
39
+ readonly mapToCurve?: ((scalar: bigint[]) => AffinePoint<bigint>) | undefined;
59
40
  }>;
60
- export interface SignatureType {
61
- readonly r: PointType;
62
- readonly s: bigint;
63
- assertValidity(): SignatureType;
64
- toRawBytes(): Uint8Array;
65
- toHex(): string;
66
- }
67
- export declare type SignatureConstructor = {
68
- new (r: PointType, s: bigint): SignatureType;
69
- fromHex(hex: Hex): SignatureType;
70
- };
71
- export interface ExtendedPointType extends Group<ExtendedPointType> {
72
- readonly x: bigint;
73
- readonly y: bigint;
74
- readonly z: bigint;
75
- readonly t: bigint;
76
- multiply(scalar: number | bigint, affinePoint?: PointType): ExtendedPointType;
77
- multiplyUnsafe(scalar: number | bigint): ExtendedPointType;
41
+ export interface ExtPointType extends Group<ExtPointType> {
42
+ readonly ex: bigint;
43
+ readonly ey: bigint;
44
+ readonly ez: bigint;
45
+ readonly et: bigint;
46
+ assertValidity(): void;
47
+ multiply(scalar: bigint): ExtPointType;
48
+ multiplyUnsafe(scalar: bigint): ExtPointType;
78
49
  isSmallOrder(): boolean;
79
50
  isTorsionFree(): boolean;
80
- toAffine(invZ?: bigint): PointType;
81
- clearCofactor(): ExtendedPointType;
82
- }
83
- export interface ExtendedPointConstructor extends GroupConstructor<ExtendedPointType> {
84
- new (x: bigint, y: bigint, z: bigint, t: bigint): ExtendedPointType;
85
- fromAffine(p: PointType): ExtendedPointType;
86
- toAffineBatch(points: ExtendedPointType[]): PointType[];
87
- normalizeZ(points: ExtendedPointType[]): ExtendedPointType[];
88
- }
89
- export interface PointType extends Group<PointType> {
90
- readonly x: bigint;
91
- readonly y: bigint;
92
- _setWindowSize(windowSize: number): void;
93
- toRawBytes(isCompressed?: boolean): Uint8Array;
94
- toHex(isCompressed?: boolean): string;
95
- isTorsionFree(): boolean;
96
- clearCofactor(): PointType;
51
+ clearCofactor(): ExtPointType;
52
+ toAffine(iz?: bigint): AffinePoint<bigint>;
97
53
  }
98
- export interface PointConstructor extends GroupConstructor<PointType> {
99
- new (x: bigint, y: bigint): PointType;
100
- fromHex(hex: Hex): PointType;
101
- fromPrivateKey(privateKey: PrivKey): PointType;
102
- hashToCurve(msg: Hex, options?: Partial<htfOpts>): PointType;
103
- encodeToCurve(msg: Hex, options?: Partial<htfOpts>): PointType;
54
+ export interface ExtPointConstructor extends GroupConstructor<ExtPointType> {
55
+ new (x: bigint, y: bigint, z: bigint, t: bigint): ExtPointType;
56
+ fromAffine(p: AffinePoint<bigint>): ExtPointType;
57
+ fromHex(hex: Hex): ExtPointType;
58
+ fromPrivateKey(privateKey: Hex): ExtPointType;
104
59
  }
105
- export declare type PubKey = Hex | PointType;
106
- export declare type SigType = Hex | SignatureType;
107
60
  export declare type CurveFn = {
108
61
  CURVE: ReturnType<typeof validateOpts>;
109
- getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array;
62
+ getPublicKey: (privateKey: Hex) => Uint8Array;
110
63
  sign: (message: Hex, privateKey: Hex) => Uint8Array;
111
- verify: (sig: SigType, message: Hex, publicKey: PubKey) => boolean;
112
- Point: PointConstructor;
113
- ExtendedPoint: ExtendedPointConstructor;
114
- Signature: SignatureConstructor;
64
+ verify: (sig: Hex, message: Hex, publicKey: Hex) => boolean;
65
+ ExtendedPoint: ExtPointConstructor;
115
66
  utils: {
116
- mod: (a: bigint) => bigint;
117
- invert: (number: bigint) => bigint;
118
67
  randomPrivateKey: () => Uint8Array;
119
- getExtendedPublicKey: (key: PrivKey) => {
68
+ getExtendedPublicKey: (key: Hex) => {
120
69
  head: Uint8Array;
121
70
  prefix: Uint8Array;
122
71
  scalar: bigint;
123
- point: PointType;
72
+ point: ExtPointType;
124
73
  pointBytes: Uint8Array;
125
74
  };
126
75
  };