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