@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.
Files changed (89) hide show
  1. package/README.md +125 -191
  2. package/abstract/bls.d.ts +27 -10
  3. package/abstract/bls.d.ts.map +1 -1
  4. package/abstract/bls.js +58 -8
  5. package/abstract/bls.js.map +1 -1
  6. package/abstract/curve.js.map +1 -1
  7. package/abstract/edwards.js.map +1 -1
  8. package/abstract/hash-to-curve.d.ts +1 -1
  9. package/abstract/hash-to-curve.d.ts.map +1 -1
  10. package/abstract/hash-to-curve.js +8 -8
  11. package/abstract/hash-to-curve.js.map +1 -1
  12. package/abstract/modular.js.map +1 -1
  13. package/abstract/montgomery.d.ts.map +1 -1
  14. package/abstract/montgomery.js +5 -7
  15. package/abstract/montgomery.js.map +1 -1
  16. package/abstract/poseidon.js.map +1 -1
  17. package/abstract/utils.d.ts +2 -1
  18. package/abstract/utils.d.ts.map +1 -1
  19. package/abstract/utils.js +55 -31
  20. package/abstract/utils.js.map +1 -1
  21. package/abstract/weierstrass.d.ts +23 -27
  22. package/abstract/weierstrass.d.ts.map +1 -1
  23. package/abstract/weierstrass.js +4 -4
  24. package/abstract/weierstrass.js.map +1 -1
  25. package/bls12-381.d.ts.map +1 -1
  26. package/bls12-381.js +137 -82
  27. package/bls12-381.js.map +1 -1
  28. package/bn254.d.ts +3 -2
  29. package/bn254.d.ts.map +1 -1
  30. package/bn254.js +3 -2
  31. package/bn254.js.map +1 -1
  32. package/ed25519.d.ts +4 -2
  33. package/ed25519.d.ts.map +1 -1
  34. package/ed25519.js +8 -2
  35. package/ed25519.js.map +1 -1
  36. package/ed448.d.ts +4 -2
  37. package/ed448.d.ts.map +1 -1
  38. package/ed448.js +10 -1
  39. package/ed448.js.map +1 -1
  40. package/esm/abstract/bls.js +58 -8
  41. package/esm/abstract/bls.js.map +1 -1
  42. package/esm/abstract/curve.js.map +1 -1
  43. package/esm/abstract/edwards.js.map +1 -1
  44. package/esm/abstract/hash-to-curve.js +9 -9
  45. package/esm/abstract/hash-to-curve.js.map +1 -1
  46. package/esm/abstract/modular.js.map +1 -1
  47. package/esm/abstract/montgomery.js +5 -7
  48. package/esm/abstract/montgomery.js.map +1 -1
  49. package/esm/abstract/poseidon.js.map +1 -1
  50. package/esm/abstract/utils.js +53 -30
  51. package/esm/abstract/utils.js.map +1 -1
  52. package/esm/abstract/weierstrass.js +4 -4
  53. package/esm/abstract/weierstrass.js.map +1 -1
  54. package/esm/bls12-381.js +138 -83
  55. package/esm/bls12-381.js.map +1 -1
  56. package/esm/bn254.js +3 -2
  57. package/esm/bn254.js.map +1 -1
  58. package/esm/ed25519.js +8 -2
  59. package/esm/ed25519.js.map +1 -1
  60. package/esm/ed448.js +10 -1
  61. package/esm/ed448.js.map +1 -1
  62. package/esm/jubjub.js.map +1 -1
  63. package/esm/p256.js +2 -2
  64. package/esm/p256.js.map +1 -1
  65. package/esm/p384.js +2 -2
  66. package/esm/p384.js.map +1 -1
  67. package/esm/p521.js +3 -3
  68. package/esm/p521.js.map +1 -1
  69. package/esm/secp256k1.js +6 -6
  70. package/esm/secp256k1.js.map +1 -1
  71. package/jubjub.js.map +1 -1
  72. package/p256.js +2 -2
  73. package/p256.js.map +1 -1
  74. package/p384.js +2 -2
  75. package/p384.js.map +1 -1
  76. package/p521.js +3 -3
  77. package/p521.js.map +1 -1
  78. package/package.json +5 -5
  79. package/secp256k1.js +6 -6
  80. package/secp256k1.js.map +1 -1
  81. package/src/abstract/bls.ts +117 -19
  82. package/src/abstract/hash-to-curve.ts +10 -9
  83. package/src/abstract/montgomery.ts +4 -6
  84. package/src/abstract/utils.ts +52 -26
  85. package/src/abstract/weierstrass.ts +16 -7
  86. package/src/bls12-381.ts +127 -69
  87. package/src/bn254.ts +3 -2
  88. package/src/ed25519.ts +10 -2
  89. 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 allows to:
6
- // - Construct zk-SNARKs at the 128-bit security
7
- // - Use threshold signatures, which allows a user to sign lots of messages with one signature and
8
- // verify them swiftly in a batch, using Boneh-Lynn-Shacham signature scheme.
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
- // Filecoin uses little endian byte arrays for private keys -
31
- // so ensure to reverse byte order if you'll use it with FIL.
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((0, utils_js_1.bitSet)((0, utils_js_1.bitSet)(_0n, I_BIT_POS, true), S_BIT_POS, true)); // set compressed & point-at-infinity bits
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 aflag1 = Boolean((tmp / Fp.ORDER) & _1n);
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)(z1, len), (0, utils_js_1.numberToBytesBE)(z2, len));
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
- bytes = bytes.slice();
947
- if (bytes.length === 48) {
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)(bytes);
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
- const aflag = (0, utils_js_1.bitGet)(compressedValue, C_BIT_POS);
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 (bytes.length === 96) {
996
+ else if (value.length === 96 && !compressed) {
966
997
  // Check if the infinity flag is set
967
- if ((bytes[0] & (1 << 6)) !== 0)
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
- const x = (0, utils_js_1.bytesToNumberBE)(bytes.subarray(0, Fp.BYTES));
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
- let num;
985
- num = (0, utils_js_1.bitSet)(x, C_BIT_POS, Boolean((y * _2n) / P)); // set aflag
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
- bytes = bytes.slice();
1060
- const m_byte = bytes[0] & 0xe0;
1061
- if (m_byte === 0x20 || m_byte === 0x60 || m_byte === 0xe0) {
1062
- throw new Error('Invalid encoding flag: ' + m_byte);
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 (bytes.length === 96 && bitC) {
1127
+ if (value.length === 96 && compressed) {
1070
1128
  const b = exports.bls12_381.params.G2b;
1071
1129
  const P = Fp.ORDER;
1072
- bytes[0] = bytes[0] & 0x1f; // clear flags
1073
- if (bitI) {
1130
+ if (infinity) {
1074
1131
  // check that all bytes are 0
1075
- if (bytes.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) {
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(bytes, 0, L);
1081
- const x_0 = slc(bytes, L, 2 * L);
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 = bitS > 0 && Y_bit > 0 ? y : Fp2.neg(y);
1143
+ y = sort && Y_bit > 0 ? y : Fp2.neg(y);
1087
1144
  return { x, y };
1088
1145
  }
1089
- else if (bytes.length === 192 && !bitC) {
1090
- // Check if the infinity flag is set
1091
- if ((bytes[0] & (1 << 6)) !== 0) {
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(bytes, 0, L);
1095
- const x0 = slc(bytes, L, 2 * L);
1096
- const y1 = slc(bytes, 2 * L, 3 * L);
1097
- const y0 = slc(bytes, 3 * L, 4 * L);
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
- // set compressed & sign bits (looks like different offsets than for G1/Fp?)
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
- hex = (0, utils_js_1.ensureBytes)('signatureHex', hex);
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)(hex.slice(0, half));
1134
- const z2 = (0, utils_js_1.bytesToNumberBE)(hex.slice(half));
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
- const bflag1 = (0, utils_js_1.bitGet)(z1, I_BIT_POS);
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 = (0, utils_js_1.bitGet)(z1, 381);
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,