@noble/curves 1.2.0 → 1.3.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 +125 -191
- package/abstract/bls.d.ts +27 -10
- package/abstract/bls.d.ts.map +1 -1
- package/abstract/bls.js +58 -8
- package/abstract/bls.js.map +1 -1
- package/abstract/curve.js.map +1 -1
- 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 +8 -8
- package/abstract/hash-to-curve.js.map +1 -1
- package/abstract/modular.js.map +1 -1
- package/abstract/montgomery.d.ts.map +1 -1
- package/abstract/montgomery.js +5 -7
- package/abstract/montgomery.js.map +1 -1
- package/abstract/poseidon.js.map +1 -1
- package/abstract/utils.d.ts +2 -1
- package/abstract/utils.d.ts.map +1 -1
- package/abstract/utils.js +55 -31
- package/abstract/utils.js.map +1 -1
- package/abstract/weierstrass.d.ts +23 -27
- package/abstract/weierstrass.d.ts.map +1 -1
- package/abstract/weierstrass.js +4 -4
- package/abstract/weierstrass.js.map +1 -1
- package/bls12-381.d.ts.map +1 -1
- package/bls12-381.js +137 -82
- package/bls12-381.js.map +1 -1
- package/bn254.d.ts +3 -2
- package/bn254.d.ts.map +1 -1
- package/bn254.js +3 -2
- package/bn254.js.map +1 -1
- package/ed25519.d.ts +4 -2
- package/ed25519.d.ts.map +1 -1
- package/ed25519.js +8 -2
- package/ed25519.js.map +1 -1
- package/ed448.d.ts +4 -2
- package/ed448.d.ts.map +1 -1
- package/ed448.js +10 -1
- package/ed448.js.map +1 -1
- package/esm/abstract/bls.js +58 -8
- package/esm/abstract/bls.js.map +1 -1
- package/esm/abstract/curve.js.map +1 -1
- package/esm/abstract/edwards.js.map +1 -1
- package/esm/abstract/hash-to-curve.js +9 -9
- package/esm/abstract/hash-to-curve.js.map +1 -1
- package/esm/abstract/modular.js.map +1 -1
- package/esm/abstract/montgomery.js +5 -7
- package/esm/abstract/montgomery.js.map +1 -1
- package/esm/abstract/poseidon.js.map +1 -1
- package/esm/abstract/utils.js +53 -30
- package/esm/abstract/utils.js.map +1 -1
- package/esm/abstract/weierstrass.js +4 -4
- package/esm/abstract/weierstrass.js.map +1 -1
- package/esm/bls12-381.js +138 -83
- package/esm/bls12-381.js.map +1 -1
- package/esm/bn254.js +3 -2
- package/esm/bn254.js.map +1 -1
- package/esm/ed25519.js +8 -2
- package/esm/ed25519.js.map +1 -1
- package/esm/ed448.js +10 -1
- package/esm/ed448.js.map +1 -1
- package/esm/jubjub.js.map +1 -1
- package/esm/p256.js +2 -2
- package/esm/p256.js.map +1 -1
- package/esm/p384.js +2 -2
- package/esm/p384.js.map +1 -1
- package/esm/p521.js +3 -3
- package/esm/p521.js.map +1 -1
- package/esm/secp256k1.js +6 -6
- package/esm/secp256k1.js.map +1 -1
- package/jubjub.js.map +1 -1
- package/p256.js +2 -2
- package/p256.js.map +1 -1
- package/p384.js +2 -2
- package/p384.js.map +1 -1
- package/p521.js +3 -3
- package/p521.js.map +1 -1
- package/package.json +5 -5
- package/secp256k1.js +6 -6
- package/secp256k1.js.map +1 -1
- package/src/abstract/bls.ts +117 -19
- package/src/abstract/hash-to-curve.ts +10 -9
- package/src/abstract/montgomery.ts +4 -6
- package/src/abstract/utils.ts +52 -26
- package/src/abstract/weierstrass.ts +16 -7
- package/src/bls12-381.ts +127 -69
- package/src/bn254.ts +3 -2
- package/src/ed25519.ts +10 -2
- package/src/ed448.ts +18 -3
package/bls12-381.js
CHANGED
|
@@ -2,16 +2,10 @@
|
|
|
2
2
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.bls12_381 = void 0;
|
|
5
|
-
// bls12-381 pairing-friendly Barreto-Lynn-Scott elliptic curve construction
|
|
6
|
-
// - Construct zk-SNARKs at the
|
|
7
|
-
// -
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// The library uses G1 for public keys and G2 for signatures. Support for G1 signatures is planned.
|
|
11
|
-
// Compatible with Algorand, Chia, Dfinity, Ethereum, FIL, Zcash. Matches specs
|
|
12
|
-
// [pairing-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11),
|
|
13
|
-
// [bls-sigs-04](https:/cfrg-hash-to/tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04),
|
|
14
|
-
// [hash-to-curve-12](https://tools.ietf.org/html/draft-irtf--curve-12).
|
|
5
|
+
// bls12-381 is pairing-friendly Barreto-Lynn-Scott elliptic curve construction allowing to:
|
|
6
|
+
// - Construct zk-SNARKs at the 120-bit security
|
|
7
|
+
// - Efficiently verify N aggregate signatures with 1 pairing and N ec additions:
|
|
8
|
+
// the Boneh-Lynn-Shacham signature scheme is orders of magnitude more efficient than Schnorr
|
|
15
9
|
//
|
|
16
10
|
// ### Summary
|
|
17
11
|
// 1. BLS Relies on Bilinear Pairing (expensive)
|
|
@@ -27,8 +21,17 @@ exports.bls12_381 = void 0;
|
|
|
27
21
|
// - `S = pk x H(m)` - signing
|
|
28
22
|
// - `e(P, H(m)) == e(G, S)` - verification using pairings
|
|
29
23
|
// - `e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))` - signature aggregation
|
|
30
|
-
//
|
|
31
|
-
//
|
|
24
|
+
//
|
|
25
|
+
// ### Compatibility and notes
|
|
26
|
+
// 1. It is compatible with Algorand, Chia, Dfinity, Ethereum, Filecoin, ZEC
|
|
27
|
+
// Filecoin uses little endian byte arrays for private keys - make sure to reverse byte order.
|
|
28
|
+
// 2. Some projects use G2 for public keys and G1 for signatures. It's called "short signature"
|
|
29
|
+
// 3. Curve security level is about 120 bits as per Barbulescu-Duquesne 2017
|
|
30
|
+
// https://hal.science/hal-01534101/file/main.pdf
|
|
31
|
+
// 4. Compatible with specs:
|
|
32
|
+
// [cfrg-pairing-friendly-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11),
|
|
33
|
+
// [cfrg-bls-signature-05](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05),
|
|
34
|
+
// [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380).
|
|
32
35
|
const sha256_1 = require("@noble/hashes/sha256");
|
|
33
36
|
const utils_1 = require("@noble/hashes/utils");
|
|
34
37
|
const bls_js_1 = require("./abstract/bls.js");
|
|
@@ -260,14 +263,14 @@ const Fp6Square = ({ c0, c1, c2 }) => {
|
|
|
260
263
|
let t3 = Fp2.mul(Fp2.mul(c1, c2), _2n); // 2 * c1 * c2
|
|
261
264
|
let t4 = Fp2.sqr(c2); // c2²
|
|
262
265
|
return {
|
|
263
|
-
c0: Fp2.add(Fp2.mulByNonresidue(t3), t0),
|
|
264
|
-
c1: Fp2.add(Fp2.mulByNonresidue(t4), t1),
|
|
266
|
+
c0: Fp2.add(Fp2.mulByNonresidue(t3), t0), // T3 * (u + 1) + T0
|
|
267
|
+
c1: Fp2.add(Fp2.mulByNonresidue(t4), t1), // T4 * (u + 1) + T1
|
|
265
268
|
// T1 + (c0 - c1 + c2)² + T3 - T0 - T4
|
|
266
269
|
c2: Fp2.sub(Fp2.sub(Fp2.add(Fp2.add(t1, Fp2.sqr(Fp2.add(Fp2.sub(c0, c1), c2))), t3), t0), t4),
|
|
267
270
|
};
|
|
268
271
|
};
|
|
269
272
|
const Fp6 = {
|
|
270
|
-
ORDER: Fp2.ORDER,
|
|
273
|
+
ORDER: Fp2.ORDER, // TODO: unused, but need to verify
|
|
271
274
|
BITS: 3 * Fp2.BITS,
|
|
272
275
|
BYTES: 3 * Fp2.BYTES,
|
|
273
276
|
MASK: (0, utils_js_1.bitMask)(3 * Fp2.BITS),
|
|
@@ -427,7 +430,7 @@ const Fp12Multiply = ({ c0, c1 }, rhs) => {
|
|
|
427
430
|
let t1 = Fp6.mul(c0, r0); // c0 * r0
|
|
428
431
|
let t2 = Fp6.mul(c1, r1); // c1 * r1
|
|
429
432
|
return {
|
|
430
|
-
c0: Fp6.add(t1, Fp6.mulByNonresidue(t2)),
|
|
433
|
+
c0: Fp6.add(t1, Fp6.mulByNonresidue(t2)), // T1 + T2 * v
|
|
431
434
|
// (c0 + c1) * (r0 + r1) - (T1 + T2)
|
|
432
435
|
c1: Fp6.sub(Fp6.mul(Fp6.add(c0, c1), Fp6.add(r0, r1)), Fp6.add(t1, t2)),
|
|
433
436
|
};
|
|
@@ -444,12 +447,12 @@ function Fp4Square(a, b) {
|
|
|
444
447
|
const a2 = Fp2.sqr(a);
|
|
445
448
|
const b2 = Fp2.sqr(b);
|
|
446
449
|
return {
|
|
447
|
-
first: Fp2.add(Fp2.mulByNonresidue(b2), a2),
|
|
450
|
+
first: Fp2.add(Fp2.mulByNonresidue(b2), a2), // b² * Nonresidue + a²
|
|
448
451
|
second: Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b²
|
|
449
452
|
};
|
|
450
453
|
}
|
|
451
454
|
const Fp12 = {
|
|
452
|
-
ORDER: Fp2.ORDER,
|
|
455
|
+
ORDER: Fp2.ORDER, // TODO: unused, but need to verify
|
|
453
456
|
BITS: 2 * Fp2.BITS,
|
|
454
457
|
BYTES: 2 * Fp2.BYTES,
|
|
455
458
|
MASK: (0, utils_js_1.bitMask)(2 * Fp2.BITS),
|
|
@@ -524,7 +527,7 @@ const Fp12 = {
|
|
|
524
527
|
let t0 = Fp6.multiplyBy01(c0, o0, o1);
|
|
525
528
|
let t1 = Fp6.multiplyBy1(c1, o4);
|
|
526
529
|
return {
|
|
527
|
-
c0: Fp6.add(Fp6.mulByNonresidue(t1), t0),
|
|
530
|
+
c0: Fp6.add(Fp6.mulByNonresidue(t1), t0), // T1 * v + T0
|
|
528
531
|
// (c1 + c0) * [o0, o1+o4] - T0 - T1
|
|
529
532
|
c1: Fp6.sub(Fp6.sub(Fp6.multiplyBy01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0), t1),
|
|
530
533
|
};
|
|
@@ -547,13 +550,13 @@ const Fp12 = {
|
|
|
547
550
|
let t9 = Fp2.mulByNonresidue(t8); // T8 * (u + 1)
|
|
548
551
|
return {
|
|
549
552
|
c0: Fp6.create({
|
|
550
|
-
c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3),
|
|
551
|
-
c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5),
|
|
553
|
+
c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3
|
|
554
|
+
c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5
|
|
552
555
|
c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7),
|
|
553
|
-
}),
|
|
556
|
+
}), // 2 * (T7 - c0c2) + T7
|
|
554
557
|
c1: Fp6.create({
|
|
555
|
-
c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9),
|
|
556
|
-
c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4),
|
|
558
|
+
c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9
|
|
559
|
+
c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4
|
|
557
560
|
c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6),
|
|
558
561
|
}),
|
|
559
562
|
}; // 2 * (T6 + c1c2) + T6
|
|
@@ -779,8 +782,8 @@ const isogenyMapG1 = (0, hash_to_curve_js_1.isogenyMap)(Fp, [
|
|
|
779
782
|
].map((i) => i.map((j) => BigInt(j))));
|
|
780
783
|
// SWU Map - Fp2 to G2': y² = x³ + 240i * x + 1012 + 1012i
|
|
781
784
|
const G2_SWU = (0, weierstrass_js_1.mapToCurveSimpleSWU)(Fp2, {
|
|
782
|
-
A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(BigInt(240)) }),
|
|
783
|
-
B: Fp2.create({ c0: Fp.create(BigInt(1012)), c1: Fp.create(BigInt(1012)) }),
|
|
785
|
+
A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(BigInt(240)) }), // A' = 240 * I
|
|
786
|
+
B: Fp2.create({ c0: Fp.create(BigInt(1012)), c1: Fp.create(BigInt(1012)) }), // B' = 1012 * (1 + I)
|
|
784
787
|
Z: Fp2.create({ c0: Fp.create(BigInt(-2)), c1: Fp.create(BigInt(-1)) }), // Z: -(2 + I)
|
|
785
788
|
});
|
|
786
789
|
// Optimized SWU Map - Fp to G1
|
|
@@ -853,11 +856,39 @@ const htfDefaults = Object.freeze({
|
|
|
853
856
|
});
|
|
854
857
|
// Encoding utils
|
|
855
858
|
// Point on G1 curve: (x, y)
|
|
856
|
-
const C_BIT_POS = Fp.BITS; // C_bit, compression bit for serialization flag
|
|
857
|
-
const I_BIT_POS = Fp.BITS + 1; // I_bit, point-at-infinity bit for serialization flag
|
|
858
|
-
const S_BIT_POS = Fp.BITS + 2; // S_bit, sign bit for serialization flag
|
|
859
859
|
// Compressed point of infinity
|
|
860
|
-
const COMPRESSED_ZERO = Fp.toBytes(
|
|
860
|
+
const COMPRESSED_ZERO = setMask(Fp.toBytes(_0n), { infinity: true, compressed: true }); // set compressed & point-at-infinity bits
|
|
861
|
+
function parseMask(bytes) {
|
|
862
|
+
// Copy, so we can remove mask data. It will be removed also later, when Fp.create will call modulo.
|
|
863
|
+
bytes = bytes.slice();
|
|
864
|
+
const mask = bytes[0] & 224;
|
|
865
|
+
const compressed = !!((mask >> 7) & 1); // compression bit (0b1000_0000)
|
|
866
|
+
const infinity = !!((mask >> 6) & 1); // point at infinity bit (0b0100_0000)
|
|
867
|
+
const sort = !!((mask >> 5) & 1); // sort bit (0b0010_0000)
|
|
868
|
+
bytes[0] &= 31; // clear mask (zero first 3 bits)
|
|
869
|
+
return { compressed, infinity, sort, value: bytes };
|
|
870
|
+
}
|
|
871
|
+
function setMask(bytes, mask) {
|
|
872
|
+
if (bytes[0] & 224)
|
|
873
|
+
throw new Error('setMask: non-empty mask');
|
|
874
|
+
if (mask.compressed)
|
|
875
|
+
bytes[0] |= 128;
|
|
876
|
+
if (mask.infinity)
|
|
877
|
+
bytes[0] |= 64;
|
|
878
|
+
if (mask.sort)
|
|
879
|
+
bytes[0] |= 32;
|
|
880
|
+
return bytes;
|
|
881
|
+
}
|
|
882
|
+
function signatureG1ToRawBytes(point) {
|
|
883
|
+
point.assertValidity();
|
|
884
|
+
const isZero = point.equals(exports.bls12_381.G1.ProjectivePoint.ZERO);
|
|
885
|
+
const { x, y } = point.toAffine();
|
|
886
|
+
if (isZero)
|
|
887
|
+
return COMPRESSED_ZERO.slice();
|
|
888
|
+
const P = Fp.ORDER;
|
|
889
|
+
const sort = Boolean((y * _2n) / P);
|
|
890
|
+
return setMask((0, utils_js_1.numberToBytesBE)(x, Fp.BYTES), { compressed: true, sort });
|
|
891
|
+
}
|
|
861
892
|
function signatureG2ToRawBytes(point) {
|
|
862
893
|
// NOTE: by some reasons it was missed in bls12-381, looks like bug
|
|
863
894
|
point.assertValidity();
|
|
@@ -868,10 +899,9 @@ function signatureG2ToRawBytes(point) {
|
|
|
868
899
|
const { re: x0, im: x1 } = Fp2.reim(x);
|
|
869
900
|
const { re: y0, im: y1 } = Fp2.reim(y);
|
|
870
901
|
const tmp = y1 > _0n ? y1 * _2n : y0 * _2n;
|
|
871
|
-
const
|
|
872
|
-
const z1 = (0, utils_js_1.bitSet)((0, utils_js_1.bitSet)(x1, 381, aflag1), S_BIT_POS, true);
|
|
902
|
+
const sort = Boolean((tmp / Fp.ORDER) & _1n);
|
|
873
903
|
const z2 = x0;
|
|
874
|
-
return (0, utils_js_1.concatBytes)((0, utils_js_1.numberToBytesBE)(
|
|
904
|
+
return (0, utils_js_1.concatBytes)(setMask((0, utils_js_1.numberToBytesBE)(x1, len), { sort, compressed: true }), (0, utils_js_1.numberToBytesBE)(z2, len));
|
|
875
905
|
}
|
|
876
906
|
// To verify curve parameters, see pairing-friendly-curves spec:
|
|
877
907
|
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-11
|
|
@@ -905,7 +935,7 @@ exports.bls12_381 = (0, bls_js_1.bls)({
|
|
|
905
935
|
Gy: BigInt('0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1'),
|
|
906
936
|
a: Fp.ZERO,
|
|
907
937
|
b: _4n,
|
|
908
|
-
htfDefaults: { ...htfDefaults, m: 1 },
|
|
938
|
+
htfDefaults: { ...htfDefaults, m: 1, DST: 'BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_' },
|
|
909
939
|
wrapPrivateKey: true,
|
|
910
940
|
allowInfinityPoint: true,
|
|
911
941
|
// Checks is the point resides in prime-order subgroup.
|
|
@@ -943,31 +973,35 @@ exports.bls12_381 = (0, bls_js_1.bls)({
|
|
|
943
973
|
return isogenyMapG1(x, y);
|
|
944
974
|
},
|
|
945
975
|
fromBytes: (bytes) => {
|
|
946
|
-
|
|
947
|
-
if (
|
|
976
|
+
const { compressed, infinity, sort, value } = parseMask(bytes);
|
|
977
|
+
if (value.length === 48 && compressed) {
|
|
948
978
|
// TODO: Fp.bytes
|
|
949
979
|
const P = Fp.ORDER;
|
|
950
|
-
const compressedValue = (0, utils_js_1.bytesToNumberBE)(
|
|
951
|
-
const bflag = (0, utils_js_1.bitGet)(compressedValue, I_BIT_POS);
|
|
980
|
+
const compressedValue = (0, utils_js_1.bytesToNumberBE)(value);
|
|
952
981
|
// Zero
|
|
953
|
-
if (bflag === _1n)
|
|
954
|
-
return { x: _0n, y: _0n };
|
|
955
982
|
const x = Fp.create(compressedValue & Fp.MASK);
|
|
983
|
+
if (infinity) {
|
|
984
|
+
if (x !== _0n)
|
|
985
|
+
throw new Error('G1: non-empty compressed point at infinity');
|
|
986
|
+
return { x: _0n, y: _0n };
|
|
987
|
+
}
|
|
956
988
|
const right = Fp.add(Fp.pow(x, _3n), Fp.create(exports.bls12_381.params.G1b)); // y² = x³ + b
|
|
957
989
|
let y = Fp.sqrt(right);
|
|
958
990
|
if (!y)
|
|
959
991
|
throw new Error('Invalid compressed G1 point');
|
|
960
|
-
|
|
961
|
-
if ((y * _2n) / P !== aflag)
|
|
992
|
+
if ((y * _2n) / P !== BigInt(sort))
|
|
962
993
|
y = Fp.neg(y);
|
|
963
994
|
return { x: Fp.create(x), y: Fp.create(y) };
|
|
964
995
|
}
|
|
965
|
-
else if (
|
|
996
|
+
else if (value.length === 96 && !compressed) {
|
|
966
997
|
// Check if the infinity flag is set
|
|
967
|
-
|
|
998
|
+
const x = (0, utils_js_1.bytesToNumberBE)(value.subarray(0, Fp.BYTES));
|
|
999
|
+
const y = (0, utils_js_1.bytesToNumberBE)(value.subarray(Fp.BYTES));
|
|
1000
|
+
if (infinity) {
|
|
1001
|
+
if (x !== _0n || y !== _0n)
|
|
1002
|
+
throw new Error('G1: non-empty point at infinity');
|
|
968
1003
|
return exports.bls12_381.G1.ProjectivePoint.ZERO.toAffine();
|
|
969
|
-
|
|
970
|
-
const y = (0, utils_js_1.bytesToNumberBE)(bytes.subarray(Fp.BYTES));
|
|
1004
|
+
}
|
|
971
1005
|
return { x: Fp.create(x), y: Fp.create(y) };
|
|
972
1006
|
}
|
|
973
1007
|
else {
|
|
@@ -981,10 +1015,8 @@ exports.bls12_381 = (0, bls_js_1.bls)({
|
|
|
981
1015
|
if (isZero)
|
|
982
1016
|
return COMPRESSED_ZERO.slice();
|
|
983
1017
|
const P = Fp.ORDER;
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
num = (0, utils_js_1.bitSet)(num, S_BIT_POS, true);
|
|
987
|
-
return (0, utils_js_1.numberToBytesBE)(num, Fp.BYTES);
|
|
1018
|
+
const sort = Boolean((y * _2n) / P);
|
|
1019
|
+
return setMask((0, utils_js_1.numberToBytesBE)(x, Fp.BYTES), { compressed: true, sort });
|
|
988
1020
|
}
|
|
989
1021
|
else {
|
|
990
1022
|
if (isZero) {
|
|
@@ -997,6 +1029,33 @@ exports.bls12_381 = (0, bls_js_1.bls)({
|
|
|
997
1029
|
}
|
|
998
1030
|
}
|
|
999
1031
|
},
|
|
1032
|
+
ShortSignature: {
|
|
1033
|
+
fromHex(hex) {
|
|
1034
|
+
const { infinity, sort, value } = parseMask((0, utils_js_1.ensureBytes)('signatureHex', hex, 48));
|
|
1035
|
+
const P = Fp.ORDER;
|
|
1036
|
+
const compressedValue = (0, utils_js_1.bytesToNumberBE)(value);
|
|
1037
|
+
// Zero
|
|
1038
|
+
if (infinity)
|
|
1039
|
+
return exports.bls12_381.G1.ProjectivePoint.ZERO;
|
|
1040
|
+
const x = Fp.create(compressedValue & Fp.MASK);
|
|
1041
|
+
const right = Fp.add(Fp.pow(x, _3n), Fp.create(exports.bls12_381.params.G1b)); // y² = x³ + b
|
|
1042
|
+
let y = Fp.sqrt(right);
|
|
1043
|
+
if (!y)
|
|
1044
|
+
throw new Error('Invalid compressed G1 point');
|
|
1045
|
+
const aflag = BigInt(sort);
|
|
1046
|
+
if ((y * _2n) / P !== aflag)
|
|
1047
|
+
y = Fp.neg(y);
|
|
1048
|
+
const point = exports.bls12_381.G1.ProjectivePoint.fromAffine({ x, y });
|
|
1049
|
+
point.assertValidity();
|
|
1050
|
+
return point;
|
|
1051
|
+
},
|
|
1052
|
+
toRawBytes(point) {
|
|
1053
|
+
return signatureG1ToRawBytes(point);
|
|
1054
|
+
},
|
|
1055
|
+
toHex(point) {
|
|
1056
|
+
return (0, utils_js_1.bytesToHex)(signatureG1ToRawBytes(point));
|
|
1057
|
+
},
|
|
1058
|
+
},
|
|
1000
1059
|
},
|
|
1001
1060
|
// G2 is the order-q subgroup of E2(Fp²) : y² = x³+4(1+√−1),
|
|
1002
1061
|
// where Fp2 is Fp[√−1]/(x2+1). #E2(Fp2 ) = h2q, where
|
|
@@ -1056,45 +1115,45 @@ exports.bls12_381 = (0, bls_js_1.bls)({
|
|
|
1056
1115
|
return Q; // [x²-x-1]P + [x-1]Ψ(P) + Ψ²(2P)
|
|
1057
1116
|
},
|
|
1058
1117
|
fromBytes: (bytes) => {
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1118
|
+
const { compressed, infinity, sort, value } = parseMask(bytes);
|
|
1119
|
+
if ((!compressed && !infinity && sort) || // 00100000
|
|
1120
|
+
(!compressed && infinity && sort) || // 01100000
|
|
1121
|
+
(sort && infinity && compressed) // 11100000
|
|
1122
|
+
) {
|
|
1123
|
+
throw new Error('Invalid encoding flag: ' + (bytes[0] & 224));
|
|
1063
1124
|
}
|
|
1064
|
-
const bitC = m_byte & 0x80; // compression bit
|
|
1065
|
-
const bitI = m_byte & 0x40; // point at infinity bit
|
|
1066
|
-
const bitS = m_byte & 0x20; // sign bit
|
|
1067
1125
|
const L = Fp.BYTES;
|
|
1068
1126
|
const slc = (b, from, to) => (0, utils_js_1.bytesToNumberBE)(b.slice(from, to));
|
|
1069
|
-
if (
|
|
1127
|
+
if (value.length === 96 && compressed) {
|
|
1070
1128
|
const b = exports.bls12_381.params.G2b;
|
|
1071
1129
|
const P = Fp.ORDER;
|
|
1072
|
-
|
|
1073
|
-
if (bitI) {
|
|
1130
|
+
if (infinity) {
|
|
1074
1131
|
// check that all bytes are 0
|
|
1075
|
-
if (
|
|
1132
|
+
if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) {
|
|
1076
1133
|
throw new Error('Invalid compressed G2 point');
|
|
1077
1134
|
}
|
|
1078
1135
|
return { x: Fp2.ZERO, y: Fp2.ZERO };
|
|
1079
1136
|
}
|
|
1080
|
-
const x_1 = slc(
|
|
1081
|
-
const x_0 = slc(
|
|
1137
|
+
const x_1 = slc(value, 0, L);
|
|
1138
|
+
const x_0 = slc(value, L, 2 * L);
|
|
1082
1139
|
const x = Fp2.create({ c0: Fp.create(x_0), c1: Fp.create(x_1) });
|
|
1083
1140
|
const right = Fp2.add(Fp2.pow(x, _3n), b); // y² = x³ + 4 * (u+1) = x³ + b
|
|
1084
1141
|
let y = Fp2.sqrt(right);
|
|
1085
1142
|
const Y_bit = y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P ? _1n : _0n;
|
|
1086
|
-
y =
|
|
1143
|
+
y = sort && Y_bit > 0 ? y : Fp2.neg(y);
|
|
1087
1144
|
return { x, y };
|
|
1088
1145
|
}
|
|
1089
|
-
else if (
|
|
1090
|
-
|
|
1091
|
-
|
|
1146
|
+
else if (value.length === 192 && !compressed) {
|
|
1147
|
+
if (infinity) {
|
|
1148
|
+
if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) {
|
|
1149
|
+
throw new Error('Invalid uncompressed G2 point');
|
|
1150
|
+
}
|
|
1092
1151
|
return { x: Fp2.ZERO, y: Fp2.ZERO };
|
|
1093
1152
|
}
|
|
1094
|
-
const x1 = slc(
|
|
1095
|
-
const x0 = slc(
|
|
1096
|
-
const y1 = slc(
|
|
1097
|
-
const y0 = slc(
|
|
1153
|
+
const x1 = slc(value, 0, L);
|
|
1154
|
+
const x0 = slc(value, L, 2 * L);
|
|
1155
|
+
const y1 = slc(value, 2 * L, 3 * L);
|
|
1156
|
+
const y0 = slc(value, 3 * L, 4 * L);
|
|
1098
1157
|
return { x: Fp2.fromBigTuple([x0, x1]), y: Fp2.fromBigTuple([y0, y1]) };
|
|
1099
1158
|
}
|
|
1100
1159
|
else {
|
|
@@ -1109,10 +1168,7 @@ exports.bls12_381 = (0, bls_js_1.bls)({
|
|
|
1109
1168
|
if (isZero)
|
|
1110
1169
|
return (0, utils_js_1.concatBytes)(COMPRESSED_ZERO, (0, utils_js_1.numberToBytesBE)(_0n, len));
|
|
1111
1170
|
const flag = Boolean(y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P);
|
|
1112
|
-
|
|
1113
|
-
let x_1 = (0, utils_js_1.bitSet)(x.c1, C_BIT_POS, flag);
|
|
1114
|
-
x_1 = (0, utils_js_1.bitSet)(x_1, S_BIT_POS, true);
|
|
1115
|
-
return (0, utils_js_1.concatBytes)((0, utils_js_1.numberToBytesBE)(x_1, len), (0, utils_js_1.numberToBytesBE)(x.c0, len));
|
|
1171
|
+
return (0, utils_js_1.concatBytes)(setMask((0, utils_js_1.numberToBytesBE)(x.c1, len), { compressed: true, sort: flag }), (0, utils_js_1.numberToBytesBE)(x.c0, len));
|
|
1116
1172
|
}
|
|
1117
1173
|
else {
|
|
1118
1174
|
if (isZero)
|
|
@@ -1125,16 +1181,15 @@ exports.bls12_381 = (0, bls_js_1.bls)({
|
|
|
1125
1181
|
Signature: {
|
|
1126
1182
|
// TODO: Optimize, it's very slow because of sqrt.
|
|
1127
1183
|
fromHex(hex) {
|
|
1128
|
-
|
|
1184
|
+
const { infinity, sort, value } = parseMask((0, utils_js_1.ensureBytes)('signatureHex', hex));
|
|
1129
1185
|
const P = Fp.ORDER;
|
|
1130
1186
|
const half = hex.length / 2;
|
|
1131
1187
|
if (half !== 48 && half !== 96)
|
|
1132
1188
|
throw new Error('Invalid compressed signature length, must be 96 or 192');
|
|
1133
|
-
const z1 = (0, utils_js_1.bytesToNumberBE)(
|
|
1134
|
-
const z2 = (0, utils_js_1.bytesToNumberBE)(
|
|
1189
|
+
const z1 = (0, utils_js_1.bytesToNumberBE)(value.slice(0, half));
|
|
1190
|
+
const z2 = (0, utils_js_1.bytesToNumberBE)(value.slice(half));
|
|
1135
1191
|
// Indicates the infinity point
|
|
1136
|
-
|
|
1137
|
-
if (bflag1 === _1n)
|
|
1192
|
+
if (infinity)
|
|
1138
1193
|
return exports.bls12_381.G2.ProjectivePoint.ZERO;
|
|
1139
1194
|
const x1 = Fp.create(z1 & Fp.MASK);
|
|
1140
1195
|
const x2 = Fp.create(z2);
|
|
@@ -1147,7 +1202,7 @@ exports.bls12_381 = (0, bls_js_1.bls)({
|
|
|
1147
1202
|
// Choose the y whose leftmost bit of the imaginary part is equal to the a_flag1
|
|
1148
1203
|
// If y1 happens to be zero, then use the bit of y0
|
|
1149
1204
|
const { re: y0, im: y1 } = Fp2.reim(y);
|
|
1150
|
-
const aflag1 = (
|
|
1205
|
+
const aflag1 = BigInt(sort);
|
|
1151
1206
|
const isGreater = y1 > _0n && (y1 * _2n) / P !== aflag1;
|
|
1152
1207
|
const isZero = y1 === _0n && (y0 * _2n) / P !== aflag1;
|
|
1153
1208
|
if (isGreater || isZero)
|
|
@@ -1165,7 +1220,7 @@ exports.bls12_381 = (0, bls_js_1.bls)({
|
|
|
1165
1220
|
},
|
|
1166
1221
|
},
|
|
1167
1222
|
params: {
|
|
1168
|
-
x: BLS_X,
|
|
1223
|
+
x: BLS_X, // The BLS parameter x for BLS12-381
|
|
1169
1224
|
r: Fr.ORDER, // order; z⁴ − z² + 1; CURVE.n from other curves
|
|
1170
1225
|
},
|
|
1171
1226
|
htfDefaults,
|