@noble/curves 1.9.5 → 1.9.6

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