@noble/curves 0.9.0 → 1.0.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 +197 -99
- package/abstract/bls.d.ts +43 -31
- package/abstract/bls.d.ts.map +1 -1
- package/abstract/bls.js +37 -28
- package/abstract/bls.js.map +1 -1
- package/abstract/edwards.d.ts +6 -2
- package/abstract/edwards.d.ts.map +1 -1
- package/abstract/edwards.js +37 -26
- package/abstract/edwards.js.map +1 -1
- package/abstract/hash-to-curve.d.ts +1 -1
- package/abstract/hash-to-curve.d.ts.map +1 -1
- package/abstract/hash-to-curve.js +3 -2
- package/abstract/hash-to-curve.js.map +1 -1
- package/abstract/modular.js +1 -1
- package/abstract/modular.js.map +1 -1
- package/abstract/utils.d.ts.map +1 -1
- package/abstract/utils.js +2 -2
- package/abstract/utils.js.map +1 -1
- package/abstract/weierstrass.d.ts +23 -0
- package/abstract/weierstrass.d.ts.map +1 -1
- package/abstract/weierstrass.js +44 -31
- package/abstract/weierstrass.js.map +1 -1
- package/bls12-381.d.ts.map +1 -1
- package/bls12-381.js +161 -162
- package/bls12-381.js.map +1 -1
- package/{bn.d.ts → bn254.d.ts} +1 -1
- package/bn254.d.ts.map +1 -0
- package/{bn.js → bn254.js} +1 -1
- package/bn254.js.map +1 -0
- package/ed25519.d.ts +9 -0
- package/ed25519.d.ts.map +1 -1
- package/ed25519.js +23 -9
- package/ed25519.js.map +1 -1
- package/ed448.d.ts +9 -0
- package/ed448.d.ts.map +1 -1
- package/ed448.js +19 -18
- package/ed448.js.map +1 -1
- package/esm/abstract/bls.js +37 -28
- package/esm/abstract/bls.js.map +1 -1
- package/esm/abstract/edwards.js +37 -26
- package/esm/abstract/edwards.js.map +1 -1
- package/esm/abstract/hash-to-curve.js +3 -2
- package/esm/abstract/hash-to-curve.js.map +1 -1
- package/esm/abstract/modular.js +1 -1
- package/esm/abstract/modular.js.map +1 -1
- package/esm/abstract/utils.js +2 -2
- package/esm/abstract/utils.js.map +1 -1
- package/esm/abstract/weierstrass.js +36 -23
- package/esm/abstract/weierstrass.js.map +1 -1
- package/esm/bls12-381.js +162 -163
- package/esm/bls12-381.js.map +1 -1
- package/esm/{bn.js → bn254.js} +1 -1
- package/esm/bn254.js.map +1 -0
- package/esm/ed25519.js +21 -8
- package/esm/ed25519.js.map +1 -1
- package/esm/ed448.js +17 -17
- package/esm/ed448.js.map +1 -1
- package/esm/p256.js +5 -6
- package/esm/p256.js.map +1 -1
- package/esm/p384.js +10 -12
- package/esm/p384.js.map +1 -1
- package/esm/p521.js +22 -18
- package/esm/p521.js.map +1 -1
- package/esm/secp256k1.js +1 -1
- package/esm/secp256k1.js.map +1 -1
- package/p256.d.ts +1 -1
- package/p256.d.ts.map +1 -1
- package/p256.js +6 -7
- package/p256.js.map +1 -1
- package/p384.d.ts +1 -1
- package/p384.d.ts.map +1 -1
- package/p384.js +11 -13
- package/p384.js.map +1 -1
- package/p521.d.ts +1 -1
- package/p521.d.ts.map +1 -1
- package/p521.js +23 -19
- package/p521.js.map +1 -1
- package/package.json +5 -8
- package/secp256k1.js +1 -1
- package/secp256k1.js.map +1 -1
- package/src/abstract/bls.ts +83 -61
- package/src/abstract/edwards.ts +49 -24
- package/src/abstract/hash-to-curve.ts +4 -3
- package/src/abstract/modular.ts +1 -1
- package/src/abstract/utils.ts +2 -2
- package/src/abstract/weierstrass.ts +36 -23
- package/src/bls12-381.ts +252 -171
- package/src/ed25519.ts +23 -9
- package/src/ed448.ts +18 -17
- package/src/p256.ts +15 -19
- package/src/p384.ts +17 -21
- package/src/p521.ts +34 -22
- package/src/secp256k1.ts +1 -1
- package/bn.d.ts.map +0 -1
- package/bn.js.map +0 -1
- package/esm/bn.js.map +0 -1
- /package/src/{bn.ts → bn254.ts} +0 -0
package/esm/bls12-381.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
//
|
|
7
7
|
// The library uses G1 for public keys and G2 for signatures. Support for G1 signatures is planned.
|
|
8
8
|
// Compatible with Algorand, Chia, Dfinity, Ethereum, FIL, Zcash. Matches specs
|
|
9
|
-
// [pairing-curves-
|
|
9
|
+
// [pairing-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11),
|
|
10
10
|
// [bls-sigs-04](https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04),
|
|
11
11
|
// [hash-to-curve-12](https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-12).
|
|
12
12
|
//
|
|
@@ -26,37 +26,25 @@
|
|
|
26
26
|
// - `e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))` - signature aggregation
|
|
27
27
|
// Filecoin uses little endian byte arrays for private keys -
|
|
28
28
|
// so ensure to reverse byte order if you'll use it with FIL.
|
|
29
|
-
//
|
|
30
|
-
// ### Resources
|
|
31
|
-
// - [BLS12-381 for the rest of us](https://hackmd.io/@benjaminion/bls12-381)
|
|
32
|
-
// - [Key concepts of pairings](https://medium.com/@alonmuroch_65570/bls-signatures-part-2-key-concepts-of-pairings-27a8a9533d0c)
|
|
33
|
-
// - Pairing over bls12-381:
|
|
34
|
-
// [part 1](https://research.nccgroup.com/2020/07/06/pairing-over-bls12-381-part-1-fields/),
|
|
35
|
-
// [part 2](https://research.nccgroup.com/2020/07/13/pairing-over-bls12-381-part-2-curves/),
|
|
36
|
-
// [part 3](https://research.nccgroup.com/2020/08/13/pairing-over-bls12-381-part-3-pairing/)
|
|
37
|
-
// - [Estimating the bit security of pairing-friendly curves](https://research.nccgroup.com/2022/02/03/estimating-the-bit-security-of-pairing-friendly-curves/)
|
|
38
|
-
//
|
|
39
|
-
// ### Differences from @noble/bls12-381 1.4
|
|
40
|
-
// - PointG1 -> G1.Point
|
|
41
|
-
// - PointG2 -> G2.Point
|
|
42
|
-
// - PointG2.fromSignature -> Signature.decode
|
|
43
|
-
// - PointG2.toSignature -> Signature.encode
|
|
44
|
-
// - Fixed Fp2 ORDER
|
|
45
|
-
// - Points now have only two coordinates
|
|
46
29
|
import { sha256 } from '@noble/hashes/sha256';
|
|
47
30
|
import { randomBytes } from '@noble/hashes/utils';
|
|
48
31
|
import { bls } from './abstract/bls.js';
|
|
49
32
|
import * as mod from './abstract/modular.js';
|
|
50
|
-
import { concatBytes as concatB, ensureBytes, numberToBytesBE, bytesToNumberBE, bitLen, bitSet, bitGet, bitMask, } from './abstract/utils.js';
|
|
33
|
+
import { concatBytes as concatB, ensureBytes, numberToBytesBE, bytesToNumberBE, bitLen, bitSet, bitGet, bitMask, bytesToHex, } from './abstract/utils.js';
|
|
51
34
|
// Types
|
|
52
35
|
import { mapToCurveSimpleSWU, } from './abstract/weierstrass.js';
|
|
53
36
|
import { isogenyMap } from './abstract/hash-to-curve.js';
|
|
37
|
+
// Be friendly to bad ECMAScript parsers by not using bigint literals
|
|
38
|
+
// prettier-ignore
|
|
39
|
+
const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);
|
|
40
|
+
// prettier-ignore
|
|
41
|
+
const _8n = BigInt(8), _16n = BigInt(16);
|
|
54
42
|
// CURVE FIELDS
|
|
55
43
|
// Finite field over p.
|
|
56
|
-
const Fp = mod.Field(
|
|
44
|
+
const Fp = mod.Field(BigInt('0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab'));
|
|
57
45
|
// Finite field over r.
|
|
58
46
|
// This particular field is not used anywhere in bls12-381, but it is still useful.
|
|
59
|
-
const Fr = mod.Field(
|
|
47
|
+
const Fr = mod.Field(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001'));
|
|
60
48
|
const Fp2Add = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({
|
|
61
49
|
c0: Fp.add(c0, r0),
|
|
62
50
|
c1: Fp.add(c1, r1),
|
|
@@ -88,8 +76,7 @@ const Fp2Square = ({ c0, c1 }) => {
|
|
|
88
76
|
// G² - 1
|
|
89
77
|
// h2q
|
|
90
78
|
// NOTE: ORDER was wrong!
|
|
91
|
-
const FP2_ORDER =
|
|
92
|
-
2n;
|
|
79
|
+
const FP2_ORDER = BigInt('0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab') ** _2n;
|
|
93
80
|
const Fp2 = {
|
|
94
81
|
ORDER: FP2_ORDER,
|
|
95
82
|
BITS: bitLen(FP2_ORDER),
|
|
@@ -142,7 +129,7 @@ const Fp2 = {
|
|
|
142
129
|
// https://github.com/zkcrypto/bls12_381/blob/080eaa74ec0e394377caa1ba302c8c121df08b07/src/fp2.rs#L250
|
|
143
130
|
// https://github.com/supranational/blst/blob/aae0c7d70b799ac269ff5edf29d8191dbd357876/src/exp2.c#L1
|
|
144
131
|
// Inspired by https://github.com/dalek-cryptography/curve25519-dalek/blob/17698df9d4c834204f83a3574143abacb4fc81a5/src/field.rs#L99
|
|
145
|
-
const candidateSqrt = Fp2.pow(num, (Fp2.ORDER +
|
|
132
|
+
const candidateSqrt = Fp2.pow(num, (Fp2.ORDER + _8n) / _16n);
|
|
146
133
|
const check = Fp2.div(Fp2.sqr(candidateSqrt), num); // candidateSqrt.square().div(this);
|
|
147
134
|
const R = FP2_ROOTS_OF_UNITY;
|
|
148
135
|
const divisor = [R[0], R[2], R[4], R[6]].find((r) => Fp2.eql(r, check));
|
|
@@ -163,10 +150,10 @@ const Fp2 = {
|
|
|
163
150
|
// Same as sgn0_fp2 in draft-irtf-cfrg-hash-to-curve-16
|
|
164
151
|
isOdd: (x) => {
|
|
165
152
|
const { re: x0, im: x1 } = Fp2.reim(x);
|
|
166
|
-
const sign_0 = x0 %
|
|
167
|
-
const zero_0 = x0 ===
|
|
168
|
-
const sign_1 = x1 %
|
|
169
|
-
return BigInt(sign_0 || (zero_0 && sign_1)) ==
|
|
153
|
+
const sign_0 = x0 % _2n;
|
|
154
|
+
const zero_0 = x0 === _0n;
|
|
155
|
+
const sign_1 = x1 % _2n;
|
|
156
|
+
return BigInt(sign_0 || (zero_0 && sign_1)) == _1n;
|
|
170
157
|
},
|
|
171
158
|
// Bytes util
|
|
172
159
|
fromBytes(b) {
|
|
@@ -187,8 +174,8 @@ const Fp2 = {
|
|
|
187
174
|
// multiply by u + 1
|
|
188
175
|
mulByNonresidue: ({ c0, c1 }) => ({ c0: Fp.sub(c0, c1), c1: Fp.add(c0, c1) }),
|
|
189
176
|
multiplyByB: ({ c0, c1 }) => {
|
|
190
|
-
let t0 = Fp.mul(c0,
|
|
191
|
-
let t1 = Fp.mul(c1,
|
|
177
|
+
let t0 = Fp.mul(c0, _4n); // 4 * c0
|
|
178
|
+
let t1 = Fp.mul(c1, _4n); // 4 * c1
|
|
192
179
|
// (T0-T1) + (T0+T1)*i
|
|
193
180
|
return { c0: Fp.sub(t0, t1), c1: Fp.add(t0, t1) };
|
|
194
181
|
},
|
|
@@ -206,30 +193,30 @@ const Fp2 = {
|
|
|
206
193
|
// Finite extension field over irreducible polynominal.
|
|
207
194
|
// Fp(u) / (u² - β) where β = -1
|
|
208
195
|
const FP2_FROBENIUS_COEFFICIENTS = [
|
|
209
|
-
|
|
210
|
-
|
|
196
|
+
BigInt('0x1'),
|
|
197
|
+
BigInt('0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa'),
|
|
211
198
|
].map((item) => Fp.create(item));
|
|
212
199
|
// For Fp2 roots of unity.
|
|
213
|
-
const rv1 =
|
|
200
|
+
const rv1 = BigInt('0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09');
|
|
214
201
|
// const ev1 =
|
|
215
|
-
//
|
|
202
|
+
// BigInt('0x699be3b8c6870965e5bf892ad5d2cc7b0e85a117402dfd83b7f4a947e02d978498255a2aaec0ac627b5afbdf1bf1c90');
|
|
216
203
|
// const ev2 =
|
|
217
|
-
//
|
|
204
|
+
// BigInt('0x8157cd83046453f5dd0972b6e3949e4288020b5b8a9cc99ca07e27089a2ce2436d965026adad3ef7baba37f2183e9b5');
|
|
218
205
|
// const ev3 =
|
|
219
|
-
//
|
|
206
|
+
// BigInt('0xab1c2ffdd6c253ca155231eb3e71ba044fd562f6f72bc5bad5ec46a0b7a3b0247cf08ce6c6317f40edbc653a72dee17');
|
|
220
207
|
// const ev4 =
|
|
221
|
-
//
|
|
208
|
+
// BigInt('0xaa404866706722864480885d68ad0ccac1967c7544b447873cc37e0181271e006df72162a3d3e0287bf597fbf7f8fc1');
|
|
222
209
|
// Eighth roots of unity, used for computing square roots in Fp2.
|
|
223
210
|
// To verify or re-calculate:
|
|
224
211
|
// Array(8).fill(new Fp2([1n, 1n])).map((fp2, k) => fp2.pow(Fp2.ORDER * BigInt(k) / 8n))
|
|
225
212
|
const FP2_ROOTS_OF_UNITY = [
|
|
226
|
-
[
|
|
213
|
+
[_1n, _0n],
|
|
227
214
|
[rv1, -rv1],
|
|
228
|
-
[
|
|
215
|
+
[_0n, _1n],
|
|
229
216
|
[rv1, rv1],
|
|
230
|
-
[-
|
|
217
|
+
[-_1n, _0n],
|
|
231
218
|
[-rv1, rv1],
|
|
232
|
-
[
|
|
219
|
+
[_0n, -_1n],
|
|
233
220
|
[-rv1, -rv1],
|
|
234
221
|
].map((pair) => Fp2.fromBigTuple(pair));
|
|
235
222
|
const Fp6Add = ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => ({
|
|
@@ -265,8 +252,8 @@ const Fp6Multiply = ({ c0, c1, c2 }, rhs) => {
|
|
|
265
252
|
};
|
|
266
253
|
const Fp6Square = ({ c0, c1, c2 }) => {
|
|
267
254
|
let t0 = Fp2.sqr(c0); // c0²
|
|
268
|
-
let t1 = Fp2.mul(Fp2.mul(c0, c1),
|
|
269
|
-
let t3 = Fp2.mul(Fp2.mul(c1, c2),
|
|
255
|
+
let t1 = Fp2.mul(Fp2.mul(c0, c1), _2n); // 2 * c0 * c1
|
|
256
|
+
let t3 = Fp2.mul(Fp2.mul(c1, c2), _2n); // 2 * c1 * c2
|
|
270
257
|
let t4 = Fp2.sqr(c2); // c2²
|
|
271
258
|
return {
|
|
272
259
|
c0: Fp2.add(Fp2.mulByNonresidue(t3), t0),
|
|
@@ -376,50 +363,50 @@ const Fp6 = {
|
|
|
376
363
|
}),
|
|
377
364
|
};
|
|
378
365
|
const FP6_FROBENIUS_COEFFICIENTS_1 = [
|
|
379
|
-
[
|
|
366
|
+
[BigInt('0x1'), BigInt('0x0')],
|
|
380
367
|
[
|
|
381
|
-
|
|
382
|
-
|
|
368
|
+
BigInt('0x0'),
|
|
369
|
+
BigInt('0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac'),
|
|
383
370
|
],
|
|
384
371
|
[
|
|
385
|
-
|
|
386
|
-
|
|
372
|
+
BigInt('0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe'),
|
|
373
|
+
BigInt('0x0'),
|
|
387
374
|
],
|
|
388
|
-
[
|
|
375
|
+
[BigInt('0x0'), BigInt('0x1')],
|
|
389
376
|
[
|
|
390
|
-
|
|
391
|
-
|
|
377
|
+
BigInt('0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac'),
|
|
378
|
+
BigInt('0x0'),
|
|
392
379
|
],
|
|
393
380
|
[
|
|
394
|
-
|
|
395
|
-
|
|
381
|
+
BigInt('0x0'),
|
|
382
|
+
BigInt('0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe'),
|
|
396
383
|
],
|
|
397
384
|
].map((pair) => Fp2.fromBigTuple(pair));
|
|
398
385
|
const FP6_FROBENIUS_COEFFICIENTS_2 = [
|
|
399
|
-
[
|
|
386
|
+
[BigInt('0x1'), BigInt('0x0')],
|
|
400
387
|
[
|
|
401
|
-
|
|
402
|
-
|
|
388
|
+
BigInt('0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaad'),
|
|
389
|
+
BigInt('0x0'),
|
|
403
390
|
],
|
|
404
391
|
[
|
|
405
|
-
|
|
406
|
-
|
|
392
|
+
BigInt('0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac'),
|
|
393
|
+
BigInt('0x0'),
|
|
407
394
|
],
|
|
408
395
|
[
|
|
409
|
-
|
|
410
|
-
|
|
396
|
+
BigInt('0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa'),
|
|
397
|
+
BigInt('0x0'),
|
|
411
398
|
],
|
|
412
399
|
[
|
|
413
|
-
|
|
414
|
-
|
|
400
|
+
BigInt('0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe'),
|
|
401
|
+
BigInt('0x0'),
|
|
415
402
|
],
|
|
416
403
|
[
|
|
417
|
-
|
|
418
|
-
|
|
404
|
+
BigInt('0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffeffff'),
|
|
405
|
+
BigInt('0x0'),
|
|
419
406
|
],
|
|
420
407
|
].map((pair) => Fp2.fromBigTuple(pair));
|
|
421
408
|
// The BLS parameter x for BLS12-381
|
|
422
|
-
const BLS_X =
|
|
409
|
+
const BLS_X = BigInt('0xd201000000010000');
|
|
423
410
|
const BLS_X_LEN = bitLen(BLS_X);
|
|
424
411
|
const Fp12Add = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({
|
|
425
412
|
c0: Fp6.add(c0, r0),
|
|
@@ -556,14 +543,14 @@ const Fp12 = {
|
|
|
556
543
|
let t9 = Fp2.mulByNonresidue(t8); // T8 * (u + 1)
|
|
557
544
|
return {
|
|
558
545
|
c0: Fp6.create({
|
|
559
|
-
c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0),
|
|
560
|
-
c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1),
|
|
561
|
-
c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2),
|
|
546
|
+
c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3),
|
|
547
|
+
c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5),
|
|
548
|
+
c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7),
|
|
562
549
|
}),
|
|
563
550
|
c1: Fp6.create({
|
|
564
|
-
c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0),
|
|
565
|
-
c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1),
|
|
566
|
-
c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2),
|
|
551
|
+
c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9),
|
|
552
|
+
c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4),
|
|
553
|
+
c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6),
|
|
567
554
|
}),
|
|
568
555
|
}; // 2 * (T6 + c1c2) + T6
|
|
569
556
|
},
|
|
@@ -599,50 +586,50 @@ const Fp12 = {
|
|
|
599
586
|
},
|
|
600
587
|
};
|
|
601
588
|
const FP12_FROBENIUS_COEFFICIENTS = [
|
|
602
|
-
[
|
|
589
|
+
[BigInt('0x1'), BigInt('0x0')],
|
|
603
590
|
[
|
|
604
|
-
|
|
605
|
-
|
|
591
|
+
BigInt('0x1904d3bf02bb0667c231beb4202c0d1f0fd603fd3cbd5f4f7b2443d784bab9c4f67ea53d63e7813d8d0775ed92235fb8'),
|
|
592
|
+
BigInt('0x00fc3e2b36c4e03288e9e902231f9fb854a14787b6c7b36fec0c8ec971f63c5f282d5ac14d6c7ec22cf78a126ddc4af3'),
|
|
606
593
|
],
|
|
607
594
|
[
|
|
608
|
-
|
|
609
|
-
|
|
595
|
+
BigInt('0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffeffff'),
|
|
596
|
+
BigInt('0x0'),
|
|
610
597
|
],
|
|
611
598
|
[
|
|
612
|
-
|
|
613
|
-
|
|
599
|
+
BigInt('0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2'),
|
|
600
|
+
BigInt('0x06af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09'),
|
|
614
601
|
],
|
|
615
602
|
[
|
|
616
|
-
|
|
617
|
-
|
|
603
|
+
BigInt('0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe'),
|
|
604
|
+
BigInt('0x0'),
|
|
618
605
|
],
|
|
619
606
|
[
|
|
620
|
-
|
|
621
|
-
|
|
607
|
+
BigInt('0x144e4211384586c16bd3ad4afa99cc9170df3560e77982d0db45f3536814f0bd5871c1908bd478cd1ee605167ff82995'),
|
|
608
|
+
BigInt('0x05b2cfd9013a5fd8df47fa6b48b1e045f39816240c0b8fee8beadf4d8e9c0566c63a3e6e257f87329b18fae980078116'),
|
|
622
609
|
],
|
|
623
610
|
[
|
|
624
|
-
|
|
625
|
-
|
|
611
|
+
BigInt('0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa'),
|
|
612
|
+
BigInt('0x0'),
|
|
626
613
|
],
|
|
627
614
|
[
|
|
628
|
-
|
|
629
|
-
|
|
615
|
+
BigInt('0x00fc3e2b36c4e03288e9e902231f9fb854a14787b6c7b36fec0c8ec971f63c5f282d5ac14d6c7ec22cf78a126ddc4af3'),
|
|
616
|
+
BigInt('0x1904d3bf02bb0667c231beb4202c0d1f0fd603fd3cbd5f4f7b2443d784bab9c4f67ea53d63e7813d8d0775ed92235fb8'),
|
|
630
617
|
],
|
|
631
618
|
[
|
|
632
|
-
|
|
633
|
-
|
|
619
|
+
BigInt('0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac'),
|
|
620
|
+
BigInt('0x0'),
|
|
634
621
|
],
|
|
635
622
|
[
|
|
636
|
-
|
|
637
|
-
|
|
623
|
+
BigInt('0x06af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09'),
|
|
624
|
+
BigInt('0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2'),
|
|
638
625
|
],
|
|
639
626
|
[
|
|
640
|
-
|
|
641
|
-
|
|
627
|
+
BigInt('0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaad'),
|
|
628
|
+
BigInt('0x0'),
|
|
642
629
|
],
|
|
643
630
|
[
|
|
644
|
-
|
|
645
|
-
|
|
631
|
+
BigInt('0x05b2cfd9013a5fd8df47fa6b48b1e045f39816240c0b8fee8beadf4d8e9c0566c63a3e6e257f87329b18fae980078116'),
|
|
632
|
+
BigInt('0x144e4211384586c16bd3ad4afa99cc9170df3560e77982d0db45f3536814f0bd5871c1908bd478cd1ee605167ff82995'),
|
|
646
633
|
],
|
|
647
634
|
].map((n) => Fp2.fromBigTuple(n));
|
|
648
635
|
// END OF CURVE FIELDS
|
|
@@ -789,15 +776,15 @@ const isogenyMapG1 = isogenyMap(Fp, [
|
|
|
789
776
|
].map((i) => i.map((j) => BigInt(j))));
|
|
790
777
|
// SWU Map - Fp2 to G2': y² = x³ + 240i * x + 1012 + 1012i
|
|
791
778
|
const G2_SWU = mapToCurveSimpleSWU(Fp2, {
|
|
792
|
-
A: Fp2.create({ c0: Fp.create(
|
|
793
|
-
B: Fp2.create({ c0: Fp.create(
|
|
794
|
-
Z: Fp2.create({ c0: Fp.create(-
|
|
779
|
+
A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(BigInt(240)) }),
|
|
780
|
+
B: Fp2.create({ c0: Fp.create(BigInt(1012)), c1: Fp.create(BigInt(1012)) }),
|
|
781
|
+
Z: Fp2.create({ c0: Fp.create(BigInt(-2)), c1: Fp.create(BigInt(-1)) }), // Z: -(2 + I)
|
|
795
782
|
});
|
|
796
783
|
// Optimized SWU Map - Fp to G1
|
|
797
784
|
const G1_SWU = mapToCurveSimpleSWU(Fp, {
|
|
798
|
-
A: Fp.create(
|
|
799
|
-
B: Fp.create(
|
|
800
|
-
Z: Fp.create(
|
|
785
|
+
A: Fp.create(BigInt('0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aefd881ac98936f8da0e0f97f5cf428082d584c1d')),
|
|
786
|
+
B: Fp.create(BigInt('0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0')),
|
|
787
|
+
Z: Fp.create(BigInt(11)),
|
|
801
788
|
});
|
|
802
789
|
// Endomorphisms (for fast cofactor clearing)
|
|
803
790
|
// Ψ(P) endomorphism
|
|
@@ -819,7 +806,7 @@ function G2psi(c, P) {
|
|
|
819
806
|
}
|
|
820
807
|
// Ψ²(P) endomorphism
|
|
821
808
|
// 1 / F2(2)^((p-1)/3) in GF(p²)
|
|
822
|
-
const PSI2_C1 =
|
|
809
|
+
const PSI2_C1 = BigInt('0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac');
|
|
823
810
|
function psi2(x, y) {
|
|
824
811
|
return [Fp2.mul(x, PSI2_C1), Fp2.neg(y)];
|
|
825
812
|
}
|
|
@@ -867,7 +854,22 @@ const C_BIT_POS = Fp.BITS; // C_bit, compression bit for serialization flag
|
|
|
867
854
|
const I_BIT_POS = Fp.BITS + 1; // I_bit, point-at-infinity bit for serialization flag
|
|
868
855
|
const S_BIT_POS = Fp.BITS + 2; // S_bit, sign bit for serialization flag
|
|
869
856
|
// Compressed point of infinity
|
|
870
|
-
const COMPRESSED_ZERO = Fp.toBytes(bitSet(bitSet(
|
|
857
|
+
const COMPRESSED_ZERO = Fp.toBytes(bitSet(bitSet(_0n, I_BIT_POS, true), S_BIT_POS, true)); // set compressed & point-at-infinity bits
|
|
858
|
+
function signatureG2ToRawBytes(point) {
|
|
859
|
+
// NOTE: by some reasons it was missed in bls12-381, looks like bug
|
|
860
|
+
point.assertValidity();
|
|
861
|
+
const len = Fp.BYTES;
|
|
862
|
+
if (point.equals(bls12_381.G2.ProjectivePoint.ZERO))
|
|
863
|
+
return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len));
|
|
864
|
+
const { x, y } = point.toAffine();
|
|
865
|
+
const { re: x0, im: x1 } = Fp2.reim(x);
|
|
866
|
+
const { re: y0, im: y1 } = Fp2.reim(y);
|
|
867
|
+
const tmp = y1 > _0n ? y1 * _2n : y0 * _2n;
|
|
868
|
+
const aflag1 = Boolean((tmp / Fp.ORDER) & _1n);
|
|
869
|
+
const z1 = bitSet(bitSet(x1, 381, aflag1), S_BIT_POS, true);
|
|
870
|
+
const z2 = x0;
|
|
871
|
+
return concatB(numberToBytesBE(z1, len), numberToBytesBE(z2, len));
|
|
872
|
+
}
|
|
871
873
|
// To verify curve parameters, see pairing-friendly-curves spec:
|
|
872
874
|
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-09
|
|
873
875
|
// Basic math is done over finite fields over p.
|
|
@@ -880,26 +882,26 @@ const COMPRESSED_ZERO = Fp.toBytes(bitSet(bitSet(0n, I_BIT_POS, true), S_BIT_POS
|
|
|
880
882
|
// Here goes constants && point encoding format
|
|
881
883
|
export const bls12_381 = bls({
|
|
882
884
|
// Fields
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
885
|
+
fields: {
|
|
886
|
+
Fp,
|
|
887
|
+
Fp2,
|
|
888
|
+
Fp6,
|
|
889
|
+
Fp12,
|
|
890
|
+
Fr,
|
|
891
|
+
},
|
|
890
892
|
// G1 is the order-q subgroup of E1(Fp) : y² = x³ + 4, #E1(Fp) = h1q, where
|
|
891
893
|
// characteristic; z + (z⁴ - z² + 1)(z - 1)²/3
|
|
892
894
|
G1: {
|
|
893
895
|
Fp,
|
|
894
896
|
// cofactor; (z - 1)²/3
|
|
895
|
-
h:
|
|
897
|
+
h: BigInt('0x396c8c005555e1568c00aaab0000aaab'),
|
|
896
898
|
// generator's coordinates
|
|
897
899
|
// x = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507
|
|
898
900
|
// y = 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569
|
|
899
|
-
Gx:
|
|
900
|
-
Gy:
|
|
901
|
+
Gx: BigInt('0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb'),
|
|
902
|
+
Gy: BigInt('0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1'),
|
|
901
903
|
a: Fp.ZERO,
|
|
902
|
-
b:
|
|
904
|
+
b: _4n,
|
|
903
905
|
htfDefaults: { ...htfDefaults, m: 1 },
|
|
904
906
|
wrapPrivateKey: true,
|
|
905
907
|
allowInfinityPoint: true,
|
|
@@ -909,15 +911,15 @@ export const bls12_381 = bls({
|
|
|
909
911
|
// https://eprint.iacr.org/2021/1130.pdf
|
|
910
912
|
isTorsionFree: (c, point) => {
|
|
911
913
|
// φ endomorphism
|
|
912
|
-
const cubicRootOfUnityModP =
|
|
914
|
+
const cubicRootOfUnityModP = BigInt('0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe');
|
|
913
915
|
const phi = new c(Fp.mul(point.px, cubicRootOfUnityModP), point.py, point.pz);
|
|
914
916
|
// todo: unroll
|
|
915
|
-
const xP = point.multiplyUnsafe(bls12_381.
|
|
916
|
-
const u2P = xP.multiplyUnsafe(bls12_381.
|
|
917
|
+
const xP = point.multiplyUnsafe(bls12_381.params.x).negate(); // [x]P
|
|
918
|
+
const u2P = xP.multiplyUnsafe(bls12_381.params.x); // [u2]P
|
|
917
919
|
return u2P.equals(phi);
|
|
918
920
|
// https://eprint.iacr.org/2019/814.pdf
|
|
919
921
|
// (z² − 1)/3
|
|
920
|
-
// const c1 =
|
|
922
|
+
// const c1 = BigInt('0x396c8c005555e1560000000055555555');
|
|
921
923
|
// const P = this;
|
|
922
924
|
// const S = P.sigma();
|
|
923
925
|
// const Q = S.double();
|
|
@@ -931,27 +933,29 @@ export const bls12_381 = bls({
|
|
|
931
933
|
// https://eprint.iacr.org/2019/403
|
|
932
934
|
clearCofactor: (c, point) => {
|
|
933
935
|
// return this.multiplyUnsafe(CURVE.h);
|
|
934
|
-
return point.multiplyUnsafe(bls12_381.
|
|
936
|
+
return point.multiplyUnsafe(bls12_381.params.x).add(point); // x*P + P
|
|
935
937
|
},
|
|
936
938
|
mapToCurve: (scalars) => {
|
|
937
939
|
const { x, y } = G1_SWU(Fp.create(scalars[0]));
|
|
938
940
|
return isogenyMapG1(x, y);
|
|
939
941
|
},
|
|
940
942
|
fromBytes: (bytes) => {
|
|
943
|
+
bytes = bytes.slice();
|
|
941
944
|
if (bytes.length === 48) {
|
|
945
|
+
// TODO: Fp.bytes
|
|
942
946
|
const P = Fp.ORDER;
|
|
943
947
|
const compressedValue = bytesToNumberBE(bytes);
|
|
944
948
|
const bflag = bitGet(compressedValue, I_BIT_POS);
|
|
945
949
|
// Zero
|
|
946
|
-
if (bflag ===
|
|
947
|
-
return { x:
|
|
950
|
+
if (bflag === _1n)
|
|
951
|
+
return { x: _0n, y: _0n };
|
|
948
952
|
const x = Fp.create(compressedValue & Fp.MASK);
|
|
949
|
-
const right = Fp.add(Fp.pow(x,
|
|
953
|
+
const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)); // y² = x³ + b
|
|
950
954
|
let y = Fp.sqrt(right);
|
|
951
955
|
if (!y)
|
|
952
956
|
throw new Error('Invalid compressed G1 point');
|
|
953
957
|
const aflag = bitGet(compressedValue, C_BIT_POS);
|
|
954
|
-
if ((y *
|
|
958
|
+
if ((y * _2n) / P !== aflag)
|
|
955
959
|
y = Fp.neg(y);
|
|
956
960
|
return { x: Fp.create(x), y: Fp.create(y) };
|
|
957
961
|
}
|
|
@@ -959,8 +963,8 @@ export const bls12_381 = bls({
|
|
|
959
963
|
// Check if the infinity flag is set
|
|
960
964
|
if ((bytes[0] & (1 << 6)) !== 0)
|
|
961
965
|
return bls12_381.G1.ProjectivePoint.ZERO.toAffine();
|
|
962
|
-
const x = bytesToNumberBE(bytes.
|
|
963
|
-
const y = bytesToNumberBE(bytes.
|
|
966
|
+
const x = bytesToNumberBE(bytes.subarray(0, Fp.BYTES));
|
|
967
|
+
const y = bytesToNumberBE(bytes.subarray(Fp.BYTES));
|
|
964
968
|
return { x: Fp.create(x), y: Fp.create(y) };
|
|
965
969
|
}
|
|
966
970
|
else {
|
|
@@ -975,7 +979,7 @@ export const bls12_381 = bls({
|
|
|
975
979
|
return COMPRESSED_ZERO.slice();
|
|
976
980
|
const P = Fp.ORDER;
|
|
977
981
|
let num;
|
|
978
|
-
num = bitSet(x, C_BIT_POS, Boolean((y *
|
|
982
|
+
num = bitSet(x, C_BIT_POS, Boolean((y * _2n) / P)); // set aflag
|
|
979
983
|
num = bitSet(num, S_BIT_POS, true);
|
|
980
984
|
return numberToBytesBE(num, Fp.BYTES);
|
|
981
985
|
}
|
|
@@ -998,21 +1002,21 @@ export const bls12_381 = bls({
|
|
|
998
1002
|
G2: {
|
|
999
1003
|
Fp: Fp2,
|
|
1000
1004
|
// cofactor
|
|
1001
|
-
h:
|
|
1005
|
+
h: BigInt('0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5'),
|
|
1002
1006
|
Gx: Fp2.fromBigTuple([
|
|
1003
|
-
|
|
1004
|
-
|
|
1007
|
+
BigInt('0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8'),
|
|
1008
|
+
BigInt('0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e'),
|
|
1005
1009
|
]),
|
|
1006
1010
|
// y =
|
|
1007
1011
|
// 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582,
|
|
1008
1012
|
// 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905
|
|
1009
1013
|
Gy: Fp2.fromBigTuple([
|
|
1010
|
-
|
|
1011
|
-
|
|
1014
|
+
BigInt('0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801'),
|
|
1015
|
+
BigInt('0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be'),
|
|
1012
1016
|
]),
|
|
1013
1017
|
a: Fp2.ZERO,
|
|
1014
|
-
b: Fp2.fromBigTuple([4n,
|
|
1015
|
-
hEff:
|
|
1018
|
+
b: Fp2.fromBigTuple([4n, _4n]),
|
|
1019
|
+
hEff: BigInt('0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551'),
|
|
1016
1020
|
htfDefaults: { ...htfDefaults },
|
|
1017
1021
|
wrapPrivateKey: true,
|
|
1018
1022
|
allowInfinityPoint: true,
|
|
@@ -1025,7 +1029,7 @@ export const bls12_381 = bls({
|
|
|
1025
1029
|
// It returns false for shitty points.
|
|
1026
1030
|
// https://eprint.iacr.org/2021/1130.pdf
|
|
1027
1031
|
isTorsionFree: (c, P) => {
|
|
1028
|
-
return P.multiplyUnsafe(bls12_381.
|
|
1032
|
+
return P.multiplyUnsafe(bls12_381.params.x).negate().equals(G2psi(c, P)); // ψ(P) == [u](P)
|
|
1029
1033
|
// Older version: https://eprint.iacr.org/2019/814.pdf
|
|
1030
1034
|
// Ψ²(P) => Ψ³(P) => [z]Ψ³(P) where z = -x => [z]Ψ³(P) - Ψ²(P) + P == O
|
|
1031
1035
|
// return P.psi2().psi().mulNegX().subtract(psi2).add(P).isZero();
|
|
@@ -1035,7 +1039,7 @@ export const bls12_381 = bls({
|
|
|
1035
1039
|
// https://eprint.iacr.org/2017/419.pdf
|
|
1036
1040
|
// prettier-ignore
|
|
1037
1041
|
clearCofactor: (c, P) => {
|
|
1038
|
-
const
|
|
1042
|
+
const x = bls12_381.params.x;
|
|
1039
1043
|
let t1 = P.multiplyUnsafe(x).negate(); // [-x]P
|
|
1040
1044
|
let t2 = G2psi(c, P); // Ψ(P)
|
|
1041
1045
|
let t3 = P.double(); // 2P
|
|
@@ -1049,6 +1053,7 @@ export const bls12_381 = bls({
|
|
|
1049
1053
|
return Q; // [x²-x-1]P + [x-1]Ψ(P) + Ψ²(2P)
|
|
1050
1054
|
},
|
|
1051
1055
|
fromBytes: (bytes) => {
|
|
1056
|
+
bytes = bytes.slice();
|
|
1052
1057
|
const m_byte = bytes[0] & 0xe0;
|
|
1053
1058
|
if (m_byte === 0x20 || m_byte === 0x60 || m_byte === 0xe0) {
|
|
1054
1059
|
throw new Error('Invalid encoding flag: ' + m_byte);
|
|
@@ -1059,7 +1064,7 @@ export const bls12_381 = bls({
|
|
|
1059
1064
|
const L = Fp.BYTES;
|
|
1060
1065
|
const slc = (b, from, to) => bytesToNumberBE(b.slice(from, to));
|
|
1061
1066
|
if (bytes.length === 96 && bitC) {
|
|
1062
|
-
const
|
|
1067
|
+
const b = bls12_381.params.G2b;
|
|
1063
1068
|
const P = Fp.ORDER;
|
|
1064
1069
|
bytes[0] = bytes[0] & 0x1f; // clear flags
|
|
1065
1070
|
if (bitI) {
|
|
@@ -1072,9 +1077,9 @@ export const bls12_381 = bls({
|
|
|
1072
1077
|
const x_1 = slc(bytes, 0, L);
|
|
1073
1078
|
const x_0 = slc(bytes, L, 2 * L);
|
|
1074
1079
|
const x = Fp2.create({ c0: Fp.create(x_0), c1: Fp.create(x_1) });
|
|
1075
|
-
const right = Fp2.add(Fp2.pow(x,
|
|
1080
|
+
const right = Fp2.add(Fp2.pow(x, _3n), b); // y² = x³ + 4 * (u+1) = x³ + b
|
|
1076
1081
|
let y = Fp2.sqrt(right);
|
|
1077
|
-
const Y_bit = y.c1 ===
|
|
1082
|
+
const Y_bit = y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P ? _1n : _0n;
|
|
1078
1083
|
y = bitS > 0 && Y_bit > 0 ? y : Fp2.neg(y);
|
|
1079
1084
|
return { x, y };
|
|
1080
1085
|
}
|
|
@@ -1094,29 +1099,29 @@ export const bls12_381 = bls({
|
|
|
1094
1099
|
}
|
|
1095
1100
|
},
|
|
1096
1101
|
toBytes: (c, point, isCompressed) => {
|
|
1102
|
+
const { BYTES: len, ORDER: P } = Fp;
|
|
1097
1103
|
const isZero = point.equals(c.ZERO);
|
|
1098
1104
|
const { x, y } = point.toAffine();
|
|
1099
1105
|
if (isCompressed) {
|
|
1100
|
-
const P = Fp.ORDER;
|
|
1101
1106
|
if (isZero)
|
|
1102
|
-
return concatB(COMPRESSED_ZERO, numberToBytesBE(
|
|
1103
|
-
const flag = Boolean(y.c1 ===
|
|
1107
|
+
return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len));
|
|
1108
|
+
const flag = Boolean(y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P);
|
|
1104
1109
|
// set compressed & sign bits (looks like different offsets than for G1/Fp?)
|
|
1105
1110
|
let x_1 = bitSet(x.c1, C_BIT_POS, flag);
|
|
1106
1111
|
x_1 = bitSet(x_1, S_BIT_POS, true);
|
|
1107
|
-
return concatB(numberToBytesBE(x_1,
|
|
1112
|
+
return concatB(numberToBytesBE(x_1, len), numberToBytesBE(x.c0, len));
|
|
1108
1113
|
}
|
|
1109
1114
|
else {
|
|
1110
1115
|
if (isZero)
|
|
1111
|
-
return concatB(new Uint8Array([0x40]), new Uint8Array(4 *
|
|
1116
|
+
return concatB(new Uint8Array([0x40]), new Uint8Array(4 * len - 1)); // bytes[0] |= 1 << 6;
|
|
1112
1117
|
const { re: x0, im: x1 } = Fp2.reim(x);
|
|
1113
1118
|
const { re: y0, im: y1 } = Fp2.reim(y);
|
|
1114
|
-
return concatB(numberToBytesBE(x1,
|
|
1119
|
+
return concatB(numberToBytesBE(x1, len), numberToBytesBE(x0, len), numberToBytesBE(y1, len), numberToBytesBE(y0, len));
|
|
1115
1120
|
}
|
|
1116
1121
|
},
|
|
1117
1122
|
Signature: {
|
|
1118
1123
|
// TODO: Optimize, it's very slow because of sqrt.
|
|
1119
|
-
|
|
1124
|
+
fromHex(hex) {
|
|
1120
1125
|
hex = ensureBytes('signatureHex', hex);
|
|
1121
1126
|
const P = Fp.ORDER;
|
|
1122
1127
|
const half = hex.length / 2;
|
|
@@ -1126,12 +1131,12 @@ export const bls12_381 = bls({
|
|
|
1126
1131
|
const z2 = bytesToNumberBE(hex.slice(half));
|
|
1127
1132
|
// Indicates the infinity point
|
|
1128
1133
|
const bflag1 = bitGet(z1, I_BIT_POS);
|
|
1129
|
-
if (bflag1 ===
|
|
1134
|
+
if (bflag1 === _1n)
|
|
1130
1135
|
return bls12_381.G2.ProjectivePoint.ZERO;
|
|
1131
1136
|
const x1 = Fp.create(z1 & Fp.MASK);
|
|
1132
1137
|
const x2 = Fp.create(z2);
|
|
1133
1138
|
const x = Fp2.create({ c0: x2, c1: x1 });
|
|
1134
|
-
const y2 = Fp2.add(Fp2.pow(x,
|
|
1139
|
+
const y2 = Fp2.add(Fp2.pow(x, _3n), bls12_381.params.G2b); // y² = x³ + 4
|
|
1135
1140
|
// The slow part
|
|
1136
1141
|
let y = Fp2.sqrt(y2);
|
|
1137
1142
|
if (!y)
|
|
@@ -1140,32 +1145,26 @@ export const bls12_381 = bls({
|
|
|
1140
1145
|
// If y1 happens to be zero, then use the bit of y0
|
|
1141
1146
|
const { re: y0, im: y1 } = Fp2.reim(y);
|
|
1142
1147
|
const aflag1 = bitGet(z1, 381);
|
|
1143
|
-
const isGreater = y1 >
|
|
1144
|
-
const isZero = y1 ===
|
|
1148
|
+
const isGreater = y1 > _0n && (y1 * _2n) / P !== aflag1;
|
|
1149
|
+
const isZero = y1 === _0n && (y0 * _2n) / P !== aflag1;
|
|
1145
1150
|
if (isGreater || isZero)
|
|
1146
1151
|
y = Fp2.neg(y);
|
|
1147
1152
|
const point = bls12_381.G2.ProjectivePoint.fromAffine({ x, y });
|
|
1148
1153
|
point.assertValidity();
|
|
1149
1154
|
return point;
|
|
1150
1155
|
},
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
const a = point.toAffine();
|
|
1157
|
-
const { re: x0, im: x1 } = Fp2.reim(a.x);
|
|
1158
|
-
const { re: y0, im: y1 } = Fp2.reim(a.y);
|
|
1159
|
-
const tmp = y1 > 0n ? y1 * 2n : y0 * 2n;
|
|
1160
|
-
const aflag1 = Boolean((tmp / Fp.ORDER) & 1n);
|
|
1161
|
-
const z1 = bitSet(bitSet(x1, 381, aflag1), S_BIT_POS, true);
|
|
1162
|
-
const z2 = x0;
|
|
1163
|
-
return concatB(numberToBytesBE(z1, Fp.BYTES), numberToBytesBE(z2, Fp.BYTES));
|
|
1156
|
+
toRawBytes(point) {
|
|
1157
|
+
return signatureG2ToRawBytes(point);
|
|
1158
|
+
},
|
|
1159
|
+
toHex(point) {
|
|
1160
|
+
return bytesToHex(signatureG2ToRawBytes(point));
|
|
1164
1161
|
},
|
|
1165
1162
|
},
|
|
1166
1163
|
},
|
|
1167
|
-
|
|
1168
|
-
|
|
1164
|
+
params: {
|
|
1165
|
+
x: BLS_X,
|
|
1166
|
+
r: Fr.ORDER, // order; z⁴ − z² + 1; CURVE.n from other curves
|
|
1167
|
+
},
|
|
1169
1168
|
htfDefaults,
|
|
1170
1169
|
hash: sha256,
|
|
1171
1170
|
randomBytes,
|