@noble/curves 1.4.2 → 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 +79 -75
- 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 -0
- package/abstract/weierstrass.d.ts.map +1 -1
- package/abstract/weierstrass.js +88 -72
- 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 +48 -575
- 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 -0
- package/ed25519.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 +80 -76
- 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 -0
- package/esm/abstract/weierstrass.d.ts.map +1 -1
- package/esm/abstract/weierstrass.js +89 -73
- 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 +50 -577
- 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 -0
- package/esm/ed25519.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 +2 -1
- 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/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,
|
|
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
|
|
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
|
-
|
|
46
|
-
|
|
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
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
// Finite field over
|
|
52
|
-
//
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
595
|
-
|
|
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
|
|
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(
|
|
950
|
-
const u2P = xP.multiplyUnsafe(
|
|
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(
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
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,
|