@noble/curves 1.9.5 → 2.0.0-beta.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 (211) hide show
  1. package/README.md +267 -421
  2. package/abstract/bls.d.ts +49 -111
  3. package/abstract/bls.d.ts.map +1 -1
  4. package/abstract/bls.js +108 -152
  5. package/abstract/bls.js.map +1 -1
  6. package/abstract/curve.d.ts +7 -48
  7. package/abstract/curve.d.ts.map +1 -1
  8. package/abstract/curve.js +22 -47
  9. package/abstract/curve.js.map +1 -1
  10. package/abstract/edwards.d.ts +17 -68
  11. package/abstract/edwards.d.ts.map +1 -1
  12. package/abstract/edwards.js +98 -175
  13. package/abstract/edwards.js.map +1 -1
  14. package/abstract/fft.js +14 -27
  15. package/abstract/fft.js.map +1 -1
  16. package/abstract/hash-to-curve.d.ts +11 -24
  17. package/abstract/hash-to-curve.d.ts.map +1 -1
  18. package/abstract/hash-to-curve.js +30 -35
  19. package/abstract/hash-to-curve.js.map +1 -1
  20. package/abstract/modular.d.ts +5 -17
  21. package/abstract/modular.d.ts.map +1 -1
  22. package/abstract/modular.js +166 -167
  23. package/abstract/modular.js.map +1 -1
  24. package/abstract/montgomery.d.ts +4 -9
  25. package/abstract/montgomery.d.ts.map +1 -1
  26. package/abstract/montgomery.js +17 -20
  27. package/abstract/montgomery.js.map +1 -1
  28. package/abstract/oprf.d.ts +282 -0
  29. package/abstract/oprf.d.ts.map +1 -0
  30. package/abstract/oprf.js +297 -0
  31. package/abstract/oprf.js.map +1 -0
  32. package/abstract/poseidon.js +20 -24
  33. package/abstract/poseidon.js.map +1 -1
  34. package/abstract/tower.d.ts +9 -7
  35. package/abstract/tower.d.ts.map +1 -1
  36. package/abstract/tower.js +600 -364
  37. package/abstract/tower.js.map +1 -1
  38. package/abstract/weierstrass.d.ts +12 -145
  39. package/abstract/weierstrass.d.ts.map +1 -1
  40. package/abstract/weierstrass.js +153 -377
  41. package/abstract/weierstrass.js.map +1 -1
  42. package/bls12-381.d.ts +2 -2
  43. package/bls12-381.d.ts.map +1 -1
  44. package/bls12-381.js +174 -216
  45. package/bls12-381.js.map +1 -1
  46. package/bn254.d.ts +58 -10
  47. package/bn254.d.ts.map +1 -1
  48. package/bn254.js +70 -130
  49. package/bn254.js.map +1 -1
  50. package/ed25519.d.ts +12 -31
  51. package/ed25519.d.ts.map +1 -1
  52. package/ed25519.js +104 -146
  53. package/ed25519.js.map +1 -1
  54. package/ed448.d.ts +14 -33
  55. package/ed448.d.ts.map +1 -1
  56. package/ed448.js +105 -132
  57. package/ed448.js.map +1 -1
  58. package/index.js +1 -1
  59. package/misc.d.ts +10 -14
  60. package/misc.d.ts.map +1 -1
  61. package/misc.js +51 -60
  62. package/misc.js.map +1 -1
  63. package/nist.d.ts +11 -14
  64. package/nist.d.ts.map +1 -1
  65. package/nist.js +46 -55
  66. package/nist.js.map +1 -1
  67. package/package.json +9 -224
  68. package/secp256k1.d.ts +7 -23
  69. package/secp256k1.d.ts.map +1 -1
  70. package/secp256k1.js +72 -83
  71. package/secp256k1.js.map +1 -1
  72. package/src/abstract/bls.ts +197 -344
  73. package/src/abstract/curve.ts +10 -83
  74. package/src/abstract/edwards.ts +96 -223
  75. package/src/abstract/hash-to-curve.ts +32 -45
  76. package/src/abstract/modular.ts +144 -130
  77. package/src/abstract/montgomery.ts +21 -22
  78. package/src/abstract/oprf.ts +600 -0
  79. package/src/abstract/tower.ts +627 -382
  80. package/src/abstract/weierstrass.ts +101 -482
  81. package/src/bls12-381.ts +148 -176
  82. package/src/bn254.ts +67 -122
  83. package/src/ed25519.ts +65 -118
  84. package/src/ed448.ts +63 -113
  85. package/src/index.ts +1 -1
  86. package/src/misc.ts +66 -49
  87. package/src/nist.ts +48 -57
  88. package/src/secp256k1.ts +56 -88
  89. package/src/utils.ts +41 -61
  90. package/src/webcrypto.ts +362 -0
  91. package/utils.d.ts +28 -19
  92. package/utils.d.ts.map +1 -1
  93. package/utils.js +45 -121
  94. package/utils.js.map +1 -1
  95. package/webcrypto.d.ts +47 -0
  96. package/webcrypto.d.ts.map +1 -0
  97. package/webcrypto.js +231 -0
  98. package/webcrypto.js.map +1 -0
  99. package/esm/_shortw_utils.d.ts +0 -19
  100. package/esm/_shortw_utils.d.ts.map +0 -1
  101. package/esm/_shortw_utils.js +0 -16
  102. package/esm/_shortw_utils.js.map +0 -1
  103. package/esm/abstract/bls.d.ts +0 -190
  104. package/esm/abstract/bls.d.ts.map +0 -1
  105. package/esm/abstract/bls.js +0 -408
  106. package/esm/abstract/bls.js.map +0 -1
  107. package/esm/abstract/curve.d.ts +0 -231
  108. package/esm/abstract/curve.d.ts.map +0 -1
  109. package/esm/abstract/curve.js +0 -465
  110. package/esm/abstract/curve.js.map +0 -1
  111. package/esm/abstract/edwards.d.ts +0 -237
  112. package/esm/abstract/edwards.d.ts.map +0 -1
  113. package/esm/abstract/edwards.js +0 -632
  114. package/esm/abstract/edwards.js.map +0 -1
  115. package/esm/abstract/fft.d.ts +0 -122
  116. package/esm/abstract/fft.d.ts.map +0 -1
  117. package/esm/abstract/fft.js +0 -425
  118. package/esm/abstract/fft.js.map +0 -1
  119. package/esm/abstract/hash-to-curve.d.ts +0 -102
  120. package/esm/abstract/hash-to-curve.d.ts.map +0 -1
  121. package/esm/abstract/hash-to-curve.js +0 -203
  122. package/esm/abstract/hash-to-curve.js.map +0 -1
  123. package/esm/abstract/modular.d.ts +0 -171
  124. package/esm/abstract/modular.d.ts.map +0 -1
  125. package/esm/abstract/modular.js +0 -530
  126. package/esm/abstract/modular.js.map +0 -1
  127. package/esm/abstract/montgomery.d.ts +0 -30
  128. package/esm/abstract/montgomery.d.ts.map +0 -1
  129. package/esm/abstract/montgomery.js +0 -157
  130. package/esm/abstract/montgomery.js.map +0 -1
  131. package/esm/abstract/poseidon.d.ts +0 -68
  132. package/esm/abstract/poseidon.d.ts.map +0 -1
  133. package/esm/abstract/poseidon.js +0 -296
  134. package/esm/abstract/poseidon.js.map +0 -1
  135. package/esm/abstract/tower.d.ts +0 -93
  136. package/esm/abstract/tower.d.ts.map +0 -1
  137. package/esm/abstract/tower.js +0 -502
  138. package/esm/abstract/tower.js.map +0 -1
  139. package/esm/abstract/utils.d.ts +0 -5
  140. package/esm/abstract/utils.d.ts.map +0 -1
  141. package/esm/abstract/utils.js +0 -7
  142. package/esm/abstract/utils.js.map +0 -1
  143. package/esm/abstract/weierstrass.d.ts +0 -412
  144. package/esm/abstract/weierstrass.d.ts.map +0 -1
  145. package/esm/abstract/weierstrass.js +0 -1428
  146. package/esm/abstract/weierstrass.js.map +0 -1
  147. package/esm/bls12-381.d.ts +0 -16
  148. package/esm/bls12-381.d.ts.map +0 -1
  149. package/esm/bls12-381.js +0 -738
  150. package/esm/bls12-381.js.map +0 -1
  151. package/esm/bn254.d.ts +0 -18
  152. package/esm/bn254.d.ts.map +0 -1
  153. package/esm/bn254.js +0 -246
  154. package/esm/bn254.js.map +0 -1
  155. package/esm/ed25519.d.ts +0 -106
  156. package/esm/ed25519.d.ts.map +0 -1
  157. package/esm/ed25519.js +0 -467
  158. package/esm/ed25519.js.map +0 -1
  159. package/esm/ed448.d.ts +0 -101
  160. package/esm/ed448.d.ts.map +0 -1
  161. package/esm/ed448.js +0 -448
  162. package/esm/ed448.js.map +0 -1
  163. package/esm/index.d.ts +0 -2
  164. package/esm/index.d.ts.map +0 -1
  165. package/esm/index.js +0 -17
  166. package/esm/index.js.map +0 -1
  167. package/esm/jubjub.d.ts +0 -12
  168. package/esm/jubjub.d.ts.map +0 -1
  169. package/esm/jubjub.js +0 -12
  170. package/esm/jubjub.js.map +0 -1
  171. package/esm/misc.d.ts +0 -19
  172. package/esm/misc.d.ts.map +0 -1
  173. package/esm/misc.js +0 -109
  174. package/esm/misc.js.map +0 -1
  175. package/esm/nist.d.ts +0 -21
  176. package/esm/nist.d.ts.map +0 -1
  177. package/esm/nist.js +0 -132
  178. package/esm/nist.js.map +0 -1
  179. package/esm/p256.d.ts +0 -16
  180. package/esm/p256.d.ts.map +0 -1
  181. package/esm/p256.js +0 -16
  182. package/esm/p256.js.map +0 -1
  183. package/esm/p384.d.ts +0 -16
  184. package/esm/p384.d.ts.map +0 -1
  185. package/esm/p384.js +0 -16
  186. package/esm/p384.js.map +0 -1
  187. package/esm/p521.d.ts +0 -16
  188. package/esm/p521.d.ts.map +0 -1
  189. package/esm/p521.js +0 -16
  190. package/esm/p521.js.map +0 -1
  191. package/esm/package.json +0 -4
  192. package/esm/pasta.d.ts +0 -10
  193. package/esm/pasta.d.ts.map +0 -1
  194. package/esm/pasta.js +0 -10
  195. package/esm/pasta.js.map +0 -1
  196. package/esm/secp256k1.d.ts +0 -89
  197. package/esm/secp256k1.d.ts.map +0 -1
  198. package/esm/secp256k1.js +0 -292
  199. package/esm/secp256k1.js.map +0 -1
  200. package/esm/utils.d.ts +0 -110
  201. package/esm/utils.d.ts.map +0 -1
  202. package/esm/utils.js +0 -322
  203. package/esm/utils.js.map +0 -1
  204. package/src/_shortw_utils.ts +0 -21
  205. package/src/abstract/utils.ts +0 -7
  206. package/src/jubjub.ts +0 -12
  207. package/src/p256.ts +0 -15
  208. package/src/p384.ts +0 -15
  209. package/src/p521.ts +0 -15
  210. package/src/package.json +0 -3
  211. package/src/pasta.ts +0 -9
package/abstract/tower.js CHANGED
@@ -1,7 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.psiFrobenius = psiFrobenius;
4
- exports.tower12 = tower12;
5
1
  /**
6
2
  * Towered extension fields.
7
3
  * Rather than implementing a massive 12th-degree extension directly, it is more efficient
@@ -14,8 +10,8 @@ exports.tower12 = tower12;
14
10
  * @module
15
11
  */
16
12
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
17
- const utils_ts_1 = require("../utils.js");
18
- const mod = require("./modular.js");
13
+ import { bitGet, bitLen, concatBytes, notImplemented } from "../utils.js";
14
+ import * as mod from "./modular.js";
19
15
  // Be friendly to bad ECMAScript parsers by not using bigint literals
20
16
  // prettier-ignore
21
17
  const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
@@ -36,7 +32,7 @@ function calcFrobeniusCoefficients(Fp, nonResidue, modulus, degree, num = 1, div
36
32
  return res;
37
33
  }
38
34
  // This works same at least for bls12-381, bn254 and bls12-377
39
- function psiFrobenius(Fp, Fp2, base) {
35
+ export function psiFrobenius(Fp, Fp2, base) {
40
36
  // GLV endomorphism Ψ(P)
41
37
  const PSI_X = Fp2.pow(base, (Fp.ORDER - _1n) / _3n); // u^((p-1)/3)
42
38
  const PSI_Y = Fp2.pow(base, (Fp.ORDER - _1n) / _2n); // u^((p-1)/2)
@@ -66,23 +62,90 @@ function psiFrobenius(Fp, Fp2, base) {
66
62
  const G2psi2 = mapAffine(psi2);
67
63
  return { psi, psi2, G2psi, G2psi2, PSI_X, PSI_Y, PSI2_X, PSI2_Y };
68
64
  }
69
- function tower12(opts) {
70
- const { ORDER } = opts;
71
- // Fp
72
- const Fp = mod.Field(ORDER);
73
- const FpNONRESIDUE = Fp.create(opts.NONRESIDUE || BigInt(-1));
74
- const Fpdiv2 = Fp.div(Fp.ONE, _2n); // 1/2
75
- // Fp2
76
- const FP2_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients(Fp, FpNONRESIDUE, Fp.ORDER, 2)[0];
77
- const Fp2Add = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({
78
- c0: Fp.add(c0, r0),
79
- c1: Fp.add(c1, r1),
80
- });
81
- const Fp2Subtract = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({
82
- c0: Fp.sub(c0, r0),
83
- c1: Fp.sub(c1, r1),
84
- });
85
- const Fp2Multiply = ({ c0, c1 }, rhs) => {
65
+ const Fp2fromBigTuple = (Fp, tuple) => {
66
+ if (tuple.length !== 2)
67
+ throw new Error('invalid tuple');
68
+ const fps = tuple.map((n) => Fp.create(n));
69
+ return { c0: fps[0], c1: fps[1] };
70
+ };
71
+ class _Field2 {
72
+ ORDER;
73
+ BITS;
74
+ BYTES;
75
+ isLE;
76
+ ZERO;
77
+ ONE;
78
+ Fp;
79
+ NONRESIDUE;
80
+ mulByB;
81
+ Fp_NONRESIDUE;
82
+ Fp_div2;
83
+ FROBENIUS_COEFFICIENTS;
84
+ constructor(Fp, opts = {}) {
85
+ const ORDER = Fp.ORDER;
86
+ const FP2_ORDER = ORDER * ORDER;
87
+ this.Fp = Fp;
88
+ this.ORDER = FP2_ORDER;
89
+ this.BITS = bitLen(FP2_ORDER);
90
+ this.BYTES = Math.ceil(bitLen(FP2_ORDER) / 8);
91
+ this.isLE = Fp.isLE;
92
+ this.ZERO = { c0: Fp.ZERO, c1: Fp.ZERO };
93
+ this.ONE = { c0: Fp.ONE, c1: Fp.ZERO };
94
+ this.Fp_NONRESIDUE = Fp.create(opts.NONRESIDUE || BigInt(-1));
95
+ this.Fp_div2 = Fp.div(Fp.ONE, _2n); // 1/2
96
+ this.NONRESIDUE = Fp2fromBigTuple(Fp, opts.FP2_NONRESIDUE);
97
+ // const Fp2Nonresidue = Fp2fromBigTuple(opts.FP2_NONRESIDUE);
98
+ this.FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients(Fp, this.Fp_NONRESIDUE, Fp.ORDER, 2)[0];
99
+ this.mulByB = opts.Fp2mulByB;
100
+ Object.seal(this);
101
+ }
102
+ fromBigTuple(tuple) {
103
+ return Fp2fromBigTuple(this.Fp, tuple);
104
+ }
105
+ create(num) {
106
+ return num;
107
+ }
108
+ isValid({ c0, c1 }) {
109
+ function isValidC(num, ORDER) {
110
+ return typeof num === 'bigint' && _0n <= num && num < ORDER;
111
+ }
112
+ return isValidC(c0, this.ORDER) && isValidC(c1, this.ORDER);
113
+ }
114
+ is0({ c0, c1 }) {
115
+ return this.Fp.is0(c0) && this.Fp.is0(c1);
116
+ }
117
+ isValidNot0(num) {
118
+ return !this.is0(num) && this.isValid(num);
119
+ }
120
+ eql({ c0, c1 }, { c0: r0, c1: r1 }) {
121
+ return this.Fp.eql(c0, r0) && this.Fp.eql(c1, r1);
122
+ }
123
+ neg({ c0, c1 }) {
124
+ return { c0: this.Fp.neg(c0), c1: this.Fp.neg(c1) };
125
+ }
126
+ pow(num, power) {
127
+ return mod.FpPow(this, num, power);
128
+ }
129
+ invertBatch(nums) {
130
+ return mod.FpInvertBatch(this, nums);
131
+ }
132
+ // Normalized
133
+ add(f1, f2) {
134
+ const { c0, c1 } = f1;
135
+ const { c0: r0, c1: r1 } = f2;
136
+ return {
137
+ c0: this.Fp.add(c0, r0),
138
+ c1: this.Fp.add(c1, r1),
139
+ };
140
+ }
141
+ sub({ c0, c1 }, { c0: r0, c1: r1 }) {
142
+ return {
143
+ c0: this.Fp.sub(c0, r0),
144
+ c1: this.Fp.sub(c1, r1),
145
+ };
146
+ }
147
+ mul({ c0, c1 }, rhs) {
148
+ const { Fp } = this;
86
149
  if (typeof rhs === 'bigint')
87
150
  return { c0: Fp.mul(c0, rhs), c1: Fp.mul(c1, rhs) };
88
151
  // (a+bi)(c+di) = (ac−bd) + (ad+bc)i
@@ -93,142 +156,171 @@ function tower12(opts) {
93
156
  const o0 = Fp.sub(t1, t2);
94
157
  const o1 = Fp.sub(Fp.mul(Fp.add(c0, c1), Fp.add(r0, r1)), Fp.add(t1, t2));
95
158
  return { c0: o0, c1: o1 };
96
- };
97
- const Fp2Square = ({ c0, c1 }) => {
159
+ }
160
+ sqr({ c0, c1 }) {
161
+ const { Fp } = this;
98
162
  const a = Fp.add(c0, c1);
99
163
  const b = Fp.sub(c0, c1);
100
164
  const c = Fp.add(c0, c0);
101
165
  return { c0: Fp.mul(a, b), c1: Fp.mul(c, c1) };
102
- };
103
- const Fp2fromBigTuple = (tuple) => {
104
- if (tuple.length !== 2)
105
- throw new Error('invalid tuple');
106
- const fps = tuple.map((n) => Fp.create(n));
107
- return { c0: fps[0], c1: fps[1] };
108
- };
109
- function isValidC(num, ORDER) {
110
- return typeof num === 'bigint' && _0n <= num && num < ORDER;
111
- }
112
- const FP2_ORDER = ORDER * ORDER;
113
- const Fp2Nonresidue = Fp2fromBigTuple(opts.FP2_NONRESIDUE);
114
- const Fp2 = {
115
- ORDER: FP2_ORDER,
116
- isLE: Fp.isLE,
117
- NONRESIDUE: Fp2Nonresidue,
118
- BITS: (0, utils_ts_1.bitLen)(FP2_ORDER),
119
- BYTES: Math.ceil((0, utils_ts_1.bitLen)(FP2_ORDER) / 8),
120
- MASK: (0, utils_ts_1.bitMask)((0, utils_ts_1.bitLen)(FP2_ORDER)),
121
- ZERO: { c0: Fp.ZERO, c1: Fp.ZERO },
122
- ONE: { c0: Fp.ONE, c1: Fp.ZERO },
123
- create: (num) => num,
124
- isValid: ({ c0, c1 }) => isValidC(c0, FP2_ORDER) && isValidC(c1, FP2_ORDER),
125
- is0: ({ c0, c1 }) => Fp.is0(c0) && Fp.is0(c1),
126
- isValidNot0: (num) => !Fp2.is0(num) && Fp2.isValid(num),
127
- eql: ({ c0, c1 }, { c0: r0, c1: r1 }) => Fp.eql(c0, r0) && Fp.eql(c1, r1),
128
- neg: ({ c0, c1 }) => ({ c0: Fp.neg(c0), c1: Fp.neg(c1) }),
129
- pow: (num, power) => mod.FpPow(Fp2, num, power),
130
- invertBatch: (nums) => mod.FpInvertBatch(Fp2, nums),
131
- // Normalized
132
- add: Fp2Add,
133
- sub: Fp2Subtract,
134
- mul: Fp2Multiply,
135
- sqr: Fp2Square,
136
- // NonNormalized stuff
137
- addN: Fp2Add,
138
- subN: Fp2Subtract,
139
- mulN: Fp2Multiply,
140
- sqrN: Fp2Square,
141
- // Why inversion for bigint inside Fp instead of Fp2? it is even used in that context?
142
- div: (lhs, rhs) => Fp2.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp2.inv(rhs)),
143
- inv: ({ c0: a, c1: b }) => {
144
- // We wish to find the multiplicative inverse of a nonzero
145
- // element a + bu in Fp2. We leverage an identity
146
- //
147
- // (a + bu)(a - bu) = a² + b²
148
- //
149
- // which holds because u² = -1. This can be rewritten as
150
- //
151
- // (a + bu)(a - bu)/(a² + b²) = 1
152
- //
153
- // because a² + b² = 0 has no nonzero solutions for (a, b).
154
- // This gives that (a - bu)/(a² + b²) is the inverse
155
- // of (a + bu). Importantly, this can be computing using
156
- // only a single inversion in Fp.
157
- const factor = Fp.inv(Fp.create(a * a + b * b));
158
- return { c0: Fp.mul(factor, Fp.create(a)), c1: Fp.mul(factor, Fp.create(-b)) };
159
- },
160
- sqrt: (num) => {
161
- if (opts.Fp2sqrt)
162
- return opts.Fp2sqrt(num);
163
- // This is generic for all quadratic extensions (Fp2)
164
- const { c0, c1 } = num;
165
- if (Fp.is0(c1)) {
166
- // if c0 is quadratic residue
167
- if (mod.FpLegendre(Fp, c0) === 1)
168
- return Fp2.create({ c0: Fp.sqrt(c0), c1: Fp.ZERO });
169
- else
170
- return Fp2.create({ c0: Fp.ZERO, c1: Fp.sqrt(Fp.div(c0, FpNONRESIDUE)) });
171
- }
172
- const a = Fp.sqrt(Fp.sub(Fp.sqr(c0), Fp.mul(Fp.sqr(c1), FpNONRESIDUE)));
173
- let d = Fp.mul(Fp.add(a, c0), Fpdiv2);
174
- const legendre = mod.FpLegendre(Fp, d);
175
- // -1, Quadratic non residue
176
- if (legendre === -1)
177
- d = Fp.sub(d, a);
178
- const a0 = Fp.sqrt(d);
179
- const candidateSqrt = Fp2.create({ c0: a0, c1: Fp.div(Fp.mul(c1, Fpdiv2), a0) });
180
- if (!Fp2.eql(Fp2.sqr(candidateSqrt), num))
181
- throw new Error('Cannot find square root');
182
- // Normalize root: at this point candidateSqrt ** 2 = num, but also -candidateSqrt ** 2 = num
183
- const x1 = candidateSqrt;
184
- const x2 = Fp2.neg(x1);
185
- const { re: re1, im: im1 } = Fp2.reim(x1);
186
- const { re: re2, im: im2 } = Fp2.reim(x2);
187
- if (im1 > im2 || (im1 === im2 && re1 > re2))
188
- return x1;
189
- return x2;
190
- },
191
- // Same as sgn0_m_eq_2 in RFC 9380
192
- isOdd: (x) => {
193
- const { re: x0, im: x1 } = Fp2.reim(x);
194
- const sign_0 = x0 % _2n;
195
- const zero_0 = x0 === _0n;
196
- const sign_1 = x1 % _2n;
197
- return BigInt(sign_0 || (zero_0 && sign_1)) == _1n;
198
- },
199
- // Bytes util
200
- fromBytes(b) {
201
- if (b.length !== Fp2.BYTES)
202
- throw new Error('fromBytes invalid length=' + b.length);
203
- return { c0: Fp.fromBytes(b.subarray(0, Fp.BYTES)), c1: Fp.fromBytes(b.subarray(Fp.BYTES)) };
204
- },
205
- toBytes: ({ c0, c1 }) => (0, utils_ts_1.concatBytes)(Fp.toBytes(c0), Fp.toBytes(c1)),
206
- cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({
207
- c0: Fp.cmov(c0, r0, c),
208
- c1: Fp.cmov(c1, r1, c),
209
- }),
210
- reim: ({ c0, c1 }) => ({ re: c0, im: c1 }),
211
- // multiply by u + 1
212
- mulByNonresidue: ({ c0, c1 }) => Fp2.mul({ c0, c1 }, Fp2Nonresidue),
213
- mulByB: opts.Fp2mulByB,
214
- fromBigTuple: Fp2fromBigTuple,
215
- frobeniusMap: ({ c0, c1 }, power) => ({
166
+ }
167
+ // NonNormalized stuff
168
+ addN(a, b) {
169
+ return this.add(a, b);
170
+ }
171
+ subN(a, b) {
172
+ return this.sub(a, b);
173
+ }
174
+ mulN(a, b) {
175
+ return this.mul(a, b);
176
+ }
177
+ sqrN(a) {
178
+ return this.sqr(a);
179
+ }
180
+ // Why inversion for bigint inside Fp instead of Fp2? it is even used in that context?
181
+ div(lhs, rhs) {
182
+ const { Fp } = this;
183
+ // @ts-ignore
184
+ return this.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : this.inv(rhs));
185
+ }
186
+ inv({ c0: a, c1: b }) {
187
+ // We wish to find the multiplicative inverse of a nonzero
188
+ // element a + bu in Fp2. We leverage an identity
189
+ //
190
+ // (a + bu)(a - bu) = a² + b²
191
+ //
192
+ // which holds because = -1. This can be rewritten as
193
+ //
194
+ // (a + bu)(a - bu)/( + b²) = 1
195
+ //
196
+ // because a² + b² = 0 has no nonzero solutions for (a, b).
197
+ // This gives that (a - bu)/(a² + b²) is the inverse
198
+ // of (a + bu). Importantly, this can be computing using
199
+ // only a single inversion in Fp.
200
+ const { Fp } = this;
201
+ const factor = Fp.inv(Fp.create(a * a + b * b));
202
+ return { c0: Fp.mul(factor, Fp.create(a)), c1: Fp.mul(factor, Fp.create(-b)) };
203
+ }
204
+ sqrt(num) {
205
+ // This is generic for all quadratic extensions (Fp2)
206
+ const { Fp } = this;
207
+ const Fp2 = this;
208
+ const { c0, c1 } = num;
209
+ if (Fp.is0(c1)) {
210
+ // if c0 is quadratic residue
211
+ if (mod.FpLegendre(Fp, c0) === 1)
212
+ return Fp2.create({ c0: Fp.sqrt(c0), c1: Fp.ZERO });
213
+ else
214
+ return Fp2.create({ c0: Fp.ZERO, c1: Fp.sqrt(Fp.div(c0, this.Fp_NONRESIDUE)) });
215
+ }
216
+ const a = Fp.sqrt(Fp.sub(Fp.sqr(c0), Fp.mul(Fp.sqr(c1), this.Fp_NONRESIDUE)));
217
+ let d = Fp.mul(Fp.add(a, c0), this.Fp_div2);
218
+ const legendre = mod.FpLegendre(Fp, d);
219
+ // -1, Quadratic non residue
220
+ if (legendre === -1)
221
+ d = Fp.sub(d, a);
222
+ const a0 = Fp.sqrt(d);
223
+ const candidateSqrt = Fp2.create({ c0: a0, c1: Fp.div(Fp.mul(c1, this.Fp_div2), a0) });
224
+ if (!Fp2.eql(Fp2.sqr(candidateSqrt), num))
225
+ throw new Error('Cannot find square root');
226
+ // Normalize root: at this point candidateSqrt ** 2 = num, but also -candidateSqrt ** 2 = num
227
+ const x1 = candidateSqrt;
228
+ const x2 = Fp2.neg(x1);
229
+ const { re: re1, im: im1 } = Fp2.reim(x1);
230
+ const { re: re2, im: im2 } = Fp2.reim(x2);
231
+ if (im1 > im2 || (im1 === im2 && re1 > re2))
232
+ return x1;
233
+ return x2;
234
+ }
235
+ // Same as sgn0_m_eq_2 in RFC 9380
236
+ isOdd(x) {
237
+ const { re: x0, im: x1 } = this.reim(x);
238
+ const sign_0 = x0 % _2n;
239
+ const zero_0 = x0 === _0n;
240
+ const sign_1 = x1 % _2n;
241
+ return BigInt(sign_0 || (zero_0 && sign_1)) == _1n;
242
+ }
243
+ // Bytes util
244
+ fromBytes(b) {
245
+ const { Fp } = this;
246
+ if (b.length !== this.BYTES)
247
+ throw new Error('fromBytes invalid length=' + b.length);
248
+ return { c0: Fp.fromBytes(b.subarray(0, Fp.BYTES)), c1: Fp.fromBytes(b.subarray(Fp.BYTES)) };
249
+ }
250
+ toBytes({ c0, c1 }) {
251
+ return concatBytes(this.Fp.toBytes(c0), this.Fp.toBytes(c1));
252
+ }
253
+ cmov({ c0, c1 }, { c0: r0, c1: r1 }, c) {
254
+ return {
255
+ c0: this.Fp.cmov(c0, r0, c),
256
+ c1: this.Fp.cmov(c1, r1, c),
257
+ };
258
+ }
259
+ reim({ c0, c1 }) {
260
+ return { re: c0, im: c1 };
261
+ }
262
+ Fp4Square(a, b) {
263
+ const Fp2 = this;
264
+ const a2 = Fp2.sqr(a);
265
+ const b2 = Fp2.sqr(b);
266
+ return {
267
+ first: Fp2.add(Fp2.mulByNonresidue(b2), a2), // b² * Nonresidue + a²
268
+ second: Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b²
269
+ };
270
+ }
271
+ // multiply by u + 1
272
+ mulByNonresidue({ c0, c1 }) {
273
+ return this.mul({ c0, c1 }, this.NONRESIDUE);
274
+ }
275
+ frobeniusMap({ c0, c1 }, power) {
276
+ return {
216
277
  c0,
217
- c1: Fp.mul(c1, FP2_FROBENIUS_COEFFICIENTS[power % 2]),
218
- }),
219
- };
220
- // Fp6
221
- const Fp6Add = ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => ({
222
- c0: Fp2.add(c0, r0),
223
- c1: Fp2.add(c1, r1),
224
- c2: Fp2.add(c2, r2),
225
- });
226
- const Fp6Subtract = ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => ({
227
- c0: Fp2.sub(c0, r0),
228
- c1: Fp2.sub(c1, r1),
229
- c2: Fp2.sub(c2, r2),
230
- });
231
- const Fp6Multiply = ({ c0, c1, c2 }, rhs) => {
278
+ c1: this.Fp.mul(c1, this.FROBENIUS_COEFFICIENTS[power % 2]),
279
+ };
280
+ }
281
+ }
282
+ class _Field6 {
283
+ ORDER;
284
+ BITS;
285
+ BYTES;
286
+ isLE;
287
+ ZERO;
288
+ ONE;
289
+ Fp2;
290
+ FROBENIUS_COEFFICIENTS_1;
291
+ FROBENIUS_COEFFICIENTS_2;
292
+ constructor(Fp2) {
293
+ this.Fp2 = Fp2;
294
+ this.ORDER = Fp2.ORDER; // TODO: unused, but need to verify
295
+ this.BITS = 3 * Fp2.BITS;
296
+ this.BYTES = 3 * Fp2.BYTES;
297
+ this.isLE = Fp2.isLE;
298
+ this.ZERO = { c0: Fp2.ZERO, c1: Fp2.ZERO, c2: Fp2.ZERO };
299
+ this.ONE = { c0: Fp2.ONE, c1: Fp2.ZERO, c2: Fp2.ZERO };
300
+ const { Fp } = Fp2;
301
+ const frob = calcFrobeniusCoefficients(Fp2, Fp2.NONRESIDUE, Fp.ORDER, 6, 2, 3);
302
+ this.FROBENIUS_COEFFICIENTS_1 = frob[0];
303
+ this.FROBENIUS_COEFFICIENTS_2 = frob[1];
304
+ Object.seal(this);
305
+ }
306
+ add({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) {
307
+ const { Fp2 } = this;
308
+ return {
309
+ c0: Fp2.add(c0, r0),
310
+ c1: Fp2.add(c1, r1),
311
+ c2: Fp2.add(c2, r2),
312
+ };
313
+ }
314
+ sub({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) {
315
+ const { Fp2 } = this;
316
+ return {
317
+ c0: Fp2.sub(c0, r0),
318
+ c1: Fp2.sub(c1, r1),
319
+ c2: Fp2.sub(c2, r2),
320
+ };
321
+ }
322
+ mul({ c0, c1, c2 }, rhs) {
323
+ const { Fp2 } = this;
232
324
  if (typeof rhs === 'bigint') {
233
325
  return {
234
326
  c0: Fp2.mul(c0, rhs),
@@ -248,8 +340,9 @@ function tower12(opts) {
248
340
  // T1 + (c0 + c2) * (r0 + r2) - T0 + T2
249
341
  c2: Fp2.sub(Fp2.add(t1, Fp2.mul(Fp2.add(c0, c2), Fp2.add(r0, r2))), Fp2.add(t0, t2)),
250
342
  };
251
- };
252
- const Fp6Square = ({ c0, c1, c2 }) => {
343
+ }
344
+ sqr({ c0, c1, c2 }) {
345
+ const { Fp2 } = this;
253
346
  let t0 = Fp2.sqr(c0); // c0²
254
347
  let t1 = Fp2.mul(Fp2.mul(c0, c1), _2n); // 2 * c0 * c1
255
348
  let t3 = Fp2.mul(Fp2.mul(c1, c2), _2n); // 2 * c1 * c2
@@ -260,112 +353,227 @@ function tower12(opts) {
260
353
  // T1 + (c0 - c1 + c2)² + T3 - T0 - T4
261
354
  c2: Fp2.sub(Fp2.sub(Fp2.add(Fp2.add(t1, Fp2.sqr(Fp2.add(Fp2.sub(c0, c1), c2))), t3), t0), t4),
262
355
  };
263
- };
264
- const [FP6_FROBENIUS_COEFFICIENTS_1, FP6_FROBENIUS_COEFFICIENTS_2] = calcFrobeniusCoefficients(Fp2, Fp2Nonresidue, Fp.ORDER, 6, 2, 3);
265
- const Fp6 = {
266
- ORDER: Fp2.ORDER, // TODO: unused, but need to verify
267
- isLE: Fp2.isLE,
268
- BITS: 3 * Fp2.BITS,
269
- BYTES: 3 * Fp2.BYTES,
270
- MASK: (0, utils_ts_1.bitMask)(3 * Fp2.BITS),
271
- ZERO: { c0: Fp2.ZERO, c1: Fp2.ZERO, c2: Fp2.ZERO },
272
- ONE: { c0: Fp2.ONE, c1: Fp2.ZERO, c2: Fp2.ZERO },
273
- create: (num) => num,
274
- isValid: ({ c0, c1, c2 }) => Fp2.isValid(c0) && Fp2.isValid(c1) && Fp2.isValid(c2),
275
- is0: ({ c0, c1, c2 }) => Fp2.is0(c0) && Fp2.is0(c1) && Fp2.is0(c2),
276
- isValidNot0: (num) => !Fp6.is0(num) && Fp6.isValid(num),
277
- neg: ({ c0, c1, c2 }) => ({ c0: Fp2.neg(c0), c1: Fp2.neg(c1), c2: Fp2.neg(c2) }),
278
- eql: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => Fp2.eql(c0, r0) && Fp2.eql(c1, r1) && Fp2.eql(c2, r2),
279
- sqrt: utils_ts_1.notImplemented,
280
- // Do we need division by bigint at all? Should be done via order:
281
- div: (lhs, rhs) => Fp6.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp6.inv(rhs)),
282
- pow: (num, power) => mod.FpPow(Fp6, num, power),
283
- invertBatch: (nums) => mod.FpInvertBatch(Fp6, nums),
284
- // Normalized
285
- add: Fp6Add,
286
- sub: Fp6Subtract,
287
- mul: Fp6Multiply,
288
- sqr: Fp6Square,
289
- // NonNormalized stuff
290
- addN: Fp6Add,
291
- subN: Fp6Subtract,
292
- mulN: Fp6Multiply,
293
- sqrN: Fp6Square,
294
- inv: ({ c0, c1, c2 }) => {
295
- let t0 = Fp2.sub(Fp2.sqr(c0), Fp2.mulByNonresidue(Fp2.mul(c2, c1))); // c0² - c2 * c1 * (u + 1)
296
- let t1 = Fp2.sub(Fp2.mulByNonresidue(Fp2.sqr(c2)), Fp2.mul(c0, c1)); // c2² * (u + 1) - c0 * c1
297
- let t2 = Fp2.sub(Fp2.sqr(c1), Fp2.mul(c0, c2)); // c1² - c0 * c2
298
- // 1/(((c2 * T1 + c1 * T2) * v) + c0 * T0)
299
- let t4 = Fp2.inv(Fp2.add(Fp2.mulByNonresidue(Fp2.add(Fp2.mul(c2, t1), Fp2.mul(c1, t2))), Fp2.mul(c0, t0)));
300
- return { c0: Fp2.mul(t4, t0), c1: Fp2.mul(t4, t1), c2: Fp2.mul(t4, t2) };
301
- },
302
- // Bytes utils
303
- fromBytes: (b) => {
304
- if (b.length !== Fp6.BYTES)
305
- throw new Error('fromBytes invalid length=' + b.length);
306
- return {
307
- c0: Fp2.fromBytes(b.subarray(0, Fp2.BYTES)),
308
- c1: Fp2.fromBytes(b.subarray(Fp2.BYTES, 2 * Fp2.BYTES)),
309
- c2: Fp2.fromBytes(b.subarray(2 * Fp2.BYTES)),
310
- };
311
- },
312
- toBytes: ({ c0, c1, c2 }) => (0, utils_ts_1.concatBytes)(Fp2.toBytes(c0), Fp2.toBytes(c1), Fp2.toBytes(c2)),
313
- cmov: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }, c) => ({
356
+ }
357
+ addN(a, b) {
358
+ return this.add(a, b);
359
+ }
360
+ subN(a, b) {
361
+ return this.sub(a, b);
362
+ }
363
+ mulN(a, b) {
364
+ return this.mul(a, b);
365
+ }
366
+ sqrN(a) {
367
+ return this.sqr(a);
368
+ }
369
+ create(num) {
370
+ return num;
371
+ }
372
+ isValid({ c0, c1, c2 }) {
373
+ const { Fp2 } = this;
374
+ return Fp2.isValid(c0) && Fp2.isValid(c1) && Fp2.isValid(c2);
375
+ }
376
+ is0({ c0, c1, c2 }) {
377
+ const { Fp2 } = this;
378
+ return Fp2.is0(c0) && Fp2.is0(c1) && Fp2.is0(c2);
379
+ }
380
+ isValidNot0(num) {
381
+ return !this.is0(num) && this.isValid(num);
382
+ }
383
+ neg({ c0, c1, c2 }) {
384
+ const { Fp2 } = this;
385
+ return { c0: Fp2.neg(c0), c1: Fp2.neg(c1), c2: Fp2.neg(c2) };
386
+ }
387
+ eql({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) {
388
+ const { Fp2 } = this;
389
+ return Fp2.eql(c0, r0) && Fp2.eql(c1, r1) && Fp2.eql(c2, r2);
390
+ }
391
+ sqrt(_) {
392
+ return notImplemented();
393
+ }
394
+ // Do we need division by bigint at all? Should be done via order:
395
+ div(lhs, rhs) {
396
+ const { Fp2 } = this;
397
+ const { Fp } = Fp2;
398
+ return this.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : this.inv(rhs));
399
+ }
400
+ pow(num, power) {
401
+ return mod.FpPow(this, num, power);
402
+ }
403
+ invertBatch(nums) {
404
+ return mod.FpInvertBatch(this, nums);
405
+ }
406
+ inv({ c0, c1, c2 }) {
407
+ const { Fp2 } = this;
408
+ let t0 = Fp2.sub(Fp2.sqr(c0), Fp2.mulByNonresidue(Fp2.mul(c2, c1))); // c0² - c2 * c1 * (u + 1)
409
+ let t1 = Fp2.sub(Fp2.mulByNonresidue(Fp2.sqr(c2)), Fp2.mul(c0, c1)); // c2² * (u + 1) - c0 * c1
410
+ let t2 = Fp2.sub(Fp2.sqr(c1), Fp2.mul(c0, c2)); // c1² - c0 * c2
411
+ // 1/(((c2 * T1 + c1 * T2) * v) + c0 * T0)
412
+ let t4 = Fp2.inv(Fp2.add(Fp2.mulByNonresidue(Fp2.add(Fp2.mul(c2, t1), Fp2.mul(c1, t2))), Fp2.mul(c0, t0)));
413
+ return { c0: Fp2.mul(t4, t0), c1: Fp2.mul(t4, t1), c2: Fp2.mul(t4, t2) };
414
+ }
415
+ // Bytes utils
416
+ fromBytes(b) {
417
+ const { Fp2 } = this;
418
+ if (b.length !== this.BYTES)
419
+ throw new Error('fromBytes invalid length=' + b.length);
420
+ const B2 = Fp2.BYTES;
421
+ return {
422
+ c0: Fp2.fromBytes(b.subarray(0, B2)),
423
+ c1: Fp2.fromBytes(b.subarray(B2, B2 * 2)),
424
+ c2: Fp2.fromBytes(b.subarray(2 * B2)),
425
+ };
426
+ }
427
+ toBytes({ c0, c1, c2 }) {
428
+ const { Fp2 } = this;
429
+ return concatBytes(Fp2.toBytes(c0), Fp2.toBytes(c1), Fp2.toBytes(c2));
430
+ }
431
+ cmov({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }, c) {
432
+ const { Fp2 } = this;
433
+ return {
314
434
  c0: Fp2.cmov(c0, r0, c),
315
435
  c1: Fp2.cmov(c1, r1, c),
316
436
  c2: Fp2.cmov(c2, r2, c),
317
- }),
318
- fromBigSix: (t) => {
319
- if (!Array.isArray(t) || t.length !== 6)
320
- throw new Error('invalid Fp6 usage');
321
- return {
322
- c0: Fp2.fromBigTuple(t.slice(0, 2)),
323
- c1: Fp2.fromBigTuple(t.slice(2, 4)),
324
- c2: Fp2.fromBigTuple(t.slice(4, 6)),
325
- };
326
- },
327
- frobeniusMap: ({ c0, c1, c2 }, power) => ({
437
+ };
438
+ }
439
+ fromBigSix(t) {
440
+ const { Fp2 } = this;
441
+ if (!Array.isArray(t) || t.length !== 6)
442
+ throw new Error('invalid Fp6 usage');
443
+ return {
444
+ c0: Fp2.fromBigTuple(t.slice(0, 2)),
445
+ c1: Fp2.fromBigTuple(t.slice(2, 4)),
446
+ c2: Fp2.fromBigTuple(t.slice(4, 6)),
447
+ };
448
+ }
449
+ frobeniusMap({ c0, c1, c2 }, power) {
450
+ const { Fp2 } = this;
451
+ return {
328
452
  c0: Fp2.frobeniusMap(c0, power),
329
- c1: Fp2.mul(Fp2.frobeniusMap(c1, power), FP6_FROBENIUS_COEFFICIENTS_1[power % 6]),
330
- c2: Fp2.mul(Fp2.frobeniusMap(c2, power), FP6_FROBENIUS_COEFFICIENTS_2[power % 6]),
331
- }),
332
- mulByFp2: ({ c0, c1, c2 }, rhs) => ({
453
+ c1: Fp2.mul(Fp2.frobeniusMap(c1, power), this.FROBENIUS_COEFFICIENTS_1[power % 6]),
454
+ c2: Fp2.mul(Fp2.frobeniusMap(c2, power), this.FROBENIUS_COEFFICIENTS_2[power % 6]),
455
+ };
456
+ }
457
+ mulByFp2({ c0, c1, c2 }, rhs) {
458
+ const { Fp2 } = this;
459
+ return {
333
460
  c0: Fp2.mul(c0, rhs),
334
461
  c1: Fp2.mul(c1, rhs),
335
462
  c2: Fp2.mul(c2, rhs),
336
- }),
337
- mulByNonresidue: ({ c0, c1, c2 }) => ({ c0: Fp2.mulByNonresidue(c2), c1: c0, c2: c1 }),
338
- // Sparse multiplication
339
- mul1: ({ c0, c1, c2 }, b1) => ({
463
+ };
464
+ }
465
+ mulByNonresidue({ c0, c1, c2 }) {
466
+ const { Fp2 } = this;
467
+ return { c0: Fp2.mulByNonresidue(c2), c1: c0, c2: c1 };
468
+ }
469
+ // Sparse multiplication
470
+ mul1({ c0, c1, c2 }, b1) {
471
+ const { Fp2 } = this;
472
+ return {
340
473
  c0: Fp2.mulByNonresidue(Fp2.mul(c2, b1)),
341
474
  c1: Fp2.mul(c0, b1),
342
475
  c2: Fp2.mul(c1, b1),
343
- }),
344
- // Sparse multiplication
345
- mul01({ c0, c1, c2 }, b0, b1) {
346
- let t0 = Fp2.mul(c0, b0); // c0 * b0
347
- let t1 = Fp2.mul(c1, b1); // c1 * b1
348
- return {
349
- // ((c1 + c2) * b1 - T1) * (u + 1) + T0
350
- c0: Fp2.add(Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), b1), t1)), t0),
351
- // (b0 + b1) * (c0 + c1) - T0 - T1
352
- c1: Fp2.sub(Fp2.sub(Fp2.mul(Fp2.add(b0, b1), Fp2.add(c0, c1)), t0), t1),
353
- // (c0 + c2) * b0 - T0 + T1
354
- c2: Fp2.add(Fp2.sub(Fp2.mul(Fp2.add(c0, c2), b0), t0), t1),
355
- };
356
- },
357
- };
358
- // Fp12
359
- const FP12_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients(Fp2, Fp2Nonresidue, Fp.ORDER, 12, 1, 6)[0];
360
- const Fp12Add = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({
361
- c0: Fp6.add(c0, r0),
362
- c1: Fp6.add(c1, r1),
363
- });
364
- const Fp12Subtract = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({
365
- c0: Fp6.sub(c0, r0),
366
- c1: Fp6.sub(c1, r1),
367
- });
368
- const Fp12Multiply = ({ c0, c1 }, rhs) => {
476
+ };
477
+ }
478
+ // Sparse multiplication
479
+ mul01({ c0, c1, c2 }, b0, b1) {
480
+ const { Fp2 } = this;
481
+ let t0 = Fp2.mul(c0, b0); // c0 * b0
482
+ let t1 = Fp2.mul(c1, b1); // c1 * b1
483
+ return {
484
+ // ((c1 + c2) * b1 - T1) * (u + 1) + T0
485
+ c0: Fp2.add(Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), b1), t1)), t0),
486
+ // (b0 + b1) * (c0 + c1) - T0 - T1
487
+ c1: Fp2.sub(Fp2.sub(Fp2.mul(Fp2.add(b0, b1), Fp2.add(c0, c1)), t0), t1),
488
+ // (c0 + c2) * b0 - T0 + T1
489
+ c2: Fp2.add(Fp2.sub(Fp2.mul(Fp2.add(c0, c2), b0), t0), t1),
490
+ };
491
+ }
492
+ }
493
+ class _Field12 {
494
+ ORDER;
495
+ BITS;
496
+ BYTES;
497
+ isLE;
498
+ ZERO;
499
+ ONE;
500
+ Fp6;
501
+ FROBENIUS_COEFFICIENTS;
502
+ X_LEN;
503
+ finalExponentiate;
504
+ constructor(Fp6, opts) {
505
+ const { Fp2 } = Fp6;
506
+ const { Fp } = Fp2;
507
+ this.Fp6 = Fp6;
508
+ this.ORDER = Fp2.ORDER; // TODO: verify if it's unuesd
509
+ this.BITS = 2 * Fp6.BITS;
510
+ this.BYTES = 2 * Fp6.BYTES;
511
+ this.isLE = Fp6.isLE;
512
+ this.ZERO = { c0: Fp6.ZERO, c1: Fp6.ZERO };
513
+ this.ONE = { c0: Fp6.ONE, c1: Fp6.ZERO };
514
+ this.FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients(Fp2, Fp2.NONRESIDUE, Fp.ORDER, 12, 1, 6)[0];
515
+ this.X_LEN = opts.X_LEN;
516
+ this.finalExponentiate = opts.Fp12finalExponentiate;
517
+ }
518
+ create(num) {
519
+ return num;
520
+ }
521
+ isValid({ c0, c1 }) {
522
+ const { Fp6 } = this;
523
+ return Fp6.isValid(c0) && Fp6.isValid(c1);
524
+ }
525
+ is0({ c0, c1 }) {
526
+ const { Fp6 } = this;
527
+ return Fp6.is0(c0) && Fp6.is0(c1);
528
+ }
529
+ isValidNot0(num) {
530
+ return !this.is0(num) && this.isValid(num);
531
+ }
532
+ neg({ c0, c1 }) {
533
+ const { Fp6 } = this;
534
+ return { c0: Fp6.neg(c0), c1: Fp6.neg(c1) };
535
+ }
536
+ eql({ c0, c1 }, { c0: r0, c1: r1 }) {
537
+ const { Fp6 } = this;
538
+ return Fp6.eql(c0, r0) && Fp6.eql(c1, r1);
539
+ }
540
+ sqrt(_) {
541
+ notImplemented();
542
+ }
543
+ inv({ c0, c1 }) {
544
+ const { Fp6 } = this;
545
+ let t = Fp6.inv(Fp6.sub(Fp6.sqr(c0), Fp6.mulByNonresidue(Fp6.sqr(c1)))); // 1 / (c0² - c1² * v)
546
+ return { c0: Fp6.mul(c0, t), c1: Fp6.neg(Fp6.mul(c1, t)) }; // ((C0 * T) * T) + (-C1 * T) * w
547
+ }
548
+ div(lhs, rhs) {
549
+ const { Fp6 } = this;
550
+ const { Fp2 } = Fp6;
551
+ const { Fp } = Fp2;
552
+ return this.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : this.inv(rhs));
553
+ }
554
+ pow(num, power) {
555
+ return mod.FpPow(this, num, power);
556
+ }
557
+ invertBatch(nums) {
558
+ return mod.FpInvertBatch(this, nums);
559
+ }
560
+ // Normalized
561
+ add({ c0, c1 }, { c0: r0, c1: r1 }) {
562
+ const { Fp6 } = this;
563
+ return {
564
+ c0: Fp6.add(c0, r0),
565
+ c1: Fp6.add(c1, r1),
566
+ };
567
+ }
568
+ sub({ c0, c1 }, { c0: r0, c1: r1 }) {
569
+ const { Fp6 } = this;
570
+ return {
571
+ c0: Fp6.sub(c0, r0),
572
+ c1: Fp6.sub(c1, r1),
573
+ };
574
+ }
575
+ mul({ c0, c1 }, rhs) {
576
+ const { Fp6 } = this;
369
577
  if (typeof rhs === 'bigint')
370
578
  return { c0: Fp6.mul(c0, rhs), c1: Fp6.mul(c1, rhs) };
371
579
  let { c0: r0, c1: r1 } = rhs;
@@ -376,131 +584,159 @@ function tower12(opts) {
376
584
  // (c0 + c1) * (r0 + r1) - (T1 + T2)
377
585
  c1: Fp6.sub(Fp6.mul(Fp6.add(c0, c1), Fp6.add(r0, r1)), Fp6.add(t1, t2)),
378
586
  };
379
- };
380
- const Fp12Square = ({ c0, c1 }) => {
587
+ }
588
+ sqr({ c0, c1 }) {
589
+ const { Fp6 } = this;
381
590
  let ab = Fp6.mul(c0, c1); // c0 * c1
382
591
  return {
383
592
  // (c1 * v + c0) * (c0 + c1) - AB - AB * v
384
593
  c0: Fp6.sub(Fp6.sub(Fp6.mul(Fp6.add(Fp6.mulByNonresidue(c1), c0), Fp6.add(c0, c1)), ab), Fp6.mulByNonresidue(ab)),
385
594
  c1: Fp6.add(ab, ab),
386
595
  }; // AB + AB
387
- };
388
- function Fp4Square(a, b) {
389
- const a2 = Fp2.sqr(a);
390
- const b2 = Fp2.sqr(b);
596
+ }
597
+ // NonNormalized stuff
598
+ addN(a, b) {
599
+ return this.add(a, b);
600
+ }
601
+ subN(a, b) {
602
+ return this.sub(a, b);
603
+ }
604
+ mulN(a, b) {
605
+ return this.mul(a, b);
606
+ }
607
+ sqrN(a) {
608
+ return this.sqr(a);
609
+ }
610
+ // Bytes utils
611
+ fromBytes(b) {
612
+ const { Fp6 } = this;
613
+ if (b.length !== this.BYTES)
614
+ throw new Error('fromBytes invalid length=' + b.length);
391
615
  return {
392
- first: Fp2.add(Fp2.mulByNonresidue(b2), a2), // b² * Nonresidue + a²
393
- second: Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b²
616
+ c0: Fp6.fromBytes(b.subarray(0, Fp6.BYTES)),
617
+ c1: Fp6.fromBytes(b.subarray(Fp6.BYTES)),
394
618
  };
395
619
  }
396
- const Fp12 = {
397
- ORDER: Fp2.ORDER, // TODO: unused, but need to verify
398
- isLE: Fp6.isLE,
399
- BITS: 2 * Fp6.BITS,
400
- BYTES: 2 * Fp6.BYTES,
401
- MASK: (0, utils_ts_1.bitMask)(2 * Fp6.BITS),
402
- ZERO: { c0: Fp6.ZERO, c1: Fp6.ZERO },
403
- ONE: { c0: Fp6.ONE, c1: Fp6.ZERO },
404
- create: (num) => num,
405
- isValid: ({ c0, c1 }) => Fp6.isValid(c0) && Fp6.isValid(c1),
406
- is0: ({ c0, c1 }) => Fp6.is0(c0) && Fp6.is0(c1),
407
- isValidNot0: (num) => !Fp12.is0(num) && Fp12.isValid(num),
408
- neg: ({ c0, c1 }) => ({ c0: Fp6.neg(c0), c1: Fp6.neg(c1) }),
409
- eql: ({ c0, c1 }, { c0: r0, c1: r1 }) => Fp6.eql(c0, r0) && Fp6.eql(c1, r1),
410
- sqrt: utils_ts_1.notImplemented,
411
- inv: ({ c0, c1 }) => {
412
- let t = Fp6.inv(Fp6.sub(Fp6.sqr(c0), Fp6.mulByNonresidue(Fp6.sqr(c1)))); // 1 / (c0² - c1² * v)
413
- return { c0: Fp6.mul(c0, t), c1: Fp6.neg(Fp6.mul(c1, t)) }; // ((C0 * T) * T) + (-C1 * T) * w
414
- },
415
- div: (lhs, rhs) => Fp12.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp12.inv(rhs)),
416
- pow: (num, power) => mod.FpPow(Fp12, num, power),
417
- invertBatch: (nums) => mod.FpInvertBatch(Fp12, nums),
418
- // Normalized
419
- add: Fp12Add,
420
- sub: Fp12Subtract,
421
- mul: Fp12Multiply,
422
- sqr: Fp12Square,
423
- // NonNormalized stuff
424
- addN: Fp12Add,
425
- subN: Fp12Subtract,
426
- mulN: Fp12Multiply,
427
- sqrN: Fp12Square,
428
- // Bytes utils
429
- fromBytes: (b) => {
430
- if (b.length !== Fp12.BYTES)
431
- throw new Error('fromBytes invalid length=' + b.length);
432
- return {
433
- c0: Fp6.fromBytes(b.subarray(0, Fp6.BYTES)),
434
- c1: Fp6.fromBytes(b.subarray(Fp6.BYTES)),
435
- };
436
- },
437
- toBytes: ({ c0, c1 }) => (0, utils_ts_1.concatBytes)(Fp6.toBytes(c0), Fp6.toBytes(c1)),
438
- cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({
620
+ toBytes({ c0, c1 }) {
621
+ const { Fp6 } = this;
622
+ return concatBytes(Fp6.toBytes(c0), Fp6.toBytes(c1));
623
+ }
624
+ cmov({ c0, c1 }, { c0: r0, c1: r1 }, c) {
625
+ const { Fp6 } = this;
626
+ return {
439
627
  c0: Fp6.cmov(c0, r0, c),
440
628
  c1: Fp6.cmov(c1, r1, c),
441
- }),
442
- // Utils
443
- // toString() {
444
- // return '' + 'Fp12(' + this.c0 + this.c1 + '* w');
445
- // },
446
- // fromTuple(c: [Fp6, Fp6]) {
447
- // return new Fp12(...c);
448
- // }
449
- fromBigTwelve: (t) => ({
629
+ };
630
+ }
631
+ // Utils
632
+ // toString() {
633
+ // return '' + 'Fp12(' + this.c0 + this.c1 + '* w');
634
+ // },
635
+ // fromTuple(c: [Fp6, Fp6]) {
636
+ // return new Fp12(...c);
637
+ // }
638
+ fromBigTwelve(t) {
639
+ const { Fp6 } = this;
640
+ return {
450
641
  c0: Fp6.fromBigSix(t.slice(0, 6)),
451
642
  c1: Fp6.fromBigSix(t.slice(6, 12)),
452
- }),
453
- // Raises to q**i -th power
454
- frobeniusMap(lhs, power) {
455
- const { c0, c1, c2 } = Fp6.frobeniusMap(lhs.c1, power);
456
- const coeff = FP12_FROBENIUS_COEFFICIENTS[power % 12];
457
- return {
458
- c0: Fp6.frobeniusMap(lhs.c0, power),
459
- c1: Fp6.create({
460
- c0: Fp2.mul(c0, coeff),
461
- c1: Fp2.mul(c1, coeff),
462
- c2: Fp2.mul(c2, coeff),
463
- }),
464
- };
465
- },
466
- mulByFp2: ({ c0, c1 }, rhs) => ({
643
+ };
644
+ }
645
+ // Raises to q**i -th power
646
+ frobeniusMap(lhs, power) {
647
+ const { Fp6 } = this;
648
+ const { Fp2 } = Fp6;
649
+ const { c0, c1, c2 } = Fp6.frobeniusMap(lhs.c1, power);
650
+ const coeff = this.FROBENIUS_COEFFICIENTS[power % 12];
651
+ return {
652
+ c0: Fp6.frobeniusMap(lhs.c0, power),
653
+ c1: Fp6.create({
654
+ c0: Fp2.mul(c0, coeff),
655
+ c1: Fp2.mul(c1, coeff),
656
+ c2: Fp2.mul(c2, coeff),
657
+ }),
658
+ };
659
+ }
660
+ mulByFp2({ c0, c1 }, rhs) {
661
+ const { Fp6 } = this;
662
+ return {
467
663
  c0: Fp6.mulByFp2(c0, rhs),
468
664
  c1: Fp6.mulByFp2(c1, rhs),
469
- }),
470
- conjugate: ({ c0, c1 }) => ({ c0, c1: Fp6.neg(c1) }),
471
- // Sparse multiplication
472
- mul014: ({ c0, c1 }, o0, o1, o4) => {
473
- let t0 = Fp6.mul01(c0, o0, o1);
474
- let t1 = Fp6.mul1(c1, o4);
475
- return {
476
- c0: Fp6.add(Fp6.mulByNonresidue(t1), t0), // T1 * v + T0
477
- // (c1 + c0) * [o0, o1+o4] - T0 - T1
478
- c1: Fp6.sub(Fp6.sub(Fp6.mul01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0), t1),
479
- };
480
- },
481
- mul034: ({ c0, c1 }, o0, o3, o4) => {
482
- const a = Fp6.create({
483
- c0: Fp2.mul(c0.c0, o0),
484
- c1: Fp2.mul(c0.c1, o0),
485
- c2: Fp2.mul(c0.c2, o0),
486
- });
487
- const b = Fp6.mul01(c1, o3, o4);
488
- const e = Fp6.mul01(Fp6.add(c0, c1), Fp2.add(o0, o3), o4);
489
- return {
490
- c0: Fp6.add(Fp6.mulByNonresidue(b), a),
491
- c1: Fp6.sub(e, Fp6.add(a, b)),
492
- };
493
- },
494
- // A cyclotomic group is a subgroup of Fp^n defined by
495
- // GΦₙ(p) = Fpⁿ : α^Φₙ(p) = 1}
496
- // The result of any pairing is in a cyclotomic subgroup
497
- // https://eprint.iacr.org/2009/565.pdf
498
- _cyclotomicSquare: opts.Fp12cyclotomicSquare,
499
- _cyclotomicExp: opts.Fp12cyclotomicExp,
500
- // https://eprint.iacr.org/2010/354.pdf
501
- // https://eprint.iacr.org/2009/565.pdf
502
- finalExponentiate: opts.Fp12finalExponentiate,
503
- };
504
- return { Fp, Fp2, Fp6, Fp12, Fp4Square };
665
+ };
666
+ }
667
+ conjugate({ c0, c1 }) {
668
+ return { c0, c1: this.Fp6.neg(c1) };
669
+ }
670
+ // Sparse multiplication
671
+ mul014({ c0, c1 }, o0, o1, o4) {
672
+ const { Fp6 } = this;
673
+ const { Fp2 } = Fp6;
674
+ let t0 = Fp6.mul01(c0, o0, o1);
675
+ let t1 = Fp6.mul1(c1, o4);
676
+ return {
677
+ c0: Fp6.add(Fp6.mulByNonresidue(t1), t0), // T1 * v + T0
678
+ // (c1 + c0) * [o0, o1+o4] - T0 - T1
679
+ c1: Fp6.sub(Fp6.sub(Fp6.mul01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0), t1),
680
+ };
681
+ }
682
+ mul034({ c0, c1 }, o0, o3, o4) {
683
+ const { Fp6 } = this;
684
+ const { Fp2 } = Fp6;
685
+ const a = Fp6.create({
686
+ c0: Fp2.mul(c0.c0, o0),
687
+ c1: Fp2.mul(c0.c1, o0),
688
+ c2: Fp2.mul(c0.c2, o0),
689
+ });
690
+ const b = Fp6.mul01(c1, o3, o4);
691
+ const e = Fp6.mul01(Fp6.add(c0, c1), Fp2.add(o0, o3), o4);
692
+ return {
693
+ c0: Fp6.add(Fp6.mulByNonresidue(b), a),
694
+ c1: Fp6.sub(e, Fp6.add(a, b)),
695
+ };
696
+ }
697
+ // A cyclotomic group is a subgroup of Fp^n defined by
698
+ // GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1}
699
+ // The result of any pairing is in a cyclotomic subgroup
700
+ // https://eprint.iacr.org/2009/565.pdf
701
+ // https://eprint.iacr.org/2010/354.pdf
702
+ _cyclotomicSquare({ c0, c1 }) {
703
+ const { Fp6 } = this;
704
+ const { Fp2 } = Fp6;
705
+ const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0;
706
+ const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1;
707
+ const { first: t3, second: t4 } = Fp2.Fp4Square(c0c0, c1c1);
708
+ const { first: t5, second: t6 } = Fp2.Fp4Square(c1c0, c0c2);
709
+ const { first: t7, second: t8 } = Fp2.Fp4Square(c0c1, c1c2);
710
+ const t9 = Fp2.mulByNonresidue(t8); // T8 * (u + 1)
711
+ return {
712
+ c0: Fp6.create({
713
+ c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3
714
+ c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5
715
+ c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7),
716
+ }), // 2 * (T7 - c0c2) + T7
717
+ c1: Fp6.create({
718
+ c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9
719
+ c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4
720
+ c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6),
721
+ }),
722
+ }; // 2 * (T6 + c1c2) + T6
723
+ }
724
+ // https://eprint.iacr.org/2009/565.pdf
725
+ _cyclotomicExp(num, n) {
726
+ let z = this.ONE;
727
+ for (let i = this.X_LEN - 1; i >= 0; i--) {
728
+ z = this._cyclotomicSquare(z);
729
+ if (bitGet(n, i))
730
+ z = this.mul(z, num);
731
+ }
732
+ return z;
733
+ }
734
+ }
735
+ export function tower12(opts) {
736
+ const Fp = mod.Field(opts.ORDER);
737
+ const Fp2 = new _Field2(Fp, opts);
738
+ const Fp6 = new _Field6(Fp2);
739
+ const Fp12 = new _Field12(Fp6, opts);
740
+ return { Fp, Fp2, Fp6, Fp12 };
505
741
  }
506
742
  //# sourceMappingURL=tower.js.map