@noble/curves 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/README.md +254 -162
  2. package/lib/_shortw_utils.d.ts +75 -0
  3. package/lib/_shortw_utils.js +20 -0
  4. package/lib/{bls.d.ts → abstract/bls.d.ts} +2 -1
  5. package/lib/{bls.js → abstract/bls.js} +28 -27
  6. package/lib/{edwards.d.ts → abstract/edwards.d.ts} +17 -0
  7. package/lib/{edwards.js → abstract/edwards.js} +45 -4
  8. package/lib/{group.d.ts → abstract/group.d.ts} +2 -1
  9. package/lib/{group.js → abstract/group.js} +4 -3
  10. package/lib/abstract/hash-to-curve.d.ts +28 -0
  11. package/lib/{hashToCurve.js → abstract/hash-to-curve.js} +46 -11
  12. package/lib/{modular.d.ts → abstract/modular.d.ts} +13 -16
  13. package/lib/abstract/modular.js +337 -0
  14. package/lib/{montgomery.d.ts → abstract/montgomery.d.ts} +2 -1
  15. package/lib/{montgomery.js → abstract/montgomery.js} +17 -8
  16. package/lib/{utils.d.ts → abstract/utils.d.ts} +4 -2
  17. package/lib/{utils.js → abstract/utils.js} +1 -1
  18. package/lib/{weierstrass.d.ts → abstract/weierstrass.d.ts} +28 -16
  19. package/lib/{weierstrass.js → abstract/weierstrass.js} +261 -127
  20. package/lib/bls12-381.d.ts +66 -0
  21. package/lib/bls12-381.js +1132 -0
  22. package/lib/bn.d.ts +7 -0
  23. package/lib/bn.js +24 -0
  24. package/lib/ed25519.d.ts +48 -0
  25. package/lib/ed25519.js +385 -0
  26. package/lib/ed448.d.ts +3 -0
  27. package/lib/ed448.js +211 -0
  28. package/lib/esm/_shortw_utils.js +15 -0
  29. package/lib/esm/{bls.js → abstract/bls.js} +25 -24
  30. package/lib/esm/{edwards.js → abstract/edwards.js} +45 -4
  31. package/lib/esm/{group.js → abstract/group.js} +4 -3
  32. package/lib/esm/{hashToCurve.js → abstract/hash-to-curve.js} +43 -10
  33. package/lib/esm/abstract/modular.js +319 -0
  34. package/lib/esm/{montgomery.js → abstract/montgomery.js} +17 -8
  35. package/lib/esm/{utils.js → abstract/utils.js} +1 -1
  36. package/lib/esm/{weierstrass.js → abstract/weierstrass.js} +255 -123
  37. package/lib/esm/bls12-381.js +1129 -0
  38. package/lib/esm/bn.js +21 -0
  39. package/lib/esm/ed25519.js +381 -0
  40. package/lib/esm/ed448.js +208 -0
  41. package/lib/esm/index.js +2 -0
  42. package/lib/esm/jubjub.js +52 -0
  43. package/lib/esm/p192.js +21 -0
  44. package/lib/esm/p224.js +21 -0
  45. package/lib/esm/p256.js +39 -0
  46. package/lib/esm/p384.js +44 -0
  47. package/lib/esm/p521.js +58 -0
  48. package/lib/esm/pasta.js +29 -0
  49. package/lib/esm/secp256k1.js +293 -0
  50. package/lib/esm/stark.js +224 -0
  51. package/lib/index.d.ts +0 -0
  52. package/lib/index.js +2 -0
  53. package/lib/jubjub.d.ts +7 -0
  54. package/lib/jubjub.js +57 -0
  55. package/lib/p192.d.ts +130 -0
  56. package/lib/p192.js +24 -0
  57. package/lib/p224.d.ts +130 -0
  58. package/lib/p224.js +24 -0
  59. package/lib/p256.d.ts +130 -0
  60. package/lib/p256.js +42 -0
  61. package/lib/p384.d.ts +130 -0
  62. package/lib/p384.js +47 -0
  63. package/lib/p521.d.ts +131 -0
  64. package/lib/p521.js +61 -0
  65. package/lib/pasta.d.ts +4 -0
  66. package/lib/pasta.js +32 -0
  67. package/lib/secp256k1.d.ts +96 -0
  68. package/lib/secp256k1.js +297 -0
  69. package/lib/stark.d.ts +72 -0
  70. package/lib/stark.js +245 -0
  71. package/package.json +146 -50
  72. package/index.js +0 -1
  73. package/lib/esm/modular.js +0 -252
  74. package/lib/hashToCurve.d.ts +0 -13
  75. package/lib/modular.js +0 -267
@@ -1,7 +1,8 @@
1
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
1
2
  import * as mod from './modular.js';
2
3
  import * as utils from './utils.js';
3
4
  import { Hex, PrivKey } from './utils.js';
4
- import { htfOpts, stringToBytes, hash_to_field, expand_message_xmd } from './hashToCurve.js';
5
+ import { htfOpts, stringToBytes, hash_to_field, expand_message_xmd } from './hash-to-curve.js';
5
6
  import { CurvePointsType, PointType, CurvePointsRes } from './weierstrass.js';
6
7
  declare type Fp = bigint;
7
8
  export declare type SignatureCoder<Fp2> = {
@@ -1,6 +1,7 @@
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) */
4
5
  // Barreto-Lynn-Scott Curves. A family of pairing friendly curves, with embedding degree = 12 or 24
5
6
  // NOTE: only 12 supported for now
6
7
  // Constructed from pair of weierstrass curves, based pairing logic
@@ -8,7 +9,7 @@ const mod = require("./modular.js");
8
9
  const utils_js_1 = require("./utils.js");
9
10
  // Types
10
11
  const utils_js_2 = require("./utils.js");
11
- const hashToCurve_js_1 = require("./hashToCurve.js");
12
+ const hash_to_curve_js_1 = require("./hash-to-curve.js");
12
13
  const weierstrass_js_1 = require("./weierstrass.js");
13
14
  function bls(CURVE) {
14
15
  // Fields looks pretty specific for curve, so for now we need to pass them with options
@@ -30,33 +31,33 @@ function bls(CURVE) {
30
31
  // Double
31
32
  let t0 = Fp2.square(Ry); // Ry²
32
33
  let t1 = Fp2.square(Rz); // Rz²
33
- let t2 = Fp2.multiplyByB(Fp2.multiply(t1, 3n)); // 3 * T1 * B
34
- let t3 = Fp2.multiply(t2, 3n); // 3 * T2
35
- let t4 = Fp2.subtract(Fp2.subtract(Fp2.square(Fp2.add(Ry, Rz)), t1), t0); // (Ry + Rz)² - T1 - T0
34
+ let t2 = Fp2.multiplyByB(Fp2.mul(t1, 3n)); // 3 * T1 * B
35
+ 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
36
37
  ell_coeff.push([
37
- Fp2.subtract(t2, t0),
38
- Fp2.multiply(Fp2.square(Rx), 3n),
38
+ Fp2.sub(t2, t0),
39
+ Fp2.mul(Fp2.square(Rx), 3n),
39
40
  Fp2.negate(t4), // -T4
40
41
  ]);
41
- Rx = Fp2.div(Fp2.multiply(Fp2.multiply(Fp2.subtract(t0, t3), Rx), Ry), 2n); // ((T0 - T3) * Rx * Ry) / 2
42
- Ry = Fp2.subtract(Fp2.square(Fp2.div(Fp2.add(t0, t3), 2n)), Fp2.multiply(Fp2.square(t2), 3n)); // ((T0 + T3) / 2)² - 3 * T2²
43
- Rz = Fp2.multiply(t0, t4); // T0 * T4
42
+ 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²
44
+ Rz = Fp2.mul(t0, t4); // T0 * T4
44
45
  if ((0, utils_js_1.bitGet)(CURVE.x, i)) {
45
46
  // Addition
46
- let t0 = Fp2.subtract(Ry, Fp2.multiply(Qy, Rz)); // Ry - Qy * Rz
47
- let t1 = Fp2.subtract(Rx, Fp2.multiply(Qx, Rz)); // Rx - Qx * Rz
47
+ let t0 = Fp2.sub(Ry, Fp2.mul(Qy, Rz)); // Ry - Qy * Rz
48
+ let t1 = Fp2.sub(Rx, Fp2.mul(Qx, Rz)); // Rx - Qx * Rz
48
49
  ell_coeff.push([
49
- Fp2.subtract(Fp2.multiply(t0, Qx), Fp2.multiply(t1, Qy)),
50
+ Fp2.sub(Fp2.mul(t0, Qx), Fp2.mul(t1, Qy)),
50
51
  Fp2.negate(t0),
51
52
  t1, // T1
52
53
  ]);
53
54
  let t2 = Fp2.square(t1); // T1²
54
- let t3 = Fp2.multiply(t2, t1); // T2 * T1
55
- let t4 = Fp2.multiply(t2, Rx); // T2 * Rx
56
- let t5 = Fp2.add(Fp2.subtract(t3, Fp2.multiply(t4, 2n)), Fp2.multiply(Fp2.square(t0), Rz)); // T3 - 2 * T4 + T0² * Rz
57
- Rx = Fp2.multiply(t1, t5); // T1 * T5
58
- Ry = Fp2.subtract(Fp2.multiply(Fp2.subtract(t4, t5), t0), Fp2.multiply(t3, Ry)); // (T4 - T5) * T0 - T3 * Ry
59
- Rz = Fp2.multiply(Rz, t3); // Rz * T3
55
+ let t3 = Fp2.mul(t2, t1); // T2 * T1
56
+ 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
58
+ Rx = Fp2.mul(t1, t5); // T1 * T5
59
+ Ry = Fp2.sub(Fp2.mul(Fp2.sub(t4, t5), t0), Fp2.mul(t3, Ry)); // (T4 - T5) * T0 - T3 * Ry
60
+ Rz = Fp2.mul(Rz, t3); // Rz * T3
60
61
  }
61
62
  }
62
63
  return ell_coeff;
@@ -67,11 +68,11 @@ function bls(CURVE) {
67
68
  let f12 = Fp12.ONE;
68
69
  for (let j = 0, i = BLS_X_LEN - 2; i >= 0; i--, j++) {
69
70
  const E = ell[j];
70
- f12 = Fp12.multiplyBy014(f12, E[0], Fp2.multiply(E[1], Px), Fp2.multiply(E[2], Py));
71
+ f12 = Fp12.multiplyBy014(f12, E[0], Fp2.mul(E[1], Px), Fp2.mul(E[2], Py));
71
72
  if ((0, utils_js_1.bitGet)(CURVE.x, i)) {
72
73
  j += 1;
73
74
  const F = ell[j];
74
- f12 = Fp12.multiplyBy014(f12, F[0], Fp2.multiply(F[1], Px), Fp2.multiply(F[2], Py));
75
+ f12 = Fp12.multiplyBy014(f12, F[0], Fp2.mul(F[1], Px), Fp2.mul(F[2], Py));
75
76
  }
76
77
  if (i !== 0)
77
78
  f12 = Fp12.square(f12);
@@ -97,10 +98,10 @@ function bls(CURVE) {
97
98
  hexToBytes: utils_js_2.hexToBytes,
98
99
  bytesToHex: utils_js_2.bytesToHex,
99
100
  mod: mod.mod,
100
- stringToBytes: hashToCurve_js_1.stringToBytes,
101
+ stringToBytes: hash_to_curve_js_1.stringToBytes,
101
102
  // TODO: do we need to export it here?
102
- hashToField: (msg, count, options = {}) => (0, hashToCurve_js_1.hash_to_field)(msg, count, { ...CURVE.htfDefaults, ...options }),
103
- expandMessageXMD: (msg, DST, lenInBytes, H = CURVE.hash) => (0, hashToCurve_js_1.expand_message_xmd)(msg, DST, lenInBytes, H),
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),
104
105
  /**
105
106
  * Can take 40 or more bytes of uniform input e.g. from CSPRNG or KDF
106
107
  * and convert them into private key, with the modulo bias being negligible.
@@ -220,7 +221,7 @@ function bls(CURVE) {
220
221
  // and do one exp after multiplying 2 points.
221
222
  const ePHm = pairing(P.negate(), Hm, false);
222
223
  const eGS = pairing(G, S, false);
223
- const exp = Fp12.finalExponentiate(Fp12.multiply(eGS, ePHm));
224
+ const exp = Fp12.finalExponentiate(Fp12.mul(eGS, ePHm));
224
225
  return Fp12.equals(exp, Fp12.ONE);
225
226
  }
226
227
  function aggregatePublicKeys(publicKeys) {
@@ -228,7 +229,7 @@ function bls(CURVE) {
228
229
  throw new Error('Expected non-empty array');
229
230
  const agg = publicKeys
230
231
  .map(normP1)
231
- .reduce((sum, p) => sum.add(G1.JacobianPoint.fromAffine(p)), G1.JacobianPoint.ZERO);
232
+ .reduce((sum, p) => sum.add(G1.ProjectivePoint.fromAffine(p)), G1.ProjectivePoint.ZERO);
232
233
  const aggAffine = agg.toAffine();
233
234
  if (publicKeys[0] instanceof G1.Point) {
234
235
  aggAffine.assertValidity();
@@ -242,7 +243,7 @@ function bls(CURVE) {
242
243
  throw new Error('Expected non-empty array');
243
244
  const agg = signatures
244
245
  .map(normP2)
245
- .reduce((sum, s) => sum.add(G2.JacobianPoint.fromAffine(s)), G2.JacobianPoint.ZERO);
246
+ .reduce((sum, s) => sum.add(G2.ProjectivePoint.fromAffine(s)), G2.ProjectivePoint.ZERO);
246
247
  const aggAffine = agg.toAffine();
247
248
  if (signatures[0] instanceof G2.Point) {
248
249
  aggAffine.assertValidity();
@@ -269,7 +270,7 @@ function bls(CURVE) {
269
270
  paired.push(pairing(groupPublicKey, message, false));
270
271
  }
271
272
  paired.push(pairing(G1.Point.BASE.negate(), sig, false));
272
- const product = paired.reduce((a, b) => Fp12.multiply(a, b), Fp12.ONE);
273
+ const product = paired.reduce((a, b) => Fp12.mul(a, b), Fp12.ONE);
273
274
  const exp = Fp12.finalExponentiate(product);
274
275
  return Fp12.equals(exp, Fp12.ONE);
275
276
  }
@@ -2,6 +2,7 @@
2
2
  import * as mod from './modular.js';
3
3
  import { BasicCurve, Hex, PrivKey } from './utils.js';
4
4
  import { Group, GroupConstructor } from './group.js';
5
+ import { htfOpts } from './hash-to-curve.js';
5
6
  export declare type CHash = {
6
7
  (message: Uint8Array | string): Uint8Array;
7
8
  blockLen: number;
@@ -20,6 +21,12 @@ export declare type CurveType = BasicCurve<bigint> & {
20
21
  value: bigint;
21
22
  };
22
23
  preHash?: CHash;
24
+ clearCofactor?: (c: ExtendedPointConstructor, point: ExtendedPointType) => ExtendedPointType;
25
+ htfDefaults?: htfOpts;
26
+ mapToCurve?: (scalar: bigint[]) => {
27
+ x: bigint;
28
+ y: bigint;
29
+ };
23
30
  };
24
31
  declare function validateOpts(curve: CurveType): Readonly<{
25
32
  readonly nBitLength: number;
@@ -43,6 +50,12 @@ declare function validateOpts(curve: CurveType): Readonly<{
43
50
  value: bigint;
44
51
  }) | undefined;
45
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;
46
59
  }>;
47
60
  export interface SignatureType {
48
61
  readonly r: PointType;
@@ -65,6 +78,7 @@ export interface ExtendedPointType extends Group<ExtendedPointType> {
65
78
  isSmallOrder(): boolean;
66
79
  isTorsionFree(): boolean;
67
80
  toAffine(invZ?: bigint): PointType;
81
+ clearCofactor(): ExtendedPointType;
68
82
  }
69
83
  export interface ExtendedPointConstructor extends GroupConstructor<ExtendedPointType> {
70
84
  new (x: bigint, y: bigint, z: bigint, t: bigint): ExtendedPointType;
@@ -79,11 +93,14 @@ export interface PointType extends Group<PointType> {
79
93
  toRawBytes(isCompressed?: boolean): Uint8Array;
80
94
  toHex(isCompressed?: boolean): string;
81
95
  isTorsionFree(): boolean;
96
+ clearCofactor(): PointType;
82
97
  }
83
98
  export interface PointConstructor extends GroupConstructor<PointType> {
84
99
  new (x: bigint, y: bigint): PointType;
85
100
  fromHex(hex: Hex): PointType;
86
101
  fromPrivateKey(privateKey: PrivKey): PointType;
102
+ hashToCurve(msg: Hex, options?: Partial<htfOpts>): PointType;
103
+ encodeToCurve(msg: Hex, options?: Partial<htfOpts>): PointType;
87
104
  }
88
105
  export declare type PubKey = Hex | PointType;
89
106
  export declare type SigType = Hex | SignatureType;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
3
- // Implementation of Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y²
3
+ // Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y²
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.twistedEdwards = void 0;
6
6
  // Differences from @noble/ed25519 1.7:
@@ -13,6 +13,7 @@ exports.twistedEdwards = void 0;
13
13
  const mod = require("./modular.js");
14
14
  const utils_js_1 = require("./utils.js"); // TODO: import * as u from './utils.js'?
15
15
  const group_js_1 = require("./group.js");
16
+ const hash_to_curve_js_1 = require("./hash-to-curve.js");
16
17
  // Be friendly to bad ECMAScript parsers by not using bigint literals like 123n
17
18
  const _0n = BigInt(0);
18
19
  const _1n = BigInt(1);
@@ -31,12 +32,20 @@ function validateOpts(curve) {
31
32
  if (typeof opts[fn] !== 'function')
32
33
  throw new Error(`Invalid ${fn} function`);
33
34
  }
34
- for (const fn of ['adjustScalarBytes', 'domain', 'uvRatio']) {
35
+ for (const fn of [
36
+ 'adjustScalarBytes',
37
+ 'domain',
38
+ 'uvRatio',
39
+ 'mapToCurve',
40
+ 'clearCofactor',
41
+ ]) {
35
42
  if (opts[fn] === undefined)
36
43
  continue; // Optional
37
44
  if (typeof opts[fn] !== 'function')
38
45
  throw new Error(`Invalid ${fn} function`);
39
46
  }
47
+ if (opts.htfDefaults !== undefined)
48
+ (0, hash_to_curve_js_1.validateHTFOpts)(opts.htfDefaults);
40
49
  // Set defaults
41
50
  return Object.freeze({ ...opts });
42
51
  }
@@ -156,7 +165,7 @@ function twistedEdwards(curveDef) {
156
165
  const B = modP((Y1 + X1) * (Y2 - X2));
157
166
  const F = modP(B - A);
158
167
  if (F === _0n)
159
- return this.double(); // Same point.
168
+ return this.double(); // Same point. Tests say it doesn't affect timing
160
169
  const C = modP(Z1 * _2n * T2);
161
170
  const D = modP(T1 * _2n * Z2);
162
171
  const E = D + C;
@@ -173,7 +182,6 @@ function twistedEdwards(curveDef) {
173
182
  const C = modP(T1 * d * T2); // C = T1*d*T2
174
183
  const D = modP(Z1 * Z2); // D = Z1*Z2
175
184
  const E = modP((X1 + Y1) * (X2 + Y2) - A - B); // E = (X1+Y1)*(X2+Y2)-A-B
176
- // TODO: do we need to check for same point here? Looks like working without it
177
185
  const F = D - C; // F = D-C
178
186
  const G = D + C; // G = D+C
179
187
  const H = modP(B - a * A); // H = B-a*A
@@ -247,6 +255,15 @@ function twistedEdwards(curveDef) {
247
255
  throw new Error('invZ was invalid');
248
256
  return new Point(ax, ay);
249
257
  }
258
+ clearCofactor() {
259
+ if (CURVE.h === _1n)
260
+ return this; // Fast-path
261
+ // clear_cofactor(P) := h_eff * P
262
+ // hEff = h for ed25519/ed448. Maybe worth moving to params?
263
+ if (CURVE.clearCofactor)
264
+ return CURVE.clearCofactor(ExtendedPoint, this);
265
+ return this.multiplyUnsafe(CURVE.h);
266
+ }
250
267
  }
251
268
  ExtendedPoint.BASE = new ExtendedPoint(CURVE.Gx, CURVE.Gy, _1n, modP(CURVE.Gx * CURVE.Gy));
252
269
  ExtendedPoint.ZERO = new ExtendedPoint(_0n, _1n, _1n, _0n);
@@ -355,6 +372,30 @@ function twistedEdwards(curveDef) {
355
372
  multiply(scalar) {
356
373
  return ExtendedPoint.fromAffine(this).multiply(scalar, this).toAffine();
357
374
  }
375
+ clearCofactor() {
376
+ return ExtendedPoint.fromAffine(this).clearCofactor().toAffine();
377
+ }
378
+ // Encodes byte string to elliptic curve
379
+ // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3
380
+ static hashToCurve(msg, options) {
381
+ if (!CURVE.mapToCurve)
382
+ throw new Error('No mapToCurve defined for curve');
383
+ msg = (0, utils_js_1.ensureBytes)(msg);
384
+ const u = (0, hash_to_curve_js_1.hash_to_field)(msg, 2, { ...CURVE.htfDefaults, ...options });
385
+ const { x: x0, y: y0 } = CURVE.mapToCurve(u[0]);
386
+ const { x: x1, y: y1 } = CURVE.mapToCurve(u[1]);
387
+ const p = new Point(x0, y0).add(new Point(x1, y1)).clearCofactor();
388
+ return p;
389
+ }
390
+ // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-3
391
+ static encodeToCurve(msg, options) {
392
+ if (!CURVE.mapToCurve)
393
+ throw new Error('No mapToCurve defined for curve');
394
+ msg = (0, utils_js_1.ensureBytes)(msg);
395
+ const u = (0, hash_to_curve_js_1.hash_to_field)(msg, 1, { ...CURVE.htfDefaults, ...options });
396
+ const { x, y } = CURVE.mapToCurve(u[0]);
397
+ return new Point(x, y).clearCofactor();
398
+ }
358
399
  }
359
400
  // Base point aka generator
360
401
  // public_key = Point.BASE * private_key
@@ -22,8 +22,9 @@ export declare function wNAF<T extends Group<T>>(c: GroupConstructor<T>, bits: n
22
22
  precomputeWindow(elm: T, W: number): Group<T>[];
23
23
  /**
24
24
  * Implements w-ary non-adjacent form for calculating ec multiplication.
25
- * @param n
25
+ * @param W window size
26
26
  * @param affinePoint optional 2d point to save cached precompute windows on it.
27
+ * @param n bits
27
28
  * @returns real and fake (for const-time) points
28
29
  */
29
30
  wNAF(W: number, precomputes: T[], n: bigint): {
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.wNAF = void 0;
4
- /*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
5
- // Default group related functions
4
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
5
+ // Abelian group utilities
6
6
  const _0n = BigInt(0);
7
7
  const _1n = BigInt(1);
8
8
  // Not big, but pretty complex and it is easy to break stuff. To avoid too much copy paste
@@ -55,8 +55,9 @@ function wNAF(c, bits) {
55
55
  },
56
56
  /**
57
57
  * Implements w-ary non-adjacent form for calculating ec multiplication.
58
- * @param n
58
+ * @param W window size
59
59
  * @param affinePoint optional 2d point to save cached precompute windows on it.
60
+ * @param n bits
60
61
  * @returns real and fake (for const-time) points
61
62
  */
62
63
  wNAF(W, precomputes, n) {
@@ -0,0 +1,28 @@
1
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2
+ import { CHash } from './utils.js';
3
+ import * as mod from './modular.js';
4
+ export declare type htfOpts = {
5
+ DST: string;
6
+ p: bigint;
7
+ m: number;
8
+ k: number;
9
+ expand?: 'xmd' | 'xof';
10
+ hash: CHash;
11
+ };
12
+ export declare function validateHTFOpts(opts: htfOpts): void;
13
+ export declare function stringToBytes(str: string): Uint8Array;
14
+ export declare function expand_message_xmd(msg: Uint8Array, DST: Uint8Array, lenInBytes: number, H: CHash): Uint8Array;
15
+ export declare function expand_message_xof(msg: Uint8Array, DST: Uint8Array, lenInBytes: number, k: number, H: CHash): Uint8Array;
16
+ /**
17
+ * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F
18
+ * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3
19
+ * @param msg a byte string containing the message to hash
20
+ * @param count the number of elements of F to output
21
+ * @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`
22
+ * @returns [u_0, ..., u_(count - 1)], a list of field elements.
23
+ */
24
+ export declare function hash_to_field(msg: Uint8Array, count: number, options: htfOpts): bigint[][];
25
+ export declare function isogenyMap<T, F extends mod.Field<T>>(field: F, map: [T[], T[], T[], T[]]): (x: T, y: T) => {
26
+ x: T;
27
+ y: T;
28
+ };
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.hash_to_field = exports.expand_message_xmd = exports.stringToBytes = exports.validateHTFOpts = void 0;
3
+ exports.isogenyMap = exports.hash_to_field = exports.expand_message_xof = exports.expand_message_xmd = exports.stringToBytes = exports.validateHTFOpts = void 0;
4
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
4
5
  const utils_js_1 = require("./utils.js");
5
6
  const mod = require("./modular.js");
6
7
  function validateHTFOpts(opts) {
@@ -12,13 +13,14 @@ function validateHTFOpts(opts) {
12
13
  throw new Error('Invalid htf/m');
13
14
  if (typeof opts.k !== 'number')
14
15
  throw new Error('Invalid htf/k');
15
- if (typeof opts.expand !== 'boolean')
16
+ if (opts.expand !== 'xmd' && opts.expand !== 'xof' && opts.expand !== undefined)
16
17
  throw new Error('Invalid htf/expand');
17
18
  if (typeof opts.hash !== 'function' || !Number.isSafeInteger(opts.hash.outputLen))
18
19
  throw new Error('Invalid htf/hash function');
19
20
  }
20
21
  exports.validateHTFOpts = validateHTFOpts;
21
22
  // UTF8 to ui8a
23
+ // TODO: looks broken, ASCII only, why not TextEncoder/TextDecoder? it is in hashes anyway
22
24
  function stringToBytes(str) {
23
25
  const bytes = new Uint8Array(str.length);
24
26
  for (let i = 0; i < str.length; i++)
@@ -61,7 +63,7 @@ function expand_message_xmd(msg, DST, lenInBytes, H) {
61
63
  if (DST.length > 255)
62
64
  DST = H((0, utils_js_1.concatBytes)(stringToBytes('H2C-OVERSIZE-DST-'), DST));
63
65
  const b_in_bytes = H.outputLen;
64
- const r_in_bytes = b_in_bytes * 2;
66
+ const r_in_bytes = H.blockLen;
65
67
  const ell = Math.ceil(lenInBytes / b_in_bytes);
66
68
  if (ell > 255)
67
69
  throw new Error('Invalid xmd length');
@@ -79,13 +81,32 @@ function expand_message_xmd(msg, DST, lenInBytes, H) {
79
81
  return pseudo_random_bytes.slice(0, lenInBytes);
80
82
  }
81
83
  exports.expand_message_xmd = expand_message_xmd;
82
- // hashes arbitrary-length byte strings to a list of one or more elements of a finite field F
83
- // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3
84
- // Inputs:
85
- // msg - a byte string containing the message to hash.
86
- // count - the number of elements of F to output.
87
- // Outputs:
88
- // [u_0, ..., u_(count - 1)], a list of field elements.
84
+ function expand_message_xof(msg, DST, lenInBytes, k, H) {
85
+ // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3
86
+ // DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8));
87
+ if (DST.length > 255) {
88
+ const dkLen = Math.ceil((2 * k) / 8);
89
+ DST = H.create({ dkLen }).update(stringToBytes('H2C-OVERSIZE-DST-')).update(DST).digest();
90
+ }
91
+ if (lenInBytes > 65535 || DST.length > 255)
92
+ throw new Error('expand_message_xof: invalid lenInBytes');
93
+ return (H.create({ dkLen: lenInBytes })
94
+ .update(msg)
95
+ .update(i2osp(lenInBytes, 2))
96
+ // 2. DST_prime = DST || I2OSP(len(DST), 1)
97
+ .update(DST)
98
+ .update(i2osp(DST.length, 1))
99
+ .digest());
100
+ }
101
+ exports.expand_message_xof = expand_message_xof;
102
+ /**
103
+ * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F
104
+ * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3
105
+ * @param msg a byte string containing the message to hash
106
+ * @param count the number of elements of F to output
107
+ * @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`
108
+ * @returns [u_0, ..., u_(count - 1)], a list of field elements.
109
+ */
89
110
  function hash_to_field(msg, count, options) {
90
111
  // if options is provided but incomplete, fill any missing fields with the
91
112
  // value in hftDefaults (ie hash to G2).
@@ -94,9 +115,12 @@ function hash_to_field(msg, count, options) {
94
115
  const len_in_bytes = count * options.m * L;
95
116
  const DST = stringToBytes(options.DST);
96
117
  let pseudo_random_bytes = msg;
97
- if (options.expand) {
118
+ if (options.expand === 'xmd') {
98
119
  pseudo_random_bytes = expand_message_xmd(msg, DST, len_in_bytes, options.hash);
99
120
  }
121
+ else if (options.expand === 'xof') {
122
+ pseudo_random_bytes = expand_message_xof(msg, DST, len_in_bytes, options.k, options.hash);
123
+ }
100
124
  const u = new Array(count);
101
125
  for (let i = 0; i < count; i++) {
102
126
  const e = new Array(options.m);
@@ -110,3 +134,14 @@ function hash_to_field(msg, count, options) {
110
134
  return u;
111
135
  }
112
136
  exports.hash_to_field = hash_to_field;
137
+ function isogenyMap(field, map) {
138
+ // Make same order as in spec
139
+ const COEFF = map.map((i) => Array.from(i).reverse());
140
+ return (x, y) => {
141
+ const [xNum, xDen, yNum, yDen] = COEFF.map((val) => val.reduce((acc, i) => field.add(field.mul(acc, x), i)));
142
+ x = field.div(xNum, xDen); // xNum / xDen
143
+ y = field.mul(y, field.div(yNum, yDen)); // y * (yNum / yDev)
144
+ return { x, y };
145
+ };
146
+ }
147
+ exports.isogenyMap = isogenyMap;
@@ -8,17 +8,8 @@ export declare function mod(a: bigint, b: bigint): bigint;
8
8
  export declare function pow(num: bigint, power: bigint, modulo: bigint): bigint;
9
9
  export declare function pow2(x: bigint, power: bigint, modulo: bigint): bigint;
10
10
  export declare function invert(number: bigint, modulo: bigint): bigint;
11
- /**
12
- * Calculates Legendre symbol (a | p), which denotes the value of a^((p-1)/2) (mod p).
13
- * * (a | p) ≡ 1 if a is a square (mod p)
14
- * * (a | p) ≡ -1 if a is not a square (mod p)
15
- * * (a | p) ≡ 0 if a ≡ 0 (mod p)
16
- */
17
- export declare function legendre(num: bigint, fieldPrime: bigint): bigint;
18
- /**
19
- * Calculates square root of a number in a finite field.
20
- */
21
- export declare function sqrt(number: bigint, modulo: bigint): bigint;
11
+ export declare function tonelliShanks(P: bigint): <T>(Fp: Field<T>, n: T) => T;
12
+ export declare function FpSqrt(P: bigint): <T>(Fp: Field<T>, n: T) => T;
22
13
  export declare const isNegativeLE: (num: bigint, modulo: bigint) => boolean;
23
14
  export interface Field<T> {
24
15
  ORDER: bigint;
@@ -36,13 +27,13 @@ export interface Field<T> {
36
27
  square(num: T): T;
37
28
  equals(lhs: T, rhs: T): boolean;
38
29
  add(lhs: T, rhs: T): T;
39
- subtract(lhs: T, rhs: T): T;
40
- multiply(lhs: T, rhs: T | bigint): T;
30
+ sub(lhs: T, rhs: T): T;
31
+ mul(lhs: T, rhs: T | bigint): T;
41
32
  pow(lhs: T, power: bigint): T;
42
33
  div(lhs: T, rhs: T | bigint): T;
43
34
  addN(lhs: T, rhs: T): T;
44
- subtractN(lhs: T, rhs: T): T;
45
- multiplyN(lhs: T, rhs: T | bigint): T;
35
+ subN(lhs: T, rhs: T): T;
36
+ mulN(lhs: T, rhs: T | bigint): T;
46
37
  squareN(num: T): T;
47
38
  isOdd?(num: T): boolean;
48
39
  legendre?(num: T): T;
@@ -50,9 +41,15 @@ export interface Field<T> {
50
41
  invertBatch: (lst: T[]) => T[];
51
42
  toBytes(num: T): Uint8Array;
52
43
  fromBytes(bytes: Uint8Array): T;
44
+ cmov(a: T, b: T, c: boolean): T;
53
45
  }
54
46
  export declare function validateField<T>(field: Field<T>): void;
55
47
  export declare function FpPow<T>(f: Field<T>, num: T, power: bigint): T;
56
48
  export declare function FpInvertBatch<T>(f: Field<T>, nums: T[]): T[];
57
49
  export declare function FpDiv<T>(f: Field<T>, lhs: T, rhs: T | bigint): T;
58
- export declare function Fp(ORDER: bigint, bitLen?: number, isLE?: boolean, redef?: Partial<Field<bigint>>): Readonly<Field<bigint>>;
50
+ export declare function FpIsSquare<T>(f: Field<T>): (x: T) => boolean;
51
+ declare type FpField = Field<bigint> & Required<Pick<Field<bigint>, 'isOdd'>>;
52
+ export declare function Fp(ORDER: bigint, bitLen?: number, isLE?: boolean, redef?: Partial<Field<bigint>>): Readonly<FpField>;
53
+ export declare function FpSqrtOdd<T>(Fp: Field<T>, elm: T): T;
54
+ export declare function FpSqrtEven<T>(Fp: Field<T>, elm: T): T;
55
+ export {};