@noble/curves 1.4.2 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +159 -128
  2. package/_shortw_utils.d.ts.map +1 -1
  3. package/abstract/bls.d.ts +37 -34
  4. package/abstract/bls.d.ts.map +1 -1
  5. package/abstract/bls.js +167 -115
  6. package/abstract/bls.js.map +1 -1
  7. package/abstract/curve.d.ts +14 -1
  8. package/abstract/curve.d.ts.map +1 -1
  9. package/abstract/curve.js +77 -7
  10. package/abstract/curve.js.map +1 -1
  11. package/abstract/edwards.d.ts +12 -0
  12. package/abstract/edwards.d.ts.map +1 -1
  13. package/abstract/edwards.js +84 -75
  14. package/abstract/edwards.js.map +1 -1
  15. package/abstract/hash-to-curve.d.ts.map +1 -1
  16. package/abstract/hash-to-curve.js +4 -2
  17. package/abstract/hash-to-curve.js.map +1 -1
  18. package/abstract/modular.d.ts +4 -0
  19. package/abstract/modular.d.ts.map +1 -1
  20. package/abstract/modular.js +13 -2
  21. package/abstract/modular.js.map +1 -1
  22. package/abstract/montgomery.d.ts.map +1 -1
  23. package/abstract/montgomery.js +4 -9
  24. package/abstract/montgomery.js.map +1 -1
  25. package/abstract/tower.d.ts +107 -0
  26. package/abstract/tower.d.ts.map +1 -0
  27. package/abstract/tower.js +498 -0
  28. package/abstract/tower.js.map +1 -0
  29. package/abstract/utils.d.ts +17 -0
  30. package/abstract/utils.d.ts.map +1 -1
  31. package/abstract/utils.js +50 -1
  32. package/abstract/utils.js.map +1 -1
  33. package/abstract/weierstrass.d.ts +25 -3
  34. package/abstract/weierstrass.d.ts.map +1 -1
  35. package/abstract/weierstrass.js +189 -113
  36. package/abstract/weierstrass.js.map +1 -1
  37. package/bls12-381.d.ts +1 -65
  38. package/bls12-381.d.ts.map +1 -1
  39. package/bls12-381.js +48 -575
  40. package/bls12-381.js.map +1 -1
  41. package/bn254.d.ts +10 -6
  42. package/bn254.d.ts.map +1 -1
  43. package/bn254.js +207 -10
  44. package/bn254.js.map +1 -1
  45. package/ed25519.d.ts +7 -4
  46. package/ed25519.d.ts.map +1 -1
  47. package/ed25519.js +3 -0
  48. package/ed25519.js.map +1 -1
  49. package/esm/_shortw_utils.d.ts.map +1 -1
  50. package/esm/abstract/bls.d.ts +37 -34
  51. package/esm/abstract/bls.d.ts.map +1 -1
  52. package/esm/abstract/bls.js +168 -116
  53. package/esm/abstract/bls.js.map +1 -1
  54. package/esm/abstract/curve.d.ts +14 -1
  55. package/esm/abstract/curve.d.ts.map +1 -1
  56. package/esm/abstract/curve.js +77 -8
  57. package/esm/abstract/curve.js.map +1 -1
  58. package/esm/abstract/edwards.d.ts +12 -0
  59. package/esm/abstract/edwards.d.ts.map +1 -1
  60. package/esm/abstract/edwards.js +87 -78
  61. package/esm/abstract/edwards.js.map +1 -1
  62. package/esm/abstract/hash-to-curve.d.ts.map +1 -1
  63. package/esm/abstract/hash-to-curve.js +4 -2
  64. package/esm/abstract/hash-to-curve.js.map +1 -1
  65. package/esm/abstract/modular.d.ts +4 -0
  66. package/esm/abstract/modular.d.ts.map +1 -1
  67. package/esm/abstract/modular.js +12 -2
  68. package/esm/abstract/modular.js.map +1 -1
  69. package/esm/abstract/montgomery.d.ts.map +1 -1
  70. package/esm/abstract/montgomery.js +5 -10
  71. package/esm/abstract/montgomery.js.map +1 -1
  72. package/esm/abstract/tower.d.ts +107 -0
  73. package/esm/abstract/tower.d.ts.map +1 -0
  74. package/esm/abstract/tower.js +494 -0
  75. package/esm/abstract/tower.js.map +1 -0
  76. package/esm/abstract/utils.d.ts +17 -0
  77. package/esm/abstract/utils.d.ts.map +1 -1
  78. package/esm/abstract/utils.js +44 -0
  79. package/esm/abstract/utils.js.map +1 -1
  80. package/esm/abstract/weierstrass.d.ts +25 -3
  81. package/esm/abstract/weierstrass.d.ts.map +1 -1
  82. package/esm/abstract/weierstrass.js +191 -115
  83. package/esm/abstract/weierstrass.js.map +1 -1
  84. package/esm/bls12-381.d.ts +1 -65
  85. package/esm/bls12-381.d.ts.map +1 -1
  86. package/esm/bls12-381.js +50 -577
  87. package/esm/bls12-381.js.map +1 -1
  88. package/esm/bn254.d.ts +10 -6
  89. package/esm/bn254.d.ts.map +1 -1
  90. package/esm/bn254.js +206 -9
  91. package/esm/bn254.js.map +1 -1
  92. package/esm/ed25519.d.ts +7 -4
  93. package/esm/ed25519.d.ts.map +1 -1
  94. package/esm/ed25519.js +3 -0
  95. package/esm/ed25519.js.map +1 -1
  96. package/esm/jubjub.d.ts.map +1 -1
  97. package/esm/jubjub.js +8 -2
  98. package/esm/jubjub.js.map +1 -1
  99. package/esm/p256.d.ts.map +1 -1
  100. package/esm/p384.d.ts.map +1 -1
  101. package/esm/p521.d.ts.map +1 -1
  102. package/esm/secp256k1.d.ts +6 -0
  103. package/esm/secp256k1.d.ts.map +1 -1
  104. package/esm/secp256k1.js +17 -13
  105. package/esm/secp256k1.js.map +1 -1
  106. package/jubjub.d.ts.map +1 -1
  107. package/jubjub.js +8 -2
  108. package/jubjub.js.map +1 -1
  109. package/p256.d.ts.map +1 -1
  110. package/p384.d.ts.map +1 -1
  111. package/p521.d.ts.map +1 -1
  112. package/package.json +27 -19
  113. package/secp256k1.d.ts +6 -0
  114. package/secp256k1.d.ts.map +1 -1
  115. package/secp256k1.js +16 -12
  116. package/secp256k1.js.map +1 -1
  117. package/src/abstract/bls.ts +222 -168
  118. package/src/abstract/curve.ts +80 -8
  119. package/src/abstract/edwards.ts +97 -70
  120. package/src/abstract/hash-to-curve.ts +3 -1
  121. package/src/abstract/modular.ts +13 -3
  122. package/src/abstract/montgomery.ts +11 -10
  123. package/src/abstract/tower.ts +605 -0
  124. package/src/abstract/utils.ts +49 -0
  125. package/src/abstract/weierstrass.ts +179 -104
  126. package/src/bls12-381.ts +53 -707
  127. package/src/bn254.ts +224 -9
  128. package/src/ed25519.ts +5 -2
  129. package/src/jubjub.ts +7 -2
  130. package/src/secp256k1.ts +24 -12
package/esm/bls12-381.js CHANGED
@@ -3,10 +3,11 @@ import { sha256 } from '@noble/hashes/sha256';
3
3
  import { randomBytes } from '@noble/hashes/utils';
4
4
  import { bls } from './abstract/bls.js';
5
5
  import * as mod from './abstract/modular.js';
6
- import { bitGet, bitLen, bitMask, bytesToHex, bytesToNumberBE, concatBytes as concatB, ensureBytes, numberToBytesBE, } from './abstract/utils.js';
6
+ import { bitGet, bitLen, bytesToHex, bytesToNumberBE, concatBytes as concatB, ensureBytes, numberToBytesBE, } from './abstract/utils.js';
7
7
  // Types
8
8
  import { isogenyMap } from './abstract/hash-to-curve.js';
9
- import { mapToCurveSimpleSWU, } from './abstract/weierstrass.js';
9
+ import { mapToCurveSimpleSWU } from './abstract/weierstrass.js';
10
+ import { tower12, psiFrobenius } from './abstract/tower.js';
10
11
  /*
11
12
  bls12-381 is pairing-friendly Barreto-Lynn-Scott elliptic curve construction allowing to:
12
13
  - Construct zk-SNARKs at the 120-bit security
@@ -42,511 +43,51 @@ bls12-381 is pairing-friendly Barreto-Lynn-Scott elliptic curve construction all
42
43
  // Be friendly to bad ECMAScript parsers by not using bigint literals
43
44
  // prettier-ignore
44
45
  const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);
45
- // prettier-ignore
46
- const _8n = BigInt(8), _16n = BigInt(16);
46
+ /*
47
+ Embedding degree (k): 12
48
+ Seed (X): -15132376222941642752
49
+ Fr: (x⁴-x²+1)
50
+ Fp: ((x-1)² ⋅ r(x)/3+x)
51
+ (E/Fp): Y²=X³+4
52
+ (Eₜ/Fp²): Y² = X³+4(u+1) (M-type twist)
53
+ Ate loop size: X
54
+
55
+ Towers:
56
+ - Fp²[u] = Fp/u²+1
57
+ - Fp⁶[v] = Fp²/v³-1-u
58
+ - Fp¹²[w] = Fp⁶/w²-v
59
+
60
+
61
+ TODO: BLS & BN Fp/Fr can be constructed from seed.
62
+ */
63
+ // The BLS parameter x (seed) for BLS12-381. NOTE: it is negative!
64
+ const BLS_X = BigInt('0xd201000000010000');
65
+ const BLS_X_LEN = bitLen(BLS_X);
47
66
  // CURVE FIELDS
48
- // Finite field over p.
49
- const Fp_raw = BigInt('0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab');
50
- const Fp = mod.Field(Fp_raw);
51
- // Finite field over r.
52
- // This particular field is not used anywhere in bls12-381, but it is still useful.
53
- const Fr = mod.Field(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001'));
54
- const Fp2Add = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({
55
- c0: Fp.add(c0, r0),
56
- c1: Fp.add(c1, r1),
57
- });
58
- const Fp2Subtract = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({
59
- c0: Fp.sub(c0, r0),
60
- c1: Fp.sub(c1, r1),
61
- });
62
- const Fp2Multiply = ({ c0, c1 }, rhs) => {
63
- if (typeof rhs === 'bigint')
64
- return { c0: Fp.mul(c0, rhs), c1: Fp.mul(c1, rhs) };
65
- // (a+bi)(c+di) = (ac−bd) + (ad+bc)i
66
- const { c0: r0, c1: r1 } = rhs;
67
- let t1 = Fp.mul(c0, r0); // c0 * o0
68
- let t2 = Fp.mul(c1, r1); // c1 * o1
69
- // (T1 - T2) + ((c0 + c1) * (r0 + r1) - (T1 + T2))*i
70
- const o0 = Fp.sub(t1, t2);
71
- const o1 = Fp.sub(Fp.mul(Fp.add(c0, c1), Fp.add(r0, r1)), Fp.add(t1, t2));
72
- return { c0: o0, c1: o1 };
73
- };
74
- const Fp2Square = ({ c0, c1 }) => {
75
- const a = Fp.add(c0, c1);
76
- const b = Fp.sub(c0, c1);
77
- const c = Fp.add(c0, c0);
78
- return { c0: Fp.mul(a, b), c1: Fp.mul(c, c1) };
79
- };
80
- // G2 is the order-q subgroup of E2(Fp²) : y² = x³+4(1+√−1),
81
- // where Fp2 is Fp[√−1]/(x2+1). #E2(Fp2 ) = h2q, where
82
- // G² - 1
83
- // h2q
84
- // NOTE: ORDER was wrong!
85
- const FP2_ORDER = Fp_raw * Fp_raw;
86
- const Fp2 = {
87
- ORDER: FP2_ORDER,
88
- BITS: bitLen(FP2_ORDER),
89
- BYTES: Math.ceil(bitLen(FP2_ORDER) / 8),
90
- MASK: bitMask(bitLen(FP2_ORDER)),
91
- ZERO: { c0: Fp.ZERO, c1: Fp.ZERO },
92
- ONE: { c0: Fp.ONE, c1: Fp.ZERO },
93
- create: (num) => num,
94
- isValid: ({ c0, c1 }) => typeof c0 === 'bigint' && typeof c1 === 'bigint',
95
- is0: ({ c0, c1 }) => Fp.is0(c0) && Fp.is0(c1),
96
- eql: ({ c0, c1 }, { c0: r0, c1: r1 }) => Fp.eql(c0, r0) && Fp.eql(c1, r1),
97
- neg: ({ c0, c1 }) => ({ c0: Fp.neg(c0), c1: Fp.neg(c1) }),
98
- pow: (num, power) => mod.FpPow(Fp2, num, power),
99
- invertBatch: (nums) => mod.FpInvertBatch(Fp2, nums),
100
- // Normalized
101
- add: Fp2Add,
102
- sub: Fp2Subtract,
103
- mul: Fp2Multiply,
104
- sqr: Fp2Square,
105
- // NonNormalized stuff
106
- addN: Fp2Add,
107
- subN: Fp2Subtract,
108
- mulN: Fp2Multiply,
109
- sqrN: Fp2Square,
110
- // Why inversion for bigint inside Fp instead of Fp2? it is even used in that context?
111
- div: (lhs, rhs) => Fp2.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp2.inv(rhs)),
112
- inv: ({ c0: a, c1: b }) => {
113
- // We wish to find the multiplicative inverse of a nonzero
114
- // element a + bu in Fp2. We leverage an identity
115
- //
116
- // (a + bu)(a - bu) = a² + b²
117
- //
118
- // which holds because u² = -1. This can be rewritten as
119
- //
120
- // (a + bu)(a - bu)/(a² + b²) = 1
121
- //
122
- // because a² + b² = 0 has no nonzero solutions for (a, b).
123
- // This gives that (a - bu)/(a² + b²) is the inverse
124
- // of (a + bu). Importantly, this can be computing using
125
- // only a single inversion in Fp.
126
- const factor = Fp.inv(Fp.create(a * a + b * b));
127
- return { c0: Fp.mul(factor, Fp.create(a)), c1: Fp.mul(factor, Fp.create(-b)) };
128
- },
129
- sqrt: (num) => {
130
- if (Fp2.eql(num, Fp2.ZERO))
131
- return Fp2.ZERO; // Algo doesn't handles this case
132
- // TODO: Optimize this line. It's extremely slow.
133
- // Speeding this up would boost aggregateSignatures.
134
- // https://eprint.iacr.org/2012/685.pdf applicable?
135
- // https://github.com/zkcrypto/bls12_381/blob/080eaa74ec0e394377caa1ba302c8c121df08b07/src/fp2.rs#L250
136
- // https://github.com/supranational/blst/blob/aae0c7d70b799ac269ff5edf29d8191dbd357876/src/exp2.c#L1
137
- // Inspired by https://github.com/dalek-cryptography/curve25519-dalek/blob/17698df9d4c834204f83a3574143abacb4fc81a5/src/field.rs#L99
138
- const candidateSqrt = Fp2.pow(num, (Fp2.ORDER + _8n) / _16n);
139
- const check = Fp2.div(Fp2.sqr(candidateSqrt), num); // candidateSqrt.square().div(this);
140
- const R = FP2_ROOTS_OF_UNITY;
141
- const divisor = [R[0], R[2], R[4], R[6]].find((r) => Fp2.eql(r, check));
142
- if (!divisor)
143
- throw new Error('No root');
144
- const index = R.indexOf(divisor);
145
- const root = R[index / 2];
146
- if (!root)
147
- throw new Error('Invalid root');
148
- const x1 = Fp2.div(candidateSqrt, root);
149
- const x2 = Fp2.neg(x1);
150
- const { re: re1, im: im1 } = Fp2.reim(x1);
151
- const { re: re2, im: im2 } = Fp2.reim(x2);
152
- if (im1 > im2 || (im1 === im2 && re1 > re2))
153
- return x1;
154
- return x2;
155
- },
156
- // Same as sgn0_m_eq_2 in RFC 9380
157
- isOdd: (x) => {
158
- const { re: x0, im: x1 } = Fp2.reim(x);
159
- const sign_0 = x0 % _2n;
160
- const zero_0 = x0 === _0n;
161
- const sign_1 = x1 % _2n;
162
- return BigInt(sign_0 || (zero_0 && sign_1)) == _1n;
163
- },
164
- // Bytes util
165
- fromBytes(b) {
166
- if (b.length !== Fp2.BYTES)
167
- throw new Error(`fromBytes wrong length=${b.length}`);
168
- return { c0: Fp.fromBytes(b.subarray(0, Fp.BYTES)), c1: Fp.fromBytes(b.subarray(Fp.BYTES)) };
169
- },
170
- toBytes: ({ c0, c1 }) => concatB(Fp.toBytes(c0), Fp.toBytes(c1)),
171
- cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({
172
- c0: Fp.cmov(c0, r0, c),
173
- c1: Fp.cmov(c1, r1, c),
174
- }),
175
- // Specific utils
176
- // toString() {
177
- // return `Fp2(${this.c0} + ${this.c1}×i)`;
178
- // }
179
- reim: ({ c0, c1 }) => ({ re: c0, im: c1 }),
180
- // multiply by u + 1
181
- mulByNonresidue: ({ c0, c1 }) => ({ c0: Fp.sub(c0, c1), c1: Fp.add(c0, c1) }),
182
- multiplyByB: ({ c0, c1 }) => {
183
- let t0 = Fp.mul(c0, _4n); // 4 * c0
184
- let t1 = Fp.mul(c1, _4n); // 4 * c1
67
+ const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = tower12({
68
+ // Order of Fp
69
+ ORDER: BigInt('0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab'),
70
+ // Finite extension field over irreducible polynominal.
71
+ // Fp(u) / (u² - β) where β = -1
72
+ FP2_NONRESIDUE: [_1n, _1n],
73
+ Fp2mulByB: ({ c0, c1 }) => {
74
+ const t0 = Fp.mul(c0, _4n); // 4 * c0
75
+ const t1 = Fp.mul(c1, _4n); // 4 * c1
185
76
  // (T0-T1) + (T0+T1)*i
186
77
  return { c0: Fp.sub(t0, t1), c1: Fp.add(t0, t1) };
187
78
  },
188
- fromBigTuple: (tuple) => {
189
- if (tuple.length !== 2)
190
- throw new Error('Invalid tuple');
191
- const fps = tuple.map((n) => Fp.create(n));
192
- return { c0: fps[0], c1: fps[1] };
193
- },
194
- frobeniusMap: ({ c0, c1 }, power) => ({
195
- c0,
196
- c1: Fp.mul(c1, FP2_FROBENIUS_COEFFICIENTS[power % 2]),
197
- }),
198
- };
199
- // Finite extension field over irreducible polynominal.
200
- // Fp(u) / (u² - β) where β = -1
201
- const FP2_FROBENIUS_COEFFICIENTS = [
202
- BigInt('0x1'),
203
- BigInt('0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa'),
204
- ].map((item) => Fp.create(item));
205
- // For Fp2 roots of unity.
206
- const rv1 = BigInt('0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09');
207
- // const ev1 =
208
- // BigInt('0x699be3b8c6870965e5bf892ad5d2cc7b0e85a117402dfd83b7f4a947e02d978498255a2aaec0ac627b5afbdf1bf1c90');
209
- // const ev2 =
210
- // BigInt('0x8157cd83046453f5dd0972b6e3949e4288020b5b8a9cc99ca07e27089a2ce2436d965026adad3ef7baba37f2183e9b5');
211
- // const ev3 =
212
- // BigInt('0xab1c2ffdd6c253ca155231eb3e71ba044fd562f6f72bc5bad5ec46a0b7a3b0247cf08ce6c6317f40edbc653a72dee17');
213
- // const ev4 =
214
- // BigInt('0xaa404866706722864480885d68ad0ccac1967c7544b447873cc37e0181271e006df72162a3d3e0287bf597fbf7f8fc1');
215
- // Eighth roots of unity, used for computing square roots in Fp2.
216
- // To verify or re-calculate:
217
- // Array(8).fill(new Fp2([1n, 1n])).map((fp2, k) => fp2.pow(Fp2.ORDER * BigInt(k) / 8n))
218
- const FP2_ROOTS_OF_UNITY = [
219
- [_1n, _0n],
220
- [rv1, -rv1],
221
- [_0n, _1n],
222
- [rv1, rv1],
223
- [-_1n, _0n],
224
- [-rv1, rv1],
225
- [_0n, -_1n],
226
- [-rv1, -rv1],
227
- ].map((pair) => Fp2.fromBigTuple(pair));
228
- const Fp6Add = ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => ({
229
- c0: Fp2.add(c0, r0),
230
- c1: Fp2.add(c1, r1),
231
- c2: Fp2.add(c2, r2),
232
- });
233
- const Fp6Subtract = ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => ({
234
- c0: Fp2.sub(c0, r0),
235
- c1: Fp2.sub(c1, r1),
236
- c2: Fp2.sub(c2, r2),
237
- });
238
- const Fp6Multiply = ({ c0, c1, c2 }, rhs) => {
239
- if (typeof rhs === 'bigint') {
240
- return {
241
- c0: Fp2.mul(c0, rhs),
242
- c1: Fp2.mul(c1, rhs),
243
- c2: Fp2.mul(c2, rhs),
244
- };
245
- }
246
- const { c0: r0, c1: r1, c2: r2 } = rhs;
247
- const t0 = Fp2.mul(c0, r0); // c0 * o0
248
- const t1 = Fp2.mul(c1, r1); // c1 * o1
249
- const t2 = Fp2.mul(c2, r2); // c2 * o2
250
- return {
251
- // t0 + (c1 + c2) * (r1 * r2) - (T1 + T2) * (u + 1)
252
- c0: Fp2.add(t0, Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), Fp2.add(r1, r2)), Fp2.add(t1, t2)))),
253
- // (c0 + c1) * (r0 + r1) - (T0 + T1) + T2 * (u + 1)
254
- c1: Fp2.add(Fp2.sub(Fp2.mul(Fp2.add(c0, c1), Fp2.add(r0, r1)), Fp2.add(t0, t1)), Fp2.mulByNonresidue(t2)),
255
- // T1 + (c0 + c2) * (r0 + r2) - T0 + T2
256
- c2: Fp2.sub(Fp2.add(t1, Fp2.mul(Fp2.add(c0, c2), Fp2.add(r0, r2))), Fp2.add(t0, t2)),
257
- };
258
- };
259
- const Fp6Square = ({ c0, c1, c2 }) => {
260
- let t0 = Fp2.sqr(c0); // c0²
261
- let t1 = Fp2.mul(Fp2.mul(c0, c1), _2n); // 2 * c0 * c1
262
- let t3 = Fp2.mul(Fp2.mul(c1, c2), _2n); // 2 * c1 * c2
263
- let t4 = Fp2.sqr(c2); // c2²
264
- return {
265
- c0: Fp2.add(Fp2.mulByNonresidue(t3), t0), // T3 * (u + 1) + T0
266
- c1: Fp2.add(Fp2.mulByNonresidue(t4), t1), // T4 * (u + 1) + T1
267
- // T1 + (c0 - c1 + c2)² + T3 - T0 - T4
268
- c2: Fp2.sub(Fp2.sub(Fp2.add(Fp2.add(t1, Fp2.sqr(Fp2.add(Fp2.sub(c0, c1), c2))), t3), t0), t4),
269
- };
270
- };
271
- const Fp6 = {
272
- ORDER: Fp2.ORDER, // TODO: unused, but need to verify
273
- BITS: 3 * Fp2.BITS,
274
- BYTES: 3 * Fp2.BYTES,
275
- MASK: bitMask(3 * Fp2.BITS),
276
- ZERO: { c0: Fp2.ZERO, c1: Fp2.ZERO, c2: Fp2.ZERO },
277
- ONE: { c0: Fp2.ONE, c1: Fp2.ZERO, c2: Fp2.ZERO },
278
- create: (num) => num,
279
- isValid: ({ c0, c1, c2 }) => Fp2.isValid(c0) && Fp2.isValid(c1) && Fp2.isValid(c2),
280
- is0: ({ c0, c1, c2 }) => Fp2.is0(c0) && Fp2.is0(c1) && Fp2.is0(c2),
281
- neg: ({ c0, c1, c2 }) => ({ c0: Fp2.neg(c0), c1: Fp2.neg(c1), c2: Fp2.neg(c2) }),
282
- eql: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => Fp2.eql(c0, r0) && Fp2.eql(c1, r1) && Fp2.eql(c2, r2),
283
- sqrt: () => {
284
- throw new Error('Not implemented');
285
- },
286
- // Do we need division by bigint at all? Should be done via order:
287
- div: (lhs, rhs) => Fp6.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp6.inv(rhs)),
288
- pow: (num, power) => mod.FpPow(Fp6, num, power),
289
- invertBatch: (nums) => mod.FpInvertBatch(Fp6, nums),
290
- // Normalized
291
- add: Fp6Add,
292
- sub: Fp6Subtract,
293
- mul: Fp6Multiply,
294
- sqr: Fp6Square,
295
- // NonNormalized stuff
296
- addN: Fp6Add,
297
- subN: Fp6Subtract,
298
- mulN: Fp6Multiply,
299
- sqrN: Fp6Square,
300
- inv: ({ c0, c1, c2 }) => {
301
- let t0 = Fp2.sub(Fp2.sqr(c0), Fp2.mulByNonresidue(Fp2.mul(c2, c1))); // c0² - c2 * c1 * (u + 1)
302
- let t1 = Fp2.sub(Fp2.mulByNonresidue(Fp2.sqr(c2)), Fp2.mul(c0, c1)); // c2² * (u + 1) - c0 * c1
303
- let t2 = Fp2.sub(Fp2.sqr(c1), Fp2.mul(c0, c2)); // c1² - c0 * c2
304
- // 1/(((c2 * T1 + c1 * T2) * v) + c0 * T0)
305
- let t4 = Fp2.inv(Fp2.add(Fp2.mulByNonresidue(Fp2.add(Fp2.mul(c2, t1), Fp2.mul(c1, t2))), Fp2.mul(c0, t0)));
306
- return { c0: Fp2.mul(t4, t0), c1: Fp2.mul(t4, t1), c2: Fp2.mul(t4, t2) };
307
- },
308
- // Bytes utils
309
- fromBytes: (b) => {
310
- if (b.length !== Fp6.BYTES)
311
- throw new Error(`fromBytes wrong length=${b.length}`);
312
- return {
313
- c0: Fp2.fromBytes(b.subarray(0, Fp2.BYTES)),
314
- c1: Fp2.fromBytes(b.subarray(Fp2.BYTES, 2 * Fp2.BYTES)),
315
- c2: Fp2.fromBytes(b.subarray(2 * Fp2.BYTES)),
316
- };
317
- },
318
- toBytes: ({ c0, c1, c2 }) => concatB(Fp2.toBytes(c0), Fp2.toBytes(c1), Fp2.toBytes(c2)),
319
- cmov: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }, c) => ({
320
- c0: Fp2.cmov(c0, r0, c),
321
- c1: Fp2.cmov(c1, r1, c),
322
- c2: Fp2.cmov(c2, r2, c),
323
- }),
324
- // Utils
325
- // fromTriple(triple: [Fp2, Fp2, Fp2]) {
326
- // return new Fp6(...triple);
327
- // }
328
- // toString() {
329
- // return `Fp6(${this.c0} + ${this.c1} * v, ${this.c2} * v^2)`;
330
- // }
331
- fromBigSix: (t) => {
332
- if (!Array.isArray(t) || t.length !== 6)
333
- throw new Error('Invalid Fp6 usage');
334
- return {
335
- c0: Fp2.fromBigTuple(t.slice(0, 2)),
336
- c1: Fp2.fromBigTuple(t.slice(2, 4)),
337
- c2: Fp2.fromBigTuple(t.slice(4, 6)),
338
- };
339
- },
340
- frobeniusMap: ({ c0, c1, c2 }, power) => ({
341
- c0: Fp2.frobeniusMap(c0, power),
342
- c1: Fp2.mul(Fp2.frobeniusMap(c1, power), FP6_FROBENIUS_COEFFICIENTS_1[power % 6]),
343
- c2: Fp2.mul(Fp2.frobeniusMap(c2, power), FP6_FROBENIUS_COEFFICIENTS_2[power % 6]),
344
- }),
345
- mulByNonresidue: ({ c0, c1, c2 }) => ({ c0: Fp2.mulByNonresidue(c2), c1: c0, c2: c1 }),
346
- // Sparse multiplication
347
- multiplyBy1: ({ c0, c1, c2 }, b1) => ({
348
- c0: Fp2.mulByNonresidue(Fp2.mul(c2, b1)),
349
- c1: Fp2.mul(c0, b1),
350
- c2: Fp2.mul(c1, b1),
351
- }),
352
- // Sparse multiplication
353
- multiplyBy01({ c0, c1, c2 }, b0, b1) {
354
- let t0 = Fp2.mul(c0, b0); // c0 * b0
355
- let t1 = Fp2.mul(c1, b1); // c1 * b1
356
- return {
357
- // ((c1 + c2) * b1 - T1) * (u + 1) + T0
358
- c0: Fp2.add(Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), b1), t1)), t0),
359
- // (b0 + b1) * (c0 + c1) - T0 - T1
360
- c1: Fp2.sub(Fp2.sub(Fp2.mul(Fp2.add(b0, b1), Fp2.add(c0, c1)), t0), t1),
361
- // (c0 + c2) * b0 - T0 + T1
362
- c2: Fp2.add(Fp2.sub(Fp2.mul(Fp2.add(c0, c2), b0), t0), t1),
363
- };
364
- },
365
- multiplyByFp2: ({ c0, c1, c2 }, rhs) => ({
366
- c0: Fp2.mul(c0, rhs),
367
- c1: Fp2.mul(c1, rhs),
368
- c2: Fp2.mul(c2, rhs),
369
- }),
370
- };
371
- const FP6_FROBENIUS_COEFFICIENTS_1 = [
372
- [BigInt('0x1'), BigInt('0x0')],
373
- [
374
- BigInt('0x0'),
375
- BigInt('0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac'),
376
- ],
377
- [
378
- BigInt('0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe'),
379
- BigInt('0x0'),
380
- ],
381
- [BigInt('0x0'), BigInt('0x1')],
382
- [
383
- BigInt('0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac'),
384
- BigInt('0x0'),
385
- ],
386
- [
387
- BigInt('0x0'),
388
- BigInt('0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe'),
389
- ],
390
- ].map((pair) => Fp2.fromBigTuple(pair));
391
- const FP6_FROBENIUS_COEFFICIENTS_2 = [
392
- [BigInt('0x1'), BigInt('0x0')],
393
- [
394
- BigInt('0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaad'),
395
- BigInt('0x0'),
396
- ],
397
- [
398
- BigInt('0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac'),
399
- BigInt('0x0'),
400
- ],
401
- [
402
- BigInt('0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa'),
403
- BigInt('0x0'),
404
- ],
405
- [
406
- BigInt('0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe'),
407
- BigInt('0x0'),
408
- ],
409
- [
410
- BigInt('0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffeffff'),
411
- BigInt('0x0'),
412
- ],
413
- ].map((pair) => Fp2.fromBigTuple(pair));
414
- // The BLS parameter x for BLS12-381
415
- const BLS_X = BigInt('0xd201000000010000');
416
- const BLS_X_LEN = bitLen(BLS_X);
417
- const Fp12Add = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({
418
- c0: Fp6.add(c0, r0),
419
- c1: Fp6.add(c1, r1),
420
- });
421
- const Fp12Subtract = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({
422
- c0: Fp6.sub(c0, r0),
423
- c1: Fp6.sub(c1, r1),
424
- });
425
- const Fp12Multiply = ({ c0, c1 }, rhs) => {
426
- if (typeof rhs === 'bigint')
427
- return { c0: Fp6.mul(c0, rhs), c1: Fp6.mul(c1, rhs) };
428
- let { c0: r0, c1: r1 } = rhs;
429
- let t1 = Fp6.mul(c0, r0); // c0 * r0
430
- let t2 = Fp6.mul(c1, r1); // c1 * r1
431
- return {
432
- c0: Fp6.add(t1, Fp6.mulByNonresidue(t2)), // T1 + T2 * v
433
- // (c0 + c1) * (r0 + r1) - (T1 + T2)
434
- c1: Fp6.sub(Fp6.mul(Fp6.add(c0, c1), Fp6.add(r0, r1)), Fp6.add(t1, t2)),
435
- };
436
- };
437
- const Fp12Square = ({ c0, c1 }) => {
438
- let ab = Fp6.mul(c0, c1); // c0 * c1
439
- return {
440
- // (c1 * v + c0) * (c0 + c1) - AB - AB * v
441
- c0: Fp6.sub(Fp6.sub(Fp6.mul(Fp6.add(Fp6.mulByNonresidue(c1), c0), Fp6.add(c0, c1)), ab), Fp6.mulByNonresidue(ab)),
442
- c1: Fp6.add(ab, ab),
443
- }; // AB + AB
444
- };
445
- function Fp4Square(a, b) {
446
- const a2 = Fp2.sqr(a);
447
- const b2 = Fp2.sqr(b);
448
- return {
449
- first: Fp2.add(Fp2.mulByNonresidue(b2), a2), // b² * Nonresidue + a²
450
- second: Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b²
451
- };
452
- }
453
- const Fp12 = {
454
- ORDER: Fp2.ORDER, // TODO: unused, but need to verify
455
- BITS: 2 * Fp2.BITS,
456
- BYTES: 2 * Fp2.BYTES,
457
- MASK: bitMask(2 * Fp2.BITS),
458
- ZERO: { c0: Fp6.ZERO, c1: Fp6.ZERO },
459
- ONE: { c0: Fp6.ONE, c1: Fp6.ZERO },
460
- create: (num) => num,
461
- isValid: ({ c0, c1 }) => Fp6.isValid(c0) && Fp6.isValid(c1),
462
- is0: ({ c0, c1 }) => Fp6.is0(c0) && Fp6.is0(c1),
463
- neg: ({ c0, c1 }) => ({ c0: Fp6.neg(c0), c1: Fp6.neg(c1) }),
464
- eql: ({ c0, c1 }, { c0: r0, c1: r1 }) => Fp6.eql(c0, r0) && Fp6.eql(c1, r1),
465
- sqrt: () => {
466
- throw new Error('Not implemented');
467
- },
468
- inv: ({ c0, c1 }) => {
469
- let t = Fp6.inv(Fp6.sub(Fp6.sqr(c0), Fp6.mulByNonresidue(Fp6.sqr(c1)))); // 1 / (c0² - c1² * v)
470
- return { c0: Fp6.mul(c0, t), c1: Fp6.neg(Fp6.mul(c1, t)) }; // ((C0 * T) * T) + (-C1 * T) * w
471
- },
472
- div: (lhs, rhs) => Fp12.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp12.inv(rhs)),
473
- pow: (num, power) => mod.FpPow(Fp12, num, power),
474
- invertBatch: (nums) => mod.FpInvertBatch(Fp12, nums),
475
- // Normalized
476
- add: Fp12Add,
477
- sub: Fp12Subtract,
478
- mul: Fp12Multiply,
479
- sqr: Fp12Square,
480
- // NonNormalized stuff
481
- addN: Fp12Add,
482
- subN: Fp12Subtract,
483
- mulN: Fp12Multiply,
484
- sqrN: Fp12Square,
485
- // Bytes utils
486
- fromBytes: (b) => {
487
- if (b.length !== Fp12.BYTES)
488
- throw new Error(`fromBytes wrong length=${b.length}`);
489
- return {
490
- c0: Fp6.fromBytes(b.subarray(0, Fp6.BYTES)),
491
- c1: Fp6.fromBytes(b.subarray(Fp6.BYTES)),
492
- };
493
- },
494
- toBytes: ({ c0, c1 }) => concatB(Fp6.toBytes(c0), Fp6.toBytes(c1)),
495
- cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({
496
- c0: Fp6.cmov(c0, r0, c),
497
- c1: Fp6.cmov(c1, r1, c),
498
- }),
499
- // Utils
500
- // toString() {
501
- // return `Fp12(${this.c0} + ${this.c1} * w)`;
502
- // },
503
- // fromTuple(c: [Fp6, Fp6]) {
504
- // return new Fp12(...c);
505
- // }
506
- fromBigTwelve: (t) => ({
507
- c0: Fp6.fromBigSix(t.slice(0, 6)),
508
- c1: Fp6.fromBigSix(t.slice(6, 12)),
509
- }),
510
- // Raises to q**i -th power
511
- frobeniusMap(lhs, power) {
512
- const r0 = Fp6.frobeniusMap(lhs.c0, power);
513
- const { c0, c1, c2 } = Fp6.frobeniusMap(lhs.c1, power);
514
- const coeff = FP12_FROBENIUS_COEFFICIENTS[power % 12];
515
- return {
516
- c0: r0,
517
- c1: Fp6.create({
518
- c0: Fp2.mul(c0, coeff),
519
- c1: Fp2.mul(c1, coeff),
520
- c2: Fp2.mul(c2, coeff),
521
- }),
522
- };
523
- },
524
- // Sparse multiplication
525
- multiplyBy014: ({ c0, c1 }, o0, o1, o4) => {
526
- let t0 = Fp6.multiplyBy01(c0, o0, o1);
527
- let t1 = Fp6.multiplyBy1(c1, o4);
528
- return {
529
- c0: Fp6.add(Fp6.mulByNonresidue(t1), t0), // T1 * v + T0
530
- // (c1 + c0) * [o0, o1+o4] - T0 - T1
531
- c1: Fp6.sub(Fp6.sub(Fp6.multiplyBy01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0), t1),
532
- };
533
- },
534
- multiplyByFp2: ({ c0, c1 }, rhs) => ({
535
- c0: Fp6.multiplyByFp2(c0, rhs),
536
- c1: Fp6.multiplyByFp2(c1, rhs),
537
- }),
538
- conjugate: ({ c0, c1 }) => ({ c0, c1: Fp6.neg(c1) }),
79
+ // Fp12
539
80
  // A cyclotomic group is a subgroup of Fp^n defined by
540
81
  // GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1}
541
82
  // The result of any pairing is in a cyclotomic subgroup
542
83
  // https://eprint.iacr.org/2009/565.pdf
543
- _cyclotomicSquare: ({ c0, c1 }) => {
84
+ Fp12cyclotomicSquare: ({ c0, c1 }) => {
544
85
  const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0;
545
86
  const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1;
546
87
  const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1);
547
88
  const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2);
548
89
  const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2);
549
- let t9 = Fp2.mulByNonresidue(t8); // T8 * (u + 1)
90
+ const t9 = Fp2.mulByNonresidue(t8); // T8 * (u + 1)
550
91
  return {
551
92
  c0: Fp6.create({
552
93
  c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3
@@ -560,7 +101,7 @@ const Fp12 = {
560
101
  }),
561
102
  }; // 2 * (T6 + c1c2) + T6
562
103
  },
563
- _cyclotomicExp(num, n) {
104
+ Fp12cyclotomicExp(num, n) {
564
105
  let z = Fp12.ONE;
565
106
  for (let i = BLS_X_LEN - 1; i >= 0; i--) {
566
107
  z = Fp12._cyclotomicSquare(z);
@@ -571,7 +112,7 @@ const Fp12 = {
571
112
  },
572
113
  // https://eprint.iacr.org/2010/354.pdf
573
114
  // https://eprint.iacr.org/2009/565.pdf
574
- finalExponentiate: (num) => {
115
+ Fp12finalExponentiate: (num) => {
575
116
  const x = BLS_X;
576
117
  // this^(q⁶) / this
577
118
  const t0 = Fp12.div(Fp12.frobeniusMap(num, 6), num);
@@ -590,54 +131,10 @@ const Fp12 = {
590
131
  // (t2 * t5)^(q²) * (t4 * t1)^(q³) * (t6 * t1.conj)^(q^1) * t7 * t3.conj * t1
591
132
  return Fp12.mul(Fp12.mul(Fp12.mul(t2_t5_pow_q2, t4_t1_pow_q3), t6_t1c_pow_q1), t7_t3c_t1);
592
133
  },
593
- };
594
- const FP12_FROBENIUS_COEFFICIENTS = [
595
- [BigInt('0x1'), BigInt('0x0')],
596
- [
597
- BigInt('0x1904d3bf02bb0667c231beb4202c0d1f0fd603fd3cbd5f4f7b2443d784bab9c4f67ea53d63e7813d8d0775ed92235fb8'),
598
- BigInt('0x00fc3e2b36c4e03288e9e902231f9fb854a14787b6c7b36fec0c8ec971f63c5f282d5ac14d6c7ec22cf78a126ddc4af3'),
599
- ],
600
- [
601
- BigInt('0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffeffff'),
602
- BigInt('0x0'),
603
- ],
604
- [
605
- BigInt('0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2'),
606
- BigInt('0x06af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09'),
607
- ],
608
- [
609
- BigInt('0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe'),
610
- BigInt('0x0'),
611
- ],
612
- [
613
- BigInt('0x144e4211384586c16bd3ad4afa99cc9170df3560e77982d0db45f3536814f0bd5871c1908bd478cd1ee605167ff82995'),
614
- BigInt('0x05b2cfd9013a5fd8df47fa6b48b1e045f39816240c0b8fee8beadf4d8e9c0566c63a3e6e257f87329b18fae980078116'),
615
- ],
616
- [
617
- BigInt('0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa'),
618
- BigInt('0x0'),
619
- ],
620
- [
621
- BigInt('0x00fc3e2b36c4e03288e9e902231f9fb854a14787b6c7b36fec0c8ec971f63c5f282d5ac14d6c7ec22cf78a126ddc4af3'),
622
- BigInt('0x1904d3bf02bb0667c231beb4202c0d1f0fd603fd3cbd5f4f7b2443d784bab9c4f67ea53d63e7813d8d0775ed92235fb8'),
623
- ],
624
- [
625
- BigInt('0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac'),
626
- BigInt('0x0'),
627
- ],
628
- [
629
- BigInt('0x06af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09'),
630
- BigInt('0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2'),
631
- ],
632
- [
633
- BigInt('0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaad'),
634
- BigInt('0x0'),
635
- ],
636
- [
637
- BigInt('0x05b2cfd9013a5fd8df47fa6b48b1e045f39816240c0b8fee8beadf4d8e9c0566c63a3e6e257f87329b18fae980078116'),
638
- BigInt('0x144e4211384586c16bd3ad4afa99cc9170df3560e77982d0db45f3536814f0bd5871c1908bd478cd1ee605167ff82995'),
639
- ],
640
- ].map((n) => Fp2.fromBigTuple(n));
134
+ });
135
+ // Finite field over r.
136
+ // This particular field is not used anywhere in bls12-381, but it is still useful.
137
+ const Fr = mod.Field(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001'));
641
138
  // END OF CURVE FIELDS
642
139
  // HashToCurve
643
140
  // 3-isogeny map from E' to E https://www.rfc-editor.org/rfc/rfc9380#appendix-E.3
@@ -793,33 +290,7 @@ const G1_SWU = mapToCurveSimpleSWU(Fp, {
793
290
  });
794
291
  // Endomorphisms (for fast cofactor clearing)
795
292
  // Ψ(P) endomorphism
796
- const ut_root = Fp6.create({ c0: Fp2.ZERO, c1: Fp2.ONE, c2: Fp2.ZERO });
797
- const wsq = Fp12.create({ c0: ut_root, c1: Fp6.ZERO });
798
- const wcu = Fp12.create({ c0: Fp6.ZERO, c1: ut_root });
799
- const [wsq_inv, wcu_inv] = Fp12.invertBatch([wsq, wcu]);
800
- function psi(x, y) {
801
- // Untwist Fp2->Fp12 && frobenius(1) && twist back
802
- const x2 = Fp12.mul(Fp12.frobeniusMap(Fp12.multiplyByFp2(wsq_inv, x), 1), wsq).c0.c0;
803
- const y2 = Fp12.mul(Fp12.frobeniusMap(Fp12.multiplyByFp2(wcu_inv, y), 1), wcu).c0.c0;
804
- return [x2, y2];
805
- }
806
- // Ψ endomorphism
807
- function G2psi(c, P) {
808
- const affine = P.toAffine();
809
- const p = psi(affine.x, affine.y);
810
- return new c(p[0], p[1], Fp2.ONE);
811
- }
812
- // Ψ²(P) endomorphism
813
- // 1 / F2(2)^((p-1)/3) in GF(p²)
814
- const PSI2_C1 = BigInt('0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac');
815
- function psi2(x, y) {
816
- return [Fp2.mul(x, PSI2_C1), Fp2.neg(y)];
817
- }
818
- function G2psi2(c, P) {
819
- const affine = P.toAffine();
820
- const p = psi2(affine.x, affine.y);
821
- return new c(p[0], p[1], Fp2.ONE);
822
- }
293
+ const { G2psi, G2psi2 } = psiFrobenius(Fp, Fp2, Fp2.div(Fp2.ONE, Fp2.NONRESIDUE)); // 1/(u+1)
823
294
  // Default hash_to_field options are for hash to G2.
824
295
  //
825
296
  // Parameter definitions are in section 5.3 of the spec unless otherwise noted.
@@ -946,8 +417,8 @@ export const bls12_381 = bls({
946
417
  const cubicRootOfUnityModP = BigInt('0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe');
947
418
  const phi = new c(Fp.mul(point.px, cubicRootOfUnityModP), point.py, point.pz);
948
419
  // todo: unroll
949
- const xP = point.multiplyUnsafe(bls12_381.params.x).negate(); // [x]P
950
- const u2P = xP.multiplyUnsafe(bls12_381.params.x); // [u2]P
420
+ const xP = point.multiplyUnsafe(BLS_X).negate(); // [x]P
421
+ const u2P = xP.multiplyUnsafe(BLS_X); // [u2]P
951
422
  return u2P.equals(phi);
952
423
  // https://eprint.iacr.org/2019/814.pdf
953
424
  // (z² − 1)/3
@@ -965,7 +436,7 @@ export const bls12_381 = bls({
965
436
  // https://eprint.iacr.org/2019/403
966
437
  clearCofactor: (_c, point) => {
967
438
  // return this.multiplyUnsafe(CURVE.h);
968
- return point.multiplyUnsafe(bls12_381.params.x).add(point); // x*P + P
439
+ return point.multiplyUnsafe(BLS_X).add(point); // x*P + P
969
440
  },
970
441
  mapToCurve: (scalars) => {
971
442
  const { x, y } = G1_SWU(Fp.create(scalars[0]));
@@ -1090,7 +561,7 @@ export const bls12_381 = bls({
1090
561
  // It returns false for shitty points.
1091
562
  // https://eprint.iacr.org/2021/1130.pdf
1092
563
  isTorsionFree: (c, P) => {
1093
- return P.multiplyUnsafe(bls12_381.params.x).negate().equals(G2psi(c, P)); // ψ(P) == [u](P)
564
+ return P.multiplyUnsafe(BLS_X).negate().equals(G2psi(c, P)); // ψ(P) == [u](P)
1094
565
  // Older version: https://eprint.iacr.org/2019/814.pdf
1095
566
  // Ψ²(P) => Ψ³(P) => [z]Ψ³(P) where z = -x => [z]Ψ³(P) - Ψ²(P) + P == O
1096
567
  // return P.psi2().psi().mulNegX().subtract(psi2).add(P).isZero();
@@ -1100,7 +571,7 @@ export const bls12_381 = bls({
1100
571
  // https://eprint.iacr.org/2017/419.pdf
1101
572
  // prettier-ignore
1102
573
  clearCofactor: (c, P) => {
1103
- const x = bls12_381.params.x;
574
+ const x = BLS_X;
1104
575
  let t1 = P.multiplyUnsafe(x).negate(); // [-x]P
1105
576
  let t2 = G2psi(c, P); // Ψ(P)
1106
577
  let t3 = P.double(); // 2P
@@ -1219,8 +690,10 @@ export const bls12_381 = bls({
1219
690
  },
1220
691
  },
1221
692
  params: {
1222
- x: BLS_X, // The BLS parameter x for BLS12-381
693
+ ateLoopSize: BLS_X, // The BLS parameter x for BLS12-381
1223
694
  r: Fr.ORDER, // order; z⁴ − z² + 1; CURVE.n from other curves
695
+ xNegative: true,
696
+ twistType: 'multiplicative',
1224
697
  },
1225
698
  htfDefaults,
1226
699
  hash: sha256,