@noble/curves 0.5.0 → 0.5.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 (50) hide show
  1. package/README.md +62 -14
  2. package/lib/_shortw_utils.d.ts +2 -6
  3. package/lib/abstract/bls.d.ts +17 -8
  4. package/lib/abstract/bls.js +15 -78
  5. package/lib/abstract/edwards.d.ts +7 -16
  6. package/lib/abstract/edwards.js +89 -106
  7. package/lib/abstract/hash-to-curve.d.ts +10 -1
  8. package/lib/abstract/hash-to-curve.js +32 -10
  9. package/lib/abstract/modular.d.ts +8 -17
  10. package/lib/abstract/modular.js +134 -152
  11. package/lib/abstract/montgomery.js +1 -1
  12. package/lib/abstract/utils.d.ts +8 -4
  13. package/lib/abstract/utils.js +22 -14
  14. package/lib/abstract/weierstrass.d.ts +8 -8
  15. package/lib/abstract/weierstrass.js +209 -168
  16. package/lib/bls12-381.d.ts +2 -1
  17. package/lib/bls12-381.js +14 -9
  18. package/lib/ed25519.js +75 -12
  19. package/lib/ed448.js +86 -2
  20. package/lib/esm/abstract/bls.js +19 -82
  21. package/lib/esm/abstract/edwards.js +90 -107
  22. package/lib/esm/abstract/hash-to-curve.js +30 -9
  23. package/lib/esm/abstract/modular.js +128 -148
  24. package/lib/esm/abstract/montgomery.js +2 -4
  25. package/lib/esm/abstract/utils.js +20 -13
  26. package/lib/esm/abstract/weierstrass.js +210 -169
  27. package/lib/esm/bls12-381.js +13 -8
  28. package/lib/esm/ed25519.js +76 -13
  29. package/lib/esm/ed448.js +87 -3
  30. package/lib/esm/jubjub.js +5 -4
  31. package/lib/esm/p256.js +1 -1
  32. package/lib/esm/p384.js +1 -1
  33. package/lib/esm/p521.js +1 -1
  34. package/lib/esm/secp256k1.js +27 -27
  35. package/lib/esm/stark.js +5 -2
  36. package/lib/jubjub.d.ts +1 -0
  37. package/lib/jubjub.js +5 -4
  38. package/lib/p192.d.ts +4 -12
  39. package/lib/p224.d.ts +4 -12
  40. package/lib/p256.d.ts +4 -12
  41. package/lib/p256.js +1 -1
  42. package/lib/p384.d.ts +4 -12
  43. package/lib/p384.js +1 -1
  44. package/lib/p521.d.ts +4 -12
  45. package/lib/p521.js +1 -1
  46. package/lib/secp256k1.d.ts +2 -6
  47. package/lib/secp256k1.js +27 -27
  48. package/lib/stark.d.ts +1 -3
  49. package/lib/stark.js +5 -2
  50. package/package.json +2 -2
@@ -1,6 +1,7 @@
1
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
1
2
  import { CurveFn } from './abstract/bls.js';
2
3
  import * as mod from './abstract/modular.js';
3
- declare const Fp: Readonly<mod.Field<bigint>>;
4
+ declare const Fp: Readonly<mod.Field<bigint> & Required<Pick<mod.Field<bigint>, "isOdd">>>;
4
5
  declare type Fp = bigint;
5
6
  declare type BigintTuple = [bigint, bigint];
6
7
  declare type Fp2 = {
package/lib/bls12-381.js CHANGED
@@ -1,7 +1,17 @@
1
1
  "use strict";
2
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.bls12_381 = void 0;
4
- /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
5
+ // The pairing-friendly Barreto-Lynn-Scott elliptic curve construction allows to:
6
+ // - Construct zk-SNARKs at the 128-bit security
7
+ // - Use threshold signatures, which allows a user to sign lots of messages with one signature and verify them swiftly in a batch, using Boneh-Lynn-Shacham signature scheme.
8
+ // Differences from @noble/bls12-381 1.4:
9
+ // - PointG1 -> G1.Point
10
+ // - PointG2 -> G2.Point
11
+ // - PointG2.fromSignature -> Signature.decode
12
+ // - PointG2.toSignature -> Signature.encode
13
+ // - Fixed Fp2 ORDER
14
+ // - Points now have only two coordinates
5
15
  const sha256_1 = require("@noble/hashes/sha256");
6
16
  const utils_1 = require("@noble/hashes/utils");
7
17
  const bls_js_1 = require("./abstract/bls.js");
@@ -10,13 +20,6 @@ const utils_js_1 = require("./abstract/utils.js");
10
20
  // Types
11
21
  const weierstrass_js_1 = require("./abstract/weierstrass.js");
12
22
  const hash_to_curve_js_1 = require("./abstract/hash-to-curve.js");
13
- // Differences from bls12-381:
14
- // - PointG1 -> G1.Point
15
- // - PointG2 -> G2.Point
16
- // - PointG2.fromSignature -> Signature.decode
17
- // - PointG2.toSignature -> Signature.encode
18
- // - Fixed Fp2 ORDER
19
- // Points now have only two coordinates
20
23
  // CURVE FIELDS
21
24
  // Finite field over p.
22
25
  const Fp = mod.Fp(0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn);
@@ -100,6 +103,8 @@ const Fp2 = {
100
103
  return { c0: Fp.mul(factor, Fp.create(a)), c1: Fp.mul(factor, Fp.create(-b)) };
101
104
  },
102
105
  sqrt: (num) => {
106
+ if (Fp2.equals(num, Fp2.ZERO))
107
+ return Fp2.ZERO; // Algo doesn't handles this case
103
108
  // TODO: Optimize this line. It's extremely slow.
104
109
  // Speeding this up would boost aggregateSignatures.
105
110
  // https://eprint.iacr.org/2012/685.pdf applicable?
@@ -818,7 +823,7 @@ const htfDefaults = {
818
823
  k: 128,
819
824
  // option to use a message that has already been processed by
820
825
  // expand_message_xmd
821
- expand: true,
826
+ expand: 'xmd',
822
827
  // Hash functions for: expand_message_xmd is appropriate for use with a
823
828
  // wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others.
824
829
  // BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247
package/lib/ed25519.js CHANGED
@@ -81,7 +81,74 @@ exports.ED25519_TORSION_SUBGROUP = [
81
81
  '0000000000000000000000000000000000000000000000000000000000000000',
82
82
  'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa',
83
83
  ];
84
- const Fp = (0, modular_js_1.Fp)(ED25519_P);
84
+ const Fp = (0, modular_js_1.Fp)(ED25519_P, undefined, true);
85
+ // Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator)
86
+ // NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since
87
+ // SageMath returns different root first and everything falls apart
88
+ const ELL2_C1 = (Fp.ORDER + BigInt(3)) / BigInt(8); // 1. c1 = (q + 3) / 8 # Integer arithmetic
89
+ const ELL2_C2 = Fp.pow(_2n, ELL2_C1); // 2. c2 = 2^c1
90
+ const ELL2_C3 = Fp.sqrt(Fp.negate(Fp.ONE)); // 3. c3 = sqrt(-1)
91
+ const ELL2_C4 = (Fp.ORDER - BigInt(5)) / BigInt(8); // 4. c4 = (q - 5) / 8 # Integer arithmetic
92
+ const ELL2_J = BigInt(486662);
93
+ // prettier-ignore
94
+ function map_to_curve_elligator2_curve25519(u) {
95
+ let tv1 = Fp.square(u); // 1. tv1 = u^2
96
+ tv1 = Fp.mul(tv1, _2n); // 2. tv1 = 2 * tv1
97
+ let xd = Fp.add(tv1, Fp.ONE); // 3. xd = tv1 + 1 # Nonzero: -1 is square (mod p), tv1 is not
98
+ let x1n = Fp.negate(ELL2_J); // 4. x1n = -J # x1 = x1n / xd = -J / (1 + 2 * u^2)
99
+ let tv2 = Fp.square(xd); // 5. tv2 = xd^2
100
+ let gxd = Fp.mul(tv2, xd); // 6. gxd = tv2 * xd # gxd = xd^3
101
+ let gx1 = Fp.mul(tv1, ELL2_J); // 7. gx1 = J * tv1 # x1n + J * xd
102
+ gx1 = Fp.mul(gx1, x1n); // 8. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd
103
+ gx1 = Fp.add(gx1, tv2); // 9. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2
104
+ gx1 = Fp.mul(gx1, x1n); // 10. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2
105
+ let tv3 = Fp.square(gxd); // 11. tv3 = gxd^2
106
+ tv2 = Fp.square(tv3); // 12. tv2 = tv3^2 # gxd^4
107
+ tv3 = Fp.mul(tv3, gxd); // 13. tv3 = tv3 * gxd # gxd^3
108
+ tv3 = Fp.mul(tv3, gx1); // 14. tv3 = tv3 * gx1 # gx1 * gxd^3
109
+ tv2 = Fp.mul(tv2, tv3); // 15. tv2 = tv2 * tv3 # gx1 * gxd^7
110
+ let y11 = Fp.pow(tv2, ELL2_C4); // 16. y11 = tv2^c4 # (gx1 * gxd^7)^((p - 5) / 8)
111
+ y11 = Fp.mul(y11, tv3); // 17. y11 = y11 * tv3 # gx1*gxd^3*(gx1*gxd^7)^((p-5)/8)
112
+ let y12 = Fp.mul(y11, ELL2_C3); // 18. y12 = y11 * c3
113
+ tv2 = Fp.square(y11); // 19. tv2 = y11^2
114
+ tv2 = Fp.mul(tv2, gxd); // 20. tv2 = tv2 * gxd
115
+ let e1 = Fp.equals(tv2, gx1); // 21. e1 = tv2 == gx1
116
+ let y1 = Fp.cmov(y12, y11, e1); // 22. y1 = CMOV(y12, y11, e1) # If g(x1) is square, this is its sqrt
117
+ let x2n = Fp.mul(x1n, tv1); // 23. x2n = x1n * tv1 # x2 = x2n / xd = 2 * u^2 * x1n / xd
118
+ let y21 = Fp.mul(y11, u); // 24. y21 = y11 * u
119
+ y21 = Fp.mul(y21, ELL2_C2); // 25. y21 = y21 * c2
120
+ let y22 = Fp.mul(y21, ELL2_C3); // 26. y22 = y21 * c3
121
+ let gx2 = Fp.mul(gx1, tv1); // 27. gx2 = gx1 * tv1 # g(x2) = gx2 / gxd = 2 * u^2 * g(x1)
122
+ tv2 = Fp.square(y21); // 28. tv2 = y21^2
123
+ tv2 = Fp.mul(tv2, gxd); // 29. tv2 = tv2 * gxd
124
+ let e2 = Fp.equals(tv2, gx2); // 30. e2 = tv2 == gx2
125
+ let y2 = Fp.cmov(y22, y21, e2); // 31. y2 = CMOV(y22, y21, e2) # If g(x2) is square, this is its sqrt
126
+ tv2 = Fp.square(y1); // 32. tv2 = y1^2
127
+ tv2 = Fp.mul(tv2, gxd); // 33. tv2 = tv2 * gxd
128
+ let e3 = Fp.equals(tv2, gx1); // 34. e3 = tv2 == gx1
129
+ let xn = Fp.cmov(x2n, x1n, e3); // 35. xn = CMOV(x2n, x1n, e3) # If e3, x = x1, else x = x2
130
+ let y = Fp.cmov(y2, y1, e3); // 36. y = CMOV(y2, y1, e3) # If e3, y = y1, else y = y2
131
+ let e4 = Fp.isOdd(y); // 37. e4 = sgn0(y) == 1 # Fix sign of y
132
+ y = Fp.cmov(y, Fp.negate(y), e3 !== e4); // 38. y = CMOV(y, -y, e3 XOR e4)
133
+ return { xMn: xn, xMd: xd, yMn: y, yMd: 1n }; // 39. return (xn, xd, y, 1)
134
+ }
135
+ const ELL2_C1_EDWARDS = (0, modular_js_1.FpSqrtEven)(Fp, Fp.negate(BigInt(486664))); // sgn0(c1) MUST equal 0
136
+ function map_to_curve_elligator2_edwards25519(u) {
137
+ const { xMn, xMd, yMn, yMd } = map_to_curve_elligator2_curve25519(u); // 1. (xMn, xMd, yMn, yMd) = map_to_curve_elligator2_curve25519(u)
138
+ let xn = Fp.mul(xMn, yMd); // 2. xn = xMn * yMd
139
+ xn = Fp.mul(xn, ELL2_C1_EDWARDS); // 3. xn = xn * c1
140
+ let xd = Fp.mul(xMd, yMn); // 4. xd = xMd * yMn # xn / xd = c1 * xM / yM
141
+ let yn = Fp.sub(xMn, xMd); // 5. yn = xMn - xMd
142
+ let yd = Fp.add(xMn, xMd); // 6. yd = xMn + xMd # (n / d - 1) / (n / d + 1) = (n - d) / (n + d)
143
+ let tv1 = Fp.mul(xd, yd); // 7. tv1 = xd * yd
144
+ let e = Fp.equals(tv1, Fp.ZERO); // 8. e = tv1 == 0
145
+ xn = Fp.cmov(xn, Fp.ZERO, e); // 9. xn = CMOV(xn, 0, e)
146
+ xd = Fp.cmov(xd, Fp.ONE, e); // 10. xd = CMOV(xd, 1, e)
147
+ yn = Fp.cmov(yn, Fp.ONE, e); // 11. yn = CMOV(yn, 1, e)
148
+ yd = Fp.cmov(yd, Fp.ONE, e); // 12. yd = CMOV(yd, 1, e)
149
+ const inv = Fp.invertBatch([xd, yd]); // batch division
150
+ return { x: Fp.mul(xn, inv[0]), y: Fp.mul(yn, inv[1]) }; // 13. return (xn, xd, yn, yd)
151
+ }
85
152
  const ED25519_DEF = {
86
153
  // Param: a
87
154
  a: BigInt(-1),
@@ -110,14 +177,10 @@ const ED25519_DEF = {
110
177
  p: Fp.ORDER,
111
178
  m: 1,
112
179
  k: 128,
113
- expand: true,
180
+ expand: 'xmd',
114
181
  hash: sha512_1.sha512,
115
182
  },
116
- mapToCurve: (scalars) => {
117
- throw new Error('Not supported yet');
118
- // const { x, y } = calcElligatorRistrettoMap(scalars[0]).toAffine();
119
- // return { x, y };
120
- },
183
+ mapToCurve: (scalars) => map_to_curve_elligator2_edwards25519(scalars[0]),
121
184
  };
122
185
  exports.ed25519 = (0, edwards_js_1.twistedEdwards)(ED25519_DEF);
123
186
  function ed25519_domain(data, ctx, phflag) {
@@ -162,13 +225,13 @@ const D_MINUS_ONE_SQ = BigInt('4044083434630853685810104246932319082624839914623
162
225
  // Calculates 1/√(number)
163
226
  const invertSqrt = (number) => uvRatio(_1n, number);
164
227
  const MAX_255B = BigInt('0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
165
- const bytes255ToNumberLE = (bytes) => exports.ed25519.utils.mod((0, utils_js_1.bytesToNumberLE)(bytes) & MAX_255B);
228
+ const bytes255ToNumberLE = (bytes) => exports.ed25519.CURVE.Fp.create((0, utils_js_1.bytesToNumberLE)(bytes) & MAX_255B);
166
229
  // Computes Elligator map for Ristretto
167
230
  // https://ristretto.group/formulas/elligator.html
168
231
  function calcElligatorRistrettoMap(r0) {
169
232
  const { d } = exports.ed25519.CURVE;
170
233
  const P = exports.ed25519.CURVE.Fp.ORDER;
171
- const { mod } = exports.ed25519.utils;
234
+ const mod = exports.ed25519.CURVE.Fp.create;
172
235
  const r = mod(SQRT_M1 * r0 * r0); // 1
173
236
  const Ns = mod((r + _1n) * ONE_MINUS_D_SQ); // 2
174
237
  let c = BigInt(-1); // 3
@@ -226,7 +289,7 @@ class RistrettoPoint {
226
289
  hex = (0, utils_js_1.ensureBytes)(hex, 32);
227
290
  const { a, d } = exports.ed25519.CURVE;
228
291
  const P = exports.ed25519.CURVE.Fp.ORDER;
229
- const { mod } = exports.ed25519.utils;
292
+ const mod = exports.ed25519.CURVE.Fp.create;
230
293
  const emsg = 'RistrettoPoint.fromHex: the hex is not valid encoding of RistrettoPoint';
231
294
  const s = bytes255ToNumberLE(hex);
232
295
  // 1. Check that s_bytes is the canonical encoding of a field element, or else abort.
@@ -258,7 +321,7 @@ class RistrettoPoint {
258
321
  toRawBytes() {
259
322
  let { x, y, z, t } = this.ep;
260
323
  const P = exports.ed25519.CURVE.Fp.ORDER;
261
- const { mod } = exports.ed25519.utils;
324
+ const mod = exports.ed25519.CURVE.Fp.create;
262
325
  const u1 = mod(mod(z + y) * mod(z - y)); // 1
263
326
  const u2 = mod(x * y); // 2
264
327
  // Square root always exists
@@ -296,7 +359,7 @@ class RistrettoPoint {
296
359
  assertRstPoint(other);
297
360
  const a = this.ep;
298
361
  const b = other.ep;
299
- const { mod } = exports.ed25519.utils;
362
+ const mod = exports.ed25519.CURVE.Fp.create;
300
363
  // (x1 * y2 == y1 * x2) | (y1 * y2 == x1 * x2)
301
364
  const one = mod(a.x * b.y) === mod(a.y * b.x);
302
365
  const two = mod(a.y * b.y) === mod(a.x * b.x);
package/lib/ed448.js CHANGED
@@ -48,14 +48,89 @@ function adjustScalarBytes(bytes) {
48
48
  bytes[56] = 0; // Byte outside of group (456 buts vs 448 bits)
49
49
  return bytes;
50
50
  }
51
+ const Fp = (0, modular_js_1.Fp)(ed448P, 456, true);
52
+ // Hash To Curve Elligator2 Map
53
+ const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4); // 1. c1 = (q - 3) / 4 # Integer arithmetic
54
+ const ELL2_J = BigInt(156326);
55
+ function map_to_curve_elligator2_curve448(u) {
56
+ let tv1 = Fp.square(u); // 1. tv1 = u^2
57
+ let e1 = Fp.equals(tv1, Fp.ONE); // 2. e1 = tv1 == 1
58
+ tv1 = Fp.cmov(tv1, Fp.ZERO, e1); // 3. tv1 = CMOV(tv1, 0, e1) # If Z * u^2 == -1, set tv1 = 0
59
+ let xd = Fp.sub(Fp.ONE, tv1); // 4. xd = 1 - tv1
60
+ let x1n = Fp.negate(ELL2_J); // 5. x1n = -J
61
+ let tv2 = Fp.square(xd); // 6. tv2 = xd^2
62
+ let gxd = Fp.mul(tv2, xd); // 7. gxd = tv2 * xd # gxd = xd^3
63
+ let gx1 = Fp.mul(tv1, Fp.negate(ELL2_J)); // 8. gx1 = -J * tv1 # x1n + J * xd
64
+ gx1 = Fp.mul(gx1, x1n); // 9. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd
65
+ gx1 = Fp.add(gx1, tv2); // 10. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2
66
+ gx1 = Fp.mul(gx1, x1n); // 11. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2
67
+ let tv3 = Fp.square(gxd); // 12. tv3 = gxd^2
68
+ tv2 = Fp.mul(gx1, gxd); // 13. tv2 = gx1 * gxd # gx1 * gxd
69
+ tv3 = Fp.mul(tv3, tv2); // 14. tv3 = tv3 * tv2 # gx1 * gxd^3
70
+ let y1 = Fp.pow(tv3, ELL2_C1); // 15. y1 = tv3^c1 # (gx1 * gxd^3)^((p - 3) / 4)
71
+ y1 = Fp.mul(y1, tv2); // 16. y1 = y1 * tv2 # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4)
72
+ let x2n = Fp.mul(x1n, Fp.negate(tv1)); // 17. x2n = -tv1 * x1n # x2 = x2n / xd = -1 * u^2 * x1n / xd
73
+ let y2 = Fp.mul(y1, u); // 18. y2 = y1 * u
74
+ y2 = Fp.cmov(y2, Fp.ZERO, e1); // 19. y2 = CMOV(y2, 0, e1)
75
+ tv2 = Fp.square(y1); // 20. tv2 = y1^2
76
+ tv2 = Fp.mul(tv2, gxd); // 21. tv2 = tv2 * gxd
77
+ let e2 = Fp.equals(tv2, gx1); // 22. e2 = tv2 == gx1
78
+ let xn = Fp.cmov(x2n, x1n, e2); // 23. xn = CMOV(x2n, x1n, e2) # If e2, x = x1, else x = x2
79
+ let y = Fp.cmov(y2, y1, e2); // 24. y = CMOV(y2, y1, e2) # If e2, y = y1, else y = y2
80
+ let e3 = Fp.isOdd(y); // 25. e3 = sgn0(y) == 1 # Fix sign of y
81
+ y = Fp.cmov(y, Fp.negate(y), e2 !== e3); // 26. y = CMOV(y, -y, e2 XOR e3)
82
+ return { xn, xd, yn: y, yd: Fp.ONE }; // 27. return (xn, xd, y, 1)
83
+ }
84
+ function map_to_curve_elligator2_edwards448(u) {
85
+ let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u); // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u)
86
+ let xn2 = Fp.square(xn); // 2. xn2 = xn^2
87
+ let xd2 = Fp.square(xd); // 3. xd2 = xd^2
88
+ let xd4 = Fp.square(xd2); // 4. xd4 = xd2^2
89
+ let yn2 = Fp.square(yn); // 5. yn2 = yn^2
90
+ let yd2 = Fp.square(yd); // 6. yd2 = yd^2
91
+ let xEn = Fp.sub(xn2, xd2); // 7. xEn = xn2 - xd2
92
+ let tv2 = Fp.sub(xEn, xd2); // 8. tv2 = xEn - xd2
93
+ xEn = Fp.mul(xEn, xd2); // 9. xEn = xEn * xd2
94
+ xEn = Fp.mul(xEn, yd); // 10. xEn = xEn * yd
95
+ xEn = Fp.mul(xEn, yn); // 11. xEn = xEn * yn
96
+ xEn = Fp.mul(xEn, 4n); // 12. xEn = xEn * 4
97
+ tv2 = Fp.mul(tv2, xn2); // 13. tv2 = tv2 * xn2
98
+ tv2 = Fp.mul(tv2, yd2); // 14. tv2 = tv2 * yd2
99
+ let tv3 = Fp.mul(yn2, 4n); // 15. tv3 = 4 * yn2
100
+ let tv1 = Fp.add(tv3, yd2); // 16. tv1 = tv3 + yd2
101
+ tv1 = Fp.mul(tv1, xd4); // 17. tv1 = tv1 * xd4
102
+ let xEd = Fp.add(tv1, tv2); // 18. xEd = tv1 + tv2
103
+ tv2 = Fp.mul(tv2, xn); // 19. tv2 = tv2 * xn
104
+ let tv4 = Fp.mul(xn, xd4); // 20. tv4 = xn * xd4
105
+ let yEn = Fp.sub(tv3, yd2); // 21. yEn = tv3 - yd2
106
+ yEn = Fp.mul(yEn, tv4); // 22. yEn = yEn * tv4
107
+ yEn = Fp.sub(yEn, tv2); // 23. yEn = yEn - tv2
108
+ tv1 = Fp.add(xn2, xd2); // 24. tv1 = xn2 + xd2
109
+ tv1 = Fp.mul(tv1, xd2); // 25. tv1 = tv1 * xd2
110
+ tv1 = Fp.mul(tv1, xd); // 26. tv1 = tv1 * xd
111
+ tv1 = Fp.mul(tv1, yn2); // 27. tv1 = tv1 * yn2
112
+ tv1 = Fp.mul(tv1, BigInt(-2)); // 28. tv1 = -2 * tv1
113
+ let yEd = Fp.add(tv2, tv1); // 29. yEd = tv2 + tv1
114
+ tv4 = Fp.mul(tv4, yd2); // 30. tv4 = tv4 * yd2
115
+ yEd = Fp.add(yEd, tv4); // 31. yEd = yEd + tv4
116
+ tv1 = Fp.mul(xEd, yEd); // 32. tv1 = xEd * yEd
117
+ let e = Fp.equals(tv1, Fp.ZERO); // 33. e = tv1 == 0
118
+ xEn = Fp.cmov(xEn, Fp.ZERO, e); // 34. xEn = CMOV(xEn, 0, e)
119
+ xEd = Fp.cmov(xEd, Fp.ONE, e); // 35. xEd = CMOV(xEd, 1, e)
120
+ yEn = Fp.cmov(yEn, Fp.ONE, e); // 36. yEn = CMOV(yEn, 1, e)
121
+ yEd = Fp.cmov(yEd, Fp.ONE, e); // 37. yEd = CMOV(yEd, 1, e)
122
+ const inv = Fp.invertBatch([xEd, yEd]); // batch division
123
+ return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) }; // 38. return (xEn, xEd, yEn, yEd)
124
+ }
51
125
  const ED448_DEF = {
52
126
  // Param: a
53
127
  a: BigInt(1),
54
128
  // -39081. Negative number is P - number
55
129
  d: BigInt('726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018326358'),
56
130
  // Finite field 𝔽p over which we'll do calculations; 2n ** 448n - 2n ** 224n - 1n
57
- Fp: (0, modular_js_1.Fp)(ed448P, 456),
58
- // Subgroup order: how many points ed448 has; 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n
131
+ Fp,
132
+ // Subgroup order: how many points curve has;
133
+ // 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n
59
134
  n: BigInt('181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779'),
60
135
  nBitLength: 456,
61
136
  // Cofactor
@@ -94,6 +169,15 @@ const ED448_DEF = {
94
169
  // square root exists, and the decoding fails.
95
170
  return { isValid: (0, modular_js_1.mod)(x2 * v, P) === u, value: x };
96
171
  },
172
+ htfDefaults: {
173
+ DST: 'edwards448_XOF:SHAKE256_ELL2_RO_',
174
+ p: Fp.ORDER,
175
+ m: 1,
176
+ k: 224,
177
+ expand: 'xof',
178
+ hash: sha3_1.shake256,
179
+ },
180
+ mapToCurve: (scalars) => map_to_curve_elligator2_edwards448(scalars[0]),
97
181
  };
98
182
  exports.ed448 = (0, edwards_js_1.twistedEdwards)(ED448_DEF);
99
183
  // NOTE: there is no ed448ctx, since ed448 supports ctx by default
@@ -1,21 +1,11 @@
1
- /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2
- // Barreto-Lynn-Scott Curves. A family of pairing friendly curves, with embedding degree = 12 or 24
3
- // NOTE: only 12 supported for now
4
- // Constructed from pair of weierstrass curves, based pairing logic
5
- import * as mod from './modular.js';
6
- import { ensureBytes, numberToBytesBE, bytesToNumberBE, bitLen, bitGet } from './utils.js';
7
- // Types
8
- import { hexToBytes, bytesToHex } from './utils.js';
9
- import { stringToBytes, hash_to_field, expand_message_xmd } from './hash-to-curve.js';
1
+ import * as ut from './utils.js';
2
+ import { stringToBytes, hash_to_field as hashToField, expand_message_xmd as expandMessageXMD, } from './hash-to-curve.js';
10
3
  import { weierstrassPoints } from './weierstrass.js';
11
4
  export function bls(CURVE) {
12
5
  // Fields looks pretty specific for curve, so for now we need to pass them with options
13
- const Fp = CURVE.Fp;
14
- const Fr = CURVE.Fr;
15
- const Fp2 = CURVE.Fp2;
16
- const Fp6 = CURVE.Fp6;
17
- const Fp12 = CURVE.Fp12;
18
- const BLS_X_LEN = bitLen(CURVE.x);
6
+ const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE;
7
+ const BLS_X_LEN = ut.bitLen(CURVE.x);
8
+ const groupLen = 32; // TODO: calculate; hardcoded for now
19
9
  // Pre-compute coefficients for sparse multiplication
20
10
  // Point addition and point double calculations is reused for coefficients
21
11
  function calcPairingPrecomputes(x, y) {
@@ -39,7 +29,7 @@ export function bls(CURVE) {
39
29
  Rx = Fp2.div(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), 2n); // ((T0 - T3) * Rx * Ry) / 2
40
30
  Ry = Fp2.sub(Fp2.square(Fp2.div(Fp2.add(t0, t3), 2n)), Fp2.mul(Fp2.square(t2), 3n)); // ((T0 + T3) / 2)² - 3 * T2²
41
31
  Rz = Fp2.mul(t0, t4); // T0 * T4
42
- if (bitGet(CURVE.x, i)) {
32
+ if (ut.bitGet(CURVE.x, i)) {
43
33
  // Addition
44
34
  let t0 = Fp2.sub(Ry, Fp2.mul(Qy, Rz)); // Ry - Qy * Rz
45
35
  let t1 = Fp2.sub(Rx, Fp2.mul(Qx, Rz)); // Rx - Qx * Rz
@@ -60,13 +50,14 @@ export function bls(CURVE) {
60
50
  return ell_coeff;
61
51
  }
62
52
  function millerLoop(ell, g1) {
53
+ const { x } = CURVE;
63
54
  const Px = g1[0];
64
55
  const Py = g1[1];
65
56
  let f12 = Fp12.ONE;
66
57
  for (let j = 0, i = BLS_X_LEN - 2; i >= 0; i--, j++) {
67
58
  const E = ell[j];
68
59
  f12 = Fp12.multiplyBy014(f12, E[0], Fp2.mul(E[1], Px), Fp2.mul(E[2], Py));
69
- if (bitGet(CURVE.x, i)) {
60
+ if (ut.bitGet(x, i)) {
70
61
  j += 1;
71
62
  const F = ell[j];
72
63
  f12 = Fp12.multiplyBy014(f12, F[0], Fp2.mul(F[1], Px), Fp2.mul(F[2], Py));
@@ -76,79 +67,25 @@ export function bls(CURVE) {
76
67
  }
77
68
  return Fp12.conjugate(f12);
78
69
  }
79
- // bls12-381 is a construction of two curves:
80
- // 1. Fp: (x, y)
81
- // 2. Fp₂: ((x₁, x₂+i), (y₁, y₂+i)) - (complex numbers)
82
- //
83
- // Bilinear Pairing (ate pairing) is used to combine both elements into a paired one:
84
- // Fp₁₂ = e(Fp, Fp2)
85
- // where Fp₁₂ = 12-degree polynomial
86
- // Pairing is used to verify signatures.
87
- //
88
- // We are using Fp for private keys (shorter) and Fp2 for signatures (longer).
89
- // Some projects may prefer to swap this relation, it is not supported for now.
90
- const htfDefaults = { ...CURVE.htfDefaults };
91
- function isWithinCurveOrder(num) {
92
- return 0 < num && num < CURVE.r;
93
- }
94
70
  const utils = {
95
- hexToBytes: hexToBytes,
96
- bytesToHex: bytesToHex,
97
- mod: mod.mod,
98
- stringToBytes,
71
+ hexToBytes: ut.hexToBytes,
72
+ bytesToHex: ut.bytesToHex,
73
+ stringToBytes: stringToBytes,
99
74
  // TODO: do we need to export it here?
100
- hashToField: (msg, count, options = {}) => hash_to_field(msg, count, { ...CURVE.htfDefaults, ...options }),
101
- expandMessageXMD: (msg, DST, lenInBytes, H = CURVE.hash) => expand_message_xmd(msg, DST, lenInBytes, H),
102
- /**
103
- * Can take 40 or more bytes of uniform input e.g. from CSPRNG or KDF
104
- * and convert them into private key, with the modulo bias being negligible.
105
- * As per FIPS 186 B.1.1.
106
- * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
107
- * @param hash hash output from sha512, or a similar function
108
- * @returns valid private key
109
- */
110
- hashToPrivateKey: (hash) => {
111
- hash = ensureBytes(hash);
112
- if (hash.length < 40 || hash.length > 1024)
113
- throw new Error('Expected 40-1024 bytes of private key as per FIPS 186');
114
- // hashToPrivateScalar(hash, CURVE.r)
115
- // NOTE: doesn't add +/-1
116
- const num = mod.mod(bytesToNumberBE(hash), CURVE.r);
117
- // This should never happen
118
- if (num === 0n || num === 1n)
119
- throw new Error('Invalid private key');
120
- return numberToBytesBE(num, 32);
121
- },
122
- randomBytes: (bytesLength = 32) => CURVE.randomBytes(bytesLength),
123
- // NIST SP 800-56A rev 3, section 5.6.1.2.2
124
- // https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
125
- randomPrivateKey: () => utils.hashToPrivateKey(utils.randomBytes(40)),
126
- getDSTLabel: () => htfDefaults.DST,
75
+ hashToField: (msg, count, options = {}) => hashToField(msg, count, { ...CURVE.htfDefaults, ...options }),
76
+ expandMessageXMD: (msg, DST, lenInBytes, H = CURVE.hash) => expandMessageXMD(msg, DST, lenInBytes, H),
77
+ hashToPrivateKey: (hash) => Fr.toBytes(ut.hashToPrivateScalar(hash, CURVE.r)),
78
+ randomBytes: (bytesLength = groupLen) => CURVE.randomBytes(bytesLength),
79
+ randomPrivateKey: () => utils.hashToPrivateKey(utils.randomBytes(groupLen + 8)),
80
+ getDSTLabel: () => CURVE.htfDefaults.DST,
127
81
  setDSTLabel(newLabel) {
128
82
  // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3.1
129
83
  if (typeof newLabel !== 'string' || newLabel.length > 2048 || newLabel.length === 0) {
130
84
  throw new TypeError('Invalid DST');
131
85
  }
132
- htfDefaults.DST = newLabel;
86
+ CURVE.htfDefaults.DST = newLabel;
133
87
  },
134
88
  };
135
- function normalizePrivKey(key) {
136
- let int;
137
- if (key instanceof Uint8Array && key.length === 32)
138
- int = bytesToNumberBE(key);
139
- else if (typeof key === 'string' && key.length === 64)
140
- int = BigInt(`0x${key}`);
141
- else if (typeof key === 'number' && key > 0 && Number.isSafeInteger(key))
142
- int = BigInt(key);
143
- else if (typeof key === 'bigint' && key > 0n)
144
- int = key;
145
- else
146
- throw new TypeError('Expected valid private key');
147
- int = mod.mod(int, CURVE.r);
148
- if (!isWithinCurveOrder(int))
149
- throw new Error('Private key must be 0 < key < CURVE.r');
150
- return int;
151
- }
152
89
  // Point on G1 curve: (x, y)
153
90
  const G1 = weierstrassPoints({
154
91
  n: Fr.ORDER,
@@ -202,7 +139,7 @@ export function bls(CURVE) {
202
139
  function sign(message, privateKey) {
203
140
  const msgPoint = normP2Hash(message);
204
141
  msgPoint.assertValidity();
205
- const sigPoint = msgPoint.multiply(normalizePrivKey(privateKey));
142
+ const sigPoint = msgPoint.multiply(G1.normalizePrivateKey(privateKey));
206
143
  if (message instanceof G2.Point)
207
144
  return sigPoint;
208
145
  return Signature.encode(sigPoint);