@noble/curves 1.1.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 +295 -258
- package/abstract/bls.d.ts +27 -10
- package/abstract/bls.d.ts.map +1 -1
- package/abstract/bls.js +60 -10
- 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 +2 -2
- package/abstract/hash-to-curve.d.ts.map +1 -1
- package/abstract/hash-to-curve.js +22 -16
- package/abstract/hash-to-curve.js.map +1 -1
- package/abstract/modular.d.ts +51 -11
- package/abstract/modular.d.ts.map +1 -1
- package/abstract/modular.js +79 -21
- 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.d.ts.map +1 -1
- package/abstract/poseidon.js +39 -41
- package/abstract/poseidon.js.map +1 -1
- package/abstract/utils.d.ts +3 -1
- package/abstract/utils.d.ts.map +1 -1
- package/abstract/utils.js +56 -31
- package/abstract/utils.js.map +1 -1
- package/abstract/weierstrass.d.ts +25 -28
- package/abstract/weierstrass.d.ts.map +1 -1
- package/abstract/weierstrass.js +17 -15
- package/abstract/weierstrass.js.map +1 -1
- package/bls12-381.d.ts.map +1 -1
- package/bls12-381.js +142 -88
- 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 +5 -2
- package/ed25519.d.ts.map +1 -1
- package/ed25519.js +17 -8
- package/ed25519.js.map +1 -1
- package/ed448.d.ts +53 -2
- package/ed448.d.ts.map +1 -1
- package/ed448.js +216 -29
- package/ed448.js.map +1 -1
- package/esm/abstract/bls.js +61 -11
- 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 +23 -17
- package/esm/abstract/hash-to-curve.js.map +1 -1
- package/esm/abstract/modular.js +75 -20
- 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 +39 -41
- package/esm/abstract/poseidon.js.map +1 -1
- package/esm/abstract/utils.js +54 -30
- package/esm/abstract/utils.js.map +1 -1
- package/esm/abstract/weierstrass.js +17 -15
- package/esm/abstract/weierstrass.js.map +1 -1
- package/esm/bls12-381.js +143 -89
- 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 +17 -8
- package/esm/ed25519.js.map +1 -1
- package/esm/ed448.js +218 -32
- package/esm/ed448.js.map +1 -1
- package/esm/jubjub.js +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/package.json +1 -4
- 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 +7 -6
- package/secp256k1.js +6 -6
- package/secp256k1.js.map +1 -1
- package/src/abstract/bls.ts +120 -22
- package/src/abstract/hash-to-curve.ts +24 -17
- package/src/abstract/modular.ts +81 -22
- package/src/abstract/montgomery.ts +4 -6
- package/src/abstract/poseidon.ts +39 -40
- package/src/abstract/utils.ts +55 -26
- package/src/abstract/weierstrass.ts +29 -18
- package/src/bls12-381.ts +132 -75
- package/src/bn254.ts +3 -2
- package/src/ed25519.ts +19 -8
- package/src/ed448.ts +267 -34
- package/src/jubjub.ts +1 -1
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://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04),
|
|
14
|
-
// [hash-to-curve-12](https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-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");
|
|
@@ -151,7 +154,7 @@ const Fp2 = {
|
|
|
151
154
|
return x1;
|
|
152
155
|
return x2;
|
|
153
156
|
},
|
|
154
|
-
// Same as
|
|
157
|
+
// Same as sgn0_m_eq_2 in RFC 9380
|
|
155
158
|
isOdd: (x) => {
|
|
156
159
|
const { re: x0, im: x1 } = Fp2.reim(x);
|
|
157
160
|
const sign_0 = x0 % _2n;
|
|
@@ -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
|
|
@@ -638,8 +641,7 @@ const FP12_FROBENIUS_COEFFICIENTS = [
|
|
|
638
641
|
].map((n) => Fp2.fromBigTuple(n));
|
|
639
642
|
// END OF CURVE FIELDS
|
|
640
643
|
// HashToCurve
|
|
641
|
-
// 3-isogeny map from E' to E
|
|
642
|
-
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#appendix-E.3
|
|
644
|
+
// 3-isogeny map from E' to E https://www.rfc-editor.org/rfc/rfc9380#appendix-E.3
|
|
643
645
|
const isogenyMapG2 = (0, hash_to_curve_js_1.isogenyMap)(Fp2, [
|
|
644
646
|
// xNum
|
|
645
647
|
[
|
|
@@ -780,8 +782,8 @@ const isogenyMapG1 = (0, hash_to_curve_js_1.isogenyMap)(Fp, [
|
|
|
780
782
|
].map((i) => i.map((j) => BigInt(j))));
|
|
781
783
|
// SWU Map - Fp2 to G2': y² = x³ + 240i * x + 1012 + 1012i
|
|
782
784
|
const G2_SWU = (0, weierstrass_js_1.mapToCurveSimpleSWU)(Fp2, {
|
|
783
|
-
A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(BigInt(240)) }),
|
|
784
|
-
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)
|
|
785
787
|
Z: Fp2.create({ c0: Fp.create(BigInt(-2)), c1: Fp.create(BigInt(-1)) }), // Z: -(2 + I)
|
|
786
788
|
});
|
|
787
789
|
// Optimized SWU Map - Fp to G1
|
|
@@ -823,7 +825,7 @@ function G2psi2(c, P) {
|
|
|
823
825
|
//
|
|
824
826
|
// Parameter definitions are in section 5.3 of the spec unless otherwise noted.
|
|
825
827
|
// Parameter values come from section 8.8.2 of the spec.
|
|
826
|
-
// https://
|
|
828
|
+
// https://www.rfc-editor.org/rfc/rfc9380#section-8.8.2
|
|
827
829
|
//
|
|
828
830
|
// Base field F is GF(p^m)
|
|
829
831
|
// p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
|
|
@@ -854,11 +856,39 @@ const htfDefaults = Object.freeze({
|
|
|
854
856
|
});
|
|
855
857
|
// Encoding utils
|
|
856
858
|
// Point on G1 curve: (x, y)
|
|
857
|
-
const C_BIT_POS = Fp.BITS; // C_bit, compression bit for serialization flag
|
|
858
|
-
const I_BIT_POS = Fp.BITS + 1; // I_bit, point-at-infinity bit for serialization flag
|
|
859
|
-
const S_BIT_POS = Fp.BITS + 2; // S_bit, sign bit for serialization flag
|
|
860
859
|
// Compressed point of infinity
|
|
861
|
-
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
|
+
}
|
|
862
892
|
function signatureG2ToRawBytes(point) {
|
|
863
893
|
// NOTE: by some reasons it was missed in bls12-381, looks like bug
|
|
864
894
|
point.assertValidity();
|
|
@@ -869,13 +899,12 @@ function signatureG2ToRawBytes(point) {
|
|
|
869
899
|
const { re: x0, im: x1 } = Fp2.reim(x);
|
|
870
900
|
const { re: y0, im: y1 } = Fp2.reim(y);
|
|
871
901
|
const tmp = y1 > _0n ? y1 * _2n : y0 * _2n;
|
|
872
|
-
const
|
|
873
|
-
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);
|
|
874
903
|
const z2 = x0;
|
|
875
|
-
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));
|
|
876
905
|
}
|
|
877
906
|
// To verify curve parameters, see pairing-friendly-curves spec:
|
|
878
|
-
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-
|
|
907
|
+
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-11
|
|
879
908
|
// Basic math is done over finite fields over p.
|
|
880
909
|
// More complicated math is done over polynominal extension fields.
|
|
881
910
|
// To simplify calculations in Fp12, we construct extension tower:
|
|
@@ -906,7 +935,7 @@ exports.bls12_381 = (0, bls_js_1.bls)({
|
|
|
906
935
|
Gy: BigInt('0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1'),
|
|
907
936
|
a: Fp.ZERO,
|
|
908
937
|
b: _4n,
|
|
909
|
-
htfDefaults: { ...htfDefaults, m: 1 },
|
|
938
|
+
htfDefaults: { ...htfDefaults, m: 1, DST: 'BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_' },
|
|
910
939
|
wrapPrivateKey: true,
|
|
911
940
|
allowInfinityPoint: true,
|
|
912
941
|
// Checks is the point resides in prime-order subgroup.
|
|
@@ -935,7 +964,7 @@ exports.bls12_381 = (0, bls_js_1.bls)({
|
|
|
935
964
|
},
|
|
936
965
|
// Clear cofactor of G1
|
|
937
966
|
// https://eprint.iacr.org/2019/403
|
|
938
|
-
clearCofactor: (
|
|
967
|
+
clearCofactor: (_c, point) => {
|
|
939
968
|
// return this.multiplyUnsafe(CURVE.h);
|
|
940
969
|
return point.multiplyUnsafe(exports.bls12_381.params.x).add(point); // x*P + P
|
|
941
970
|
},
|
|
@@ -944,31 +973,35 @@ exports.bls12_381 = (0, bls_js_1.bls)({
|
|
|
944
973
|
return isogenyMapG1(x, y);
|
|
945
974
|
},
|
|
946
975
|
fromBytes: (bytes) => {
|
|
947
|
-
|
|
948
|
-
if (
|
|
976
|
+
const { compressed, infinity, sort, value } = parseMask(bytes);
|
|
977
|
+
if (value.length === 48 && compressed) {
|
|
949
978
|
// TODO: Fp.bytes
|
|
950
979
|
const P = Fp.ORDER;
|
|
951
|
-
const compressedValue = (0, utils_js_1.bytesToNumberBE)(
|
|
952
|
-
const bflag = (0, utils_js_1.bitGet)(compressedValue, I_BIT_POS);
|
|
980
|
+
const compressedValue = (0, utils_js_1.bytesToNumberBE)(value);
|
|
953
981
|
// Zero
|
|
954
|
-
if (bflag === _1n)
|
|
955
|
-
return { x: _0n, y: _0n };
|
|
956
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
|
+
}
|
|
957
988
|
const right = Fp.add(Fp.pow(x, _3n), Fp.create(exports.bls12_381.params.G1b)); // y² = x³ + b
|
|
958
989
|
let y = Fp.sqrt(right);
|
|
959
990
|
if (!y)
|
|
960
991
|
throw new Error('Invalid compressed G1 point');
|
|
961
|
-
|
|
962
|
-
if ((y * _2n) / P !== aflag)
|
|
992
|
+
if ((y * _2n) / P !== BigInt(sort))
|
|
963
993
|
y = Fp.neg(y);
|
|
964
994
|
return { x: Fp.create(x), y: Fp.create(y) };
|
|
965
995
|
}
|
|
966
|
-
else if (
|
|
996
|
+
else if (value.length === 96 && !compressed) {
|
|
967
997
|
// Check if the infinity flag is set
|
|
968
|
-
|
|
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');
|
|
969
1003
|
return exports.bls12_381.G1.ProjectivePoint.ZERO.toAffine();
|
|
970
|
-
|
|
971
|
-
const y = (0, utils_js_1.bytesToNumberBE)(bytes.subarray(Fp.BYTES));
|
|
1004
|
+
}
|
|
972
1005
|
return { x: Fp.create(x), y: Fp.create(y) };
|
|
973
1006
|
}
|
|
974
1007
|
else {
|
|
@@ -982,10 +1015,8 @@ exports.bls12_381 = (0, bls_js_1.bls)({
|
|
|
982
1015
|
if (isZero)
|
|
983
1016
|
return COMPRESSED_ZERO.slice();
|
|
984
1017
|
const P = Fp.ORDER;
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
num = (0, utils_js_1.bitSet)(num, S_BIT_POS, true);
|
|
988
|
-
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 });
|
|
989
1020
|
}
|
|
990
1021
|
else {
|
|
991
1022
|
if (isZero) {
|
|
@@ -998,6 +1029,33 @@ exports.bls12_381 = (0, bls_js_1.bls)({
|
|
|
998
1029
|
}
|
|
999
1030
|
}
|
|
1000
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
|
+
},
|
|
1001
1059
|
},
|
|
1002
1060
|
// G2 is the order-q subgroup of E2(Fp²) : y² = x³+4(1+√−1),
|
|
1003
1061
|
// where Fp2 is Fp[√−1]/(x2+1). #E2(Fp2 ) = h2q, where
|
|
@@ -1057,45 +1115,45 @@ exports.bls12_381 = (0, bls_js_1.bls)({
|
|
|
1057
1115
|
return Q; // [x²-x-1]P + [x-1]Ψ(P) + Ψ²(2P)
|
|
1058
1116
|
},
|
|
1059
1117
|
fromBytes: (bytes) => {
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
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));
|
|
1064
1124
|
}
|
|
1065
|
-
const bitC = m_byte & 0x80; // compression bit
|
|
1066
|
-
const bitI = m_byte & 0x40; // point at infinity bit
|
|
1067
|
-
const bitS = m_byte & 0x20; // sign bit
|
|
1068
1125
|
const L = Fp.BYTES;
|
|
1069
1126
|
const slc = (b, from, to) => (0, utils_js_1.bytesToNumberBE)(b.slice(from, to));
|
|
1070
|
-
if (
|
|
1127
|
+
if (value.length === 96 && compressed) {
|
|
1071
1128
|
const b = exports.bls12_381.params.G2b;
|
|
1072
1129
|
const P = Fp.ORDER;
|
|
1073
|
-
|
|
1074
|
-
if (bitI) {
|
|
1130
|
+
if (infinity) {
|
|
1075
1131
|
// check that all bytes are 0
|
|
1076
|
-
if (
|
|
1132
|
+
if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) {
|
|
1077
1133
|
throw new Error('Invalid compressed G2 point');
|
|
1078
1134
|
}
|
|
1079
1135
|
return { x: Fp2.ZERO, y: Fp2.ZERO };
|
|
1080
1136
|
}
|
|
1081
|
-
const x_1 = slc(
|
|
1082
|
-
const x_0 = slc(
|
|
1137
|
+
const x_1 = slc(value, 0, L);
|
|
1138
|
+
const x_0 = slc(value, L, 2 * L);
|
|
1083
1139
|
const x = Fp2.create({ c0: Fp.create(x_0), c1: Fp.create(x_1) });
|
|
1084
1140
|
const right = Fp2.add(Fp2.pow(x, _3n), b); // y² = x³ + 4 * (u+1) = x³ + b
|
|
1085
1141
|
let y = Fp2.sqrt(right);
|
|
1086
1142
|
const Y_bit = y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P ? _1n : _0n;
|
|
1087
|
-
y =
|
|
1143
|
+
y = sort && Y_bit > 0 ? y : Fp2.neg(y);
|
|
1088
1144
|
return { x, y };
|
|
1089
1145
|
}
|
|
1090
|
-
else if (
|
|
1091
|
-
|
|
1092
|
-
|
|
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
|
+
}
|
|
1093
1151
|
return { x: Fp2.ZERO, y: Fp2.ZERO };
|
|
1094
1152
|
}
|
|
1095
|
-
const x1 = slc(
|
|
1096
|
-
const x0 = slc(
|
|
1097
|
-
const y1 = slc(
|
|
1098
|
-
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);
|
|
1099
1157
|
return { x: Fp2.fromBigTuple([x0, x1]), y: Fp2.fromBigTuple([y0, y1]) };
|
|
1100
1158
|
}
|
|
1101
1159
|
else {
|
|
@@ -1110,10 +1168,7 @@ exports.bls12_381 = (0, bls_js_1.bls)({
|
|
|
1110
1168
|
if (isZero)
|
|
1111
1169
|
return (0, utils_js_1.concatBytes)(COMPRESSED_ZERO, (0, utils_js_1.numberToBytesBE)(_0n, len));
|
|
1112
1170
|
const flag = Boolean(y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P);
|
|
1113
|
-
|
|
1114
|
-
let x_1 = (0, utils_js_1.bitSet)(x.c1, C_BIT_POS, flag);
|
|
1115
|
-
x_1 = (0, utils_js_1.bitSet)(x_1, S_BIT_POS, true);
|
|
1116
|
-
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));
|
|
1117
1172
|
}
|
|
1118
1173
|
else {
|
|
1119
1174
|
if (isZero)
|
|
@@ -1126,16 +1181,15 @@ exports.bls12_381 = (0, bls_js_1.bls)({
|
|
|
1126
1181
|
Signature: {
|
|
1127
1182
|
// TODO: Optimize, it's very slow because of sqrt.
|
|
1128
1183
|
fromHex(hex) {
|
|
1129
|
-
|
|
1184
|
+
const { infinity, sort, value } = parseMask((0, utils_js_1.ensureBytes)('signatureHex', hex));
|
|
1130
1185
|
const P = Fp.ORDER;
|
|
1131
1186
|
const half = hex.length / 2;
|
|
1132
1187
|
if (half !== 48 && half !== 96)
|
|
1133
1188
|
throw new Error('Invalid compressed signature length, must be 96 or 192');
|
|
1134
|
-
const z1 = (0, utils_js_1.bytesToNumberBE)(
|
|
1135
|
-
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));
|
|
1136
1191
|
// Indicates the infinity point
|
|
1137
|
-
|
|
1138
|
-
if (bflag1 === _1n)
|
|
1192
|
+
if (infinity)
|
|
1139
1193
|
return exports.bls12_381.G2.ProjectivePoint.ZERO;
|
|
1140
1194
|
const x1 = Fp.create(z1 & Fp.MASK);
|
|
1141
1195
|
const x2 = Fp.create(z2);
|
|
@@ -1148,7 +1202,7 @@ exports.bls12_381 = (0, bls_js_1.bls)({
|
|
|
1148
1202
|
// Choose the y whose leftmost bit of the imaginary part is equal to the a_flag1
|
|
1149
1203
|
// If y1 happens to be zero, then use the bit of y0
|
|
1150
1204
|
const { re: y0, im: y1 } = Fp2.reim(y);
|
|
1151
|
-
const aflag1 = (
|
|
1205
|
+
const aflag1 = BigInt(sort);
|
|
1152
1206
|
const isGreater = y1 > _0n && (y1 * _2n) / P !== aflag1;
|
|
1153
1207
|
const isZero = y1 === _0n && (y0 * _2n) / P !== aflag1;
|
|
1154
1208
|
if (isGreater || isZero)
|
|
@@ -1166,7 +1220,7 @@ exports.bls12_381 = (0, bls_js_1.bls)({
|
|
|
1166
1220
|
},
|
|
1167
1221
|
},
|
|
1168
1222
|
params: {
|
|
1169
|
-
x: BLS_X,
|
|
1223
|
+
x: BLS_X, // The BLS parameter x for BLS12-381
|
|
1170
1224
|
r: Fr.ORDER, // order; z⁴ − z² + 1; CURVE.n from other curves
|
|
1171
1225
|
},
|
|
1172
1226
|
htfDefaults,
|