@noble/curves 1.9.1 → 1.9.2

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 (189) hide show
  1. package/README.md +56 -25
  2. package/_shortw_utils.d.ts +7 -5
  3. package/_shortw_utils.d.ts.map +1 -1
  4. package/_shortw_utils.js +2 -8
  5. package/_shortw_utils.js.map +1 -1
  6. package/abstract/bls.d.ts +60 -24
  7. package/abstract/bls.d.ts.map +1 -1
  8. package/abstract/bls.js +158 -109
  9. package/abstract/bls.js.map +1 -1
  10. package/abstract/curve.d.ts +44 -9
  11. package/abstract/curve.d.ts.map +1 -1
  12. package/abstract/curve.js +86 -7
  13. package/abstract/curve.js.map +1 -1
  14. package/abstract/edwards.d.ts +112 -25
  15. package/abstract/edwards.d.ts.map +1 -1
  16. package/abstract/edwards.js +138 -102
  17. package/abstract/edwards.js.map +1 -1
  18. package/abstract/fft.d.ts +12 -10
  19. package/abstract/fft.d.ts.map +1 -1
  20. package/abstract/fft.js +12 -13
  21. package/abstract/fft.js.map +1 -1
  22. package/abstract/hash-to-curve.d.ts +25 -11
  23. package/abstract/hash-to-curve.d.ts.map +1 -1
  24. package/abstract/hash-to-curve.js +17 -14
  25. package/abstract/hash-to-curve.js.map +1 -1
  26. package/abstract/modular.d.ts +24 -11
  27. package/abstract/modular.d.ts.map +1 -1
  28. package/abstract/modular.js +49 -20
  29. package/abstract/modular.js.map +1 -1
  30. package/abstract/montgomery.d.ts +1 -1
  31. package/abstract/montgomery.d.ts.map +1 -1
  32. package/abstract/montgomery.js +5 -4
  33. package/abstract/montgomery.js.map +1 -1
  34. package/abstract/poseidon.d.ts +5 -13
  35. package/abstract/poseidon.d.ts.map +1 -1
  36. package/abstract/poseidon.js +12 -7
  37. package/abstract/poseidon.js.map +1 -1
  38. package/abstract/tower.d.ts +20 -46
  39. package/abstract/tower.d.ts.map +1 -1
  40. package/abstract/tower.js +9 -3
  41. package/abstract/tower.js.map +1 -1
  42. package/abstract/utils.d.ts +1 -115
  43. package/abstract/utils.d.ts.map +1 -1
  44. package/abstract/utils.js +17 -371
  45. package/abstract/utils.js.map +1 -1
  46. package/abstract/weierstrass.d.ts +132 -76
  47. package/abstract/weierstrass.d.ts.map +1 -1
  48. package/abstract/weierstrass.js +462 -398
  49. package/abstract/weierstrass.js.map +1 -1
  50. package/bls12-381.d.ts +2 -0
  51. package/bls12-381.d.ts.map +1 -1
  52. package/bls12-381.js +504 -466
  53. package/bls12-381.js.map +1 -1
  54. package/bn254.d.ts +2 -0
  55. package/bn254.d.ts.map +1 -1
  56. package/bn254.js +44 -32
  57. package/bn254.js.map +1 -1
  58. package/ed25519.d.ts +8 -5
  59. package/ed25519.d.ts.map +1 -1
  60. package/ed25519.js +67 -54
  61. package/ed25519.js.map +1 -1
  62. package/ed448.d.ts +10 -6
  63. package/ed448.d.ts.map +1 -1
  64. package/ed448.js +80 -57
  65. package/ed448.js.map +1 -1
  66. package/esm/_shortw_utils.d.ts +7 -5
  67. package/esm/_shortw_utils.d.ts.map +1 -1
  68. package/esm/_shortw_utils.js +2 -8
  69. package/esm/_shortw_utils.js.map +1 -1
  70. package/esm/abstract/bls.d.ts +60 -24
  71. package/esm/abstract/bls.d.ts.map +1 -1
  72. package/esm/abstract/bls.js +158 -109
  73. package/esm/abstract/bls.js.map +1 -1
  74. package/esm/abstract/curve.d.ts +44 -9
  75. package/esm/abstract/curve.d.ts.map +1 -1
  76. package/esm/abstract/curve.js +83 -8
  77. package/esm/abstract/curve.js.map +1 -1
  78. package/esm/abstract/edwards.d.ts +112 -25
  79. package/esm/abstract/edwards.d.ts.map +1 -1
  80. package/esm/abstract/edwards.js +138 -104
  81. package/esm/abstract/edwards.js.map +1 -1
  82. package/esm/abstract/fft.d.ts +12 -10
  83. package/esm/abstract/fft.d.ts.map +1 -1
  84. package/esm/abstract/fft.js +10 -11
  85. package/esm/abstract/fft.js.map +1 -1
  86. package/esm/abstract/hash-to-curve.d.ts +25 -11
  87. package/esm/abstract/hash-to-curve.d.ts.map +1 -1
  88. package/esm/abstract/hash-to-curve.js +17 -14
  89. package/esm/abstract/hash-to-curve.js.map +1 -1
  90. package/esm/abstract/modular.d.ts +24 -11
  91. package/esm/abstract/modular.d.ts.map +1 -1
  92. package/esm/abstract/modular.js +48 -19
  93. package/esm/abstract/modular.js.map +1 -1
  94. package/esm/abstract/montgomery.d.ts +1 -1
  95. package/esm/abstract/montgomery.d.ts.map +1 -1
  96. package/esm/abstract/montgomery.js +5 -4
  97. package/esm/abstract/montgomery.js.map +1 -1
  98. package/esm/abstract/poseidon.d.ts +5 -13
  99. package/esm/abstract/poseidon.d.ts.map +1 -1
  100. package/esm/abstract/poseidon.js +12 -7
  101. package/esm/abstract/poseidon.js.map +1 -1
  102. package/esm/abstract/tower.d.ts +20 -46
  103. package/esm/abstract/tower.d.ts.map +1 -1
  104. package/esm/abstract/tower.js +9 -3
  105. package/esm/abstract/tower.js.map +1 -1
  106. package/esm/abstract/utils.d.ts +1 -115
  107. package/esm/abstract/utils.d.ts.map +1 -1
  108. package/esm/abstract/utils.js +3 -344
  109. package/esm/abstract/utils.js.map +1 -1
  110. package/esm/abstract/weierstrass.d.ts +132 -76
  111. package/esm/abstract/weierstrass.d.ts.map +1 -1
  112. package/esm/abstract/weierstrass.js +460 -400
  113. package/esm/abstract/weierstrass.js.map +1 -1
  114. package/esm/bls12-381.d.ts +2 -0
  115. package/esm/bls12-381.d.ts.map +1 -1
  116. package/esm/bls12-381.js +503 -465
  117. package/esm/bls12-381.js.map +1 -1
  118. package/esm/bn254.d.ts +2 -0
  119. package/esm/bn254.d.ts.map +1 -1
  120. package/esm/bn254.js +41 -29
  121. package/esm/bn254.js.map +1 -1
  122. package/esm/ed25519.d.ts +8 -5
  123. package/esm/ed25519.d.ts.map +1 -1
  124. package/esm/ed25519.js +62 -49
  125. package/esm/ed25519.js.map +1 -1
  126. package/esm/ed448.d.ts +10 -6
  127. package/esm/ed448.d.ts.map +1 -1
  128. package/esm/ed448.js +74 -51
  129. package/esm/ed448.js.map +1 -1
  130. package/esm/misc.d.ts.map +1 -1
  131. package/esm/misc.js +31 -26
  132. package/esm/misc.js.map +1 -1
  133. package/esm/nist.d.ts +7 -16
  134. package/esm/nist.d.ts.map +1 -1
  135. package/esm/nist.js +86 -97
  136. package/esm/nist.js.map +1 -1
  137. package/esm/p256.d.ts +3 -3
  138. package/esm/p384.d.ts +3 -3
  139. package/esm/p521.d.ts +3 -3
  140. package/esm/secp256k1.d.ts +6 -6
  141. package/esm/secp256k1.d.ts.map +1 -1
  142. package/esm/secp256k1.js +43 -40
  143. package/esm/secp256k1.js.map +1 -1
  144. package/esm/utils.d.ts +96 -0
  145. package/esm/utils.d.ts.map +1 -0
  146. package/esm/utils.js +279 -0
  147. package/esm/utils.js.map +1 -0
  148. package/misc.d.ts.map +1 -1
  149. package/misc.js +35 -30
  150. package/misc.js.map +1 -1
  151. package/nist.d.ts +7 -16
  152. package/nist.d.ts.map +1 -1
  153. package/nist.js +86 -97
  154. package/nist.js.map +1 -1
  155. package/p256.d.ts +3 -3
  156. package/p384.d.ts +3 -3
  157. package/p521.d.ts +3 -3
  158. package/package.json +14 -5
  159. package/secp256k1.d.ts +6 -6
  160. package/secp256k1.d.ts.map +1 -1
  161. package/secp256k1.js +46 -43
  162. package/secp256k1.js.map +1 -1
  163. package/src/_shortw_utils.ts +5 -15
  164. package/src/abstract/bls.ts +260 -145
  165. package/src/abstract/curve.ts +115 -13
  166. package/src/abstract/edwards.ts +279 -138
  167. package/src/abstract/fft.ts +30 -19
  168. package/src/abstract/hash-to-curve.ts +51 -27
  169. package/src/abstract/modular.ts +49 -28
  170. package/src/abstract/montgomery.ts +9 -7
  171. package/src/abstract/poseidon.ts +22 -18
  172. package/src/abstract/tower.ts +36 -67
  173. package/src/abstract/utils.ts +3 -378
  174. package/src/abstract/weierstrass.ts +700 -453
  175. package/src/bls12-381.ts +540 -489
  176. package/src/bn254.ts +47 -35
  177. package/src/ed25519.ts +80 -64
  178. package/src/ed448.ts +129 -92
  179. package/src/misc.ts +39 -34
  180. package/src/nist.ts +138 -127
  181. package/src/p256.ts +3 -3
  182. package/src/p384.ts +3 -3
  183. package/src/p521.ts +3 -3
  184. package/src/secp256k1.ts +58 -46
  185. package/src/utils.ts +328 -0
  186. package/utils.d.ts +96 -0
  187. package/utils.d.ts.map +1 -0
  188. package/utils.js +313 -0
  189. package/utils.js.map +1 -0
package/bls12-381.js CHANGED
@@ -1,72 +1,89 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.bls12_381 = void 0;
3
+ exports.bls12_381 = exports.bls12_381_Fr = void 0;
4
4
  /**
5
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
6
+
7
+ * Construct zk-SNARKs at the ~120-bit security, as per [Barbulescu-Duquesne 2017](https://hal.science/hal-01534101/file/main.pdf)
8
+ * Efficiently verify N aggregate signatures with 1 pairing and N ec additions:
9
+ the Boneh-Lynn-Shacham signature scheme is orders of magnitude more efficient than Schnorr
10
+
11
+ BLS can mean 2 different things:
12
+
13
+ * Barreto-Lynn-Scott: BLS12, a Pairing Friendly Elliptic Curve
14
+ * Boneh-Lynn-Shacham: A Signature Scheme.
15
+
16
+ ### Summary
17
+
18
+ 1. BLS Relies on expensive bilinear pairing
19
+ 2. Private Keys: 32 bytes
20
+ 3. Public Keys: 48 OR 96 bytes - big-endian x coordinate of point on G1 OR G2 curve
21
+ 4. Signatures: 96 OR 48 bytes - big-endian x coordinate of point on G2 OR G1 curve
22
+ 5. The 12 stands for the Embedding degree.
23
+
24
+ Modes of operation:
25
+
26
+ * Long signatures: 48-byte keys + 96-byte sigs (G1 keys + G2 sigs).
27
+ * Short signatures: 96-byte keys + 48-byte sigs (G2 keys + G1 sigs).
28
+
29
+ ### Formulas
30
+
31
+ - `P = pk x G` - public keys
32
+ - `S = pk x H(m)` - signing, uses hash-to-curve on m
33
+ - `e(P, H(m)) == e(G, S)` - verification using pairings
34
+ - `e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))` - signature aggregation
35
+
36
+ ### Curves
37
+
38
+ G1 is ordinary elliptic curve. G2 is extension field curve, think "over complex numbers".
39
+
40
+ - G1: y² = x³ + 4
41
+ - G2: y² = x³ + 4(u + 1) where u = √−1; r-order subgroup of E'(Fp²), M-type twist
42
+
43
+ ### Towers
44
+
45
+ Pairing G1 + G2 produces element in Fp₁₂, 12-degree polynomial.
46
+ Fp₁₂ is usually implemented using tower of lower-degree polynomials for speed.
47
+
48
+ - Fp₁₂ = Fp₆² => Fp₂³
49
+ - Fp(u) / (u² - β) where β = -1
50
+ - Fp₂(v) / (v³ - ξ) where ξ = u + 1
51
+ - Fp₆(w) / (w² - γ) where γ = v
52
+ - Fp²[u] = Fp/u²+1
53
+ - Fp⁶[v] = Fp²/v³-1-u
54
+ - Fp¹²[w] = Fp⁶/w²-v
55
+
56
+ ### Params
57
+
58
+ * Embedding degree (k): 12
59
+ * Seed is sometimes named x or t
60
+ * t = -15132376222941642752
61
+ * p = (t-1)² * (t⁴-t²+1)/3 + t
62
+ * r = t⁴-t²+1
63
+ * Ate loop size: X
64
+
65
+ To verify curve parameters, see
66
+ [pairing-friendly-curves spec](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-11).
67
+ Basic math is done over finite fields over p.
68
+ More complicated math is done over polynominal extension fields.
69
+
70
+ ### Compatibility and notes
71
+ 1. It is compatible with Algorand, Chia, Dfinity, Ethereum, Filecoin, ZEC.
72
+ Filecoin uses little endian byte arrays for private keys - make sure to reverse byte order.
73
+ 2. Make sure to correctly select mode: "long signature" or "short signature".
74
+ 3. Compatible with specs:
75
+ RFC 9380,
76
+ [cfrg-pairing-friendly-curves-11](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-11),
77
+ [cfrg-bls-signature-05](https://datatracker.ietf.org/doc/draft-irtf-cfrg-bls-signature/).
78
+
9
79
  *
10
- * ### Summary
11
- * 1. BLS Relies on Bilinear Pairing (expensive)
12
- * 2. Private Keys: 32 bytes
13
- * 3. Public Keys: 48 bytes: 381 bit affine x coordinate, encoded into 48 big-endian bytes.
14
- * 4. Signatures: 96 bytes: two 381 bit integers (affine x coordinate), encoded into two 48 big-endian byte arrays.
15
- * - The signature is a point on the G2 subgroup, which is defined over a finite field
16
- * with elements twice as big as the G1 curve (G2 is over Fp2 rather than Fp. Fp2 is analogous to the
17
- * complex numbers).
18
- * - We also support reversed 96-byte pubkeys & 48-byte short signatures.
19
- * 5. The 12 stands for the Embedding degree.
20
- *
21
- * ### Formulas
22
- * - `P = pk x G` - public keys
23
- * - `S = pk x H(m)` - signing
24
- * - `e(P, H(m)) == e(G, S)` - verification using pairings
25
- * - `e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))` - signature aggregation
26
- *
27
- * ### Compatibility and notes
28
- * 1. It is compatible with Algorand, Chia, Dfinity, Ethereum, Filecoin, ZEC.
29
- * Filecoin uses little endian byte arrays for private keys - make sure to reverse byte order.
30
- * 2. Some projects use G2 for public keys and G1 for signatures. It's called "short signature".
31
- * 3. Curve security level is about 120 bits as per [Barbulescu-Duquesne 2017](https://hal.science/hal-01534101/file/main.pdf)
32
- * 4. Compatible with specs:
33
- * [cfrg-pairing-friendly-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11),
34
- * [cfrg-bls-signature-05](https://www.rfc-editor.org/rfc/draft-irtf-cfrg-bls-signature-05),
35
- * RFC 9380.
36
- *
37
- * ### Params
38
- * To verify curve parameters, see
39
- * [pairing-friendly-curves spec](https://www.rfc-editor.org/rfc/draft-irtf-cfrg-pairing-friendly-curves-11).
40
- * Basic math is done over finite fields over p.
41
- * More complicated math is done over polynominal extension fields.
42
- * To simplify calculations in Fp12, we construct extension tower:
43
- *
44
- * Embedding degree (k): 12
45
- * Seed (X): -15132376222941642752
46
- * Fr: (x⁴-x²+1)
47
- * Fp: ((x-1)² ⋅ r(x)/3+x)
48
- * (E/Fp): Y²=X³+4
49
- * (Eₜ/Fp²): Y² = X³+4(u+1) (M-type twist)
50
- * Ate loop size: X
51
- *
52
- * ### Towers
53
- * - Fp₁₂ = Fp₆² => Fp₂³
54
- * - Fp(u) / (u² - β) where β = -1
55
- * - Fp₂(v) / (v³ - ξ) where ξ = u + 1
56
- * - Fp₆(w) / (w² - γ) where γ = v
57
- * - Fp²[u] = Fp/u²+1
58
- * - Fp⁶[v] = Fp²/v³-1-u
59
- * - Fp¹²[w] = Fp⁶/w²-v
60
- *
61
- * @todo construct bls & bn fp/fr from seed.
62
80
  * @module
63
81
  */
64
82
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
65
- const sha2_1 = require("@noble/hashes/sha2");
66
- const utils_1 = require("@noble/hashes/utils");
83
+ const sha2_js_1 = require("@noble/hashes/sha2.js");
67
84
  const bls_ts_1 = require("./abstract/bls.js");
68
85
  const modular_ts_1 = require("./abstract/modular.js");
69
- const utils_ts_1 = require("./abstract/utils.js");
86
+ const utils_ts_1 = require("./utils.js");
70
87
  // Types
71
88
  const hash_to_curve_ts_1 = require("./abstract/hash-to-curve.js");
72
89
  const tower_ts_1 = require("./abstract/tower.js");
@@ -74,13 +91,40 @@ const weierstrass_ts_1 = require("./abstract/weierstrass.js");
74
91
  // Be friendly to bad ECMAScript parsers by not using bigint literals
75
92
  // prettier-ignore
76
93
  const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);
94
+ // To verify math:
95
+ // https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11
77
96
  // The BLS parameter x (seed) for BLS12-381. NOTE: it is negative!
97
+ // x = -2^63 - 2^62 - 2^60 - 2^57 - 2^48 - 2^16
78
98
  const BLS_X = BigInt('0xd201000000010000');
99
+ // t = x (called differently in different places)
100
+ // const t = -BLS_X;
79
101
  const BLS_X_LEN = (0, utils_ts_1.bitLen)(BLS_X);
102
+ // a=0, b=4
103
+ // P is characteristic of field Fp, in which curve calculations are done.
104
+ // p = (t-1)² * (t⁴-t²+1)/3 + t
105
+ // bls12_381_Fp = (t-1n)**2n * (t**4n - t**2n + 1n) / 3n + t
106
+ // r*h is curve order, amount of points on curve,
107
+ // where r is order of prime subgroup and h is cofactor.
108
+ // r = t⁴-t²+1
109
+ // r = (t**4n - t**2n + 1n)
110
+ // cofactor h of G1: (t - 1)²/3
111
+ // cofactorG1 = (t-1n)**2n/3n
112
+ // x = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507
113
+ // y = 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569
114
+ const bls12_381_CURVE_G1 = {
115
+ p: BigInt('0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab'),
116
+ n: BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001'),
117
+ h: BigInt('0x396c8c005555e1568c00aaab0000aaab'),
118
+ a: _0n,
119
+ b: _4n,
120
+ Gx: BigInt('0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb'),
121
+ Gy: BigInt('0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1'),
122
+ };
80
123
  // CURVE FIELDS
124
+ exports.bls12_381_Fr = (0, modular_ts_1.Field)(bls12_381_CURVE_G1.n);
81
125
  const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = (0, tower_ts_1.tower12)({
82
126
  // Order of Fp
83
- ORDER: BigInt('0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab'),
127
+ ORDER: bls12_381_CURVE_G1.p,
84
128
  // Finite extension field over irreducible polynominal.
85
129
  // Fp(u) / (u² - β) where β = -1
86
130
  FP2_NONRESIDUE: [_1n, _1n],
@@ -146,11 +190,395 @@ const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = (0, tower_ts_1.tower12)({
146
190
  return Fp12.mul(Fp12.mul(Fp12.mul(t2_t5_pow_q2, t4_t1_pow_q3), t6_t1c_pow_q1), t7_t3c_t1);
147
191
  },
148
192
  });
149
- // Finite field over r.
150
- // This particular field is not used anywhere in bls12-381, but it is still useful.
151
- const Fr = (0, modular_ts_1.Field)(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001'));
152
- // END OF CURVE FIELDS
153
- // HashToCurve
193
+ // GLV endomorphism Ψ(P), for fast cofactor clearing
194
+ const { G2psi, G2psi2 } = (0, tower_ts_1.psiFrobenius)(Fp, Fp2, Fp2.div(Fp2.ONE, Fp2.NONRESIDUE)); // 1/(u+1)
195
+ /**
196
+ * Default hash_to_field / hash-to-curve for BLS.
197
+ * m: 1 for G1, 2 for G2
198
+ * k: target security level in bits
199
+ * hash: any function, e.g. BBS+ uses BLAKE2: see [github](https://github.com/hyperledger/aries-framework-go/issues/2247).
200
+ * Parameter values come from [section 8.8.2 of RFC 9380](https://www.rfc-editor.org/rfc/rfc9380#section-8.8.2).
201
+ */
202
+ const htfDefaults = Object.freeze({
203
+ DST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_',
204
+ encodeDST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_',
205
+ p: Fp.ORDER,
206
+ m: 2,
207
+ k: 128,
208
+ expand: 'xmd',
209
+ hash: sha2_js_1.sha256,
210
+ });
211
+ // a=0, b=4
212
+ // cofactor h of G2
213
+ // (t^8 - 4t^7 + 5t^6 - 4t^4 + 6t^3 - 4t^2 - 4t + 13)/9
214
+ // cofactorG2 = (t**8n - 4n*t**7n + 5n*t**6n - 4n*t**4n + 6n*t**3n - 4n*t**2n - 4n*t+13n)/9n
215
+ // x = 3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758*u + 352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160
216
+ // y = 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582*u + 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905
217
+ const bls12_381_CURVE_G2 = {
218
+ p: Fp2.ORDER,
219
+ n: bls12_381_CURVE_G1.n,
220
+ h: BigInt('0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5'),
221
+ a: Fp2.ZERO,
222
+ b: Fp2.fromBigTuple([_4n, _4n]),
223
+ Gx: Fp2.fromBigTuple([
224
+ BigInt('0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8'),
225
+ BigInt('0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e'),
226
+ ]),
227
+ Gy: Fp2.fromBigTuple([
228
+ BigInt('0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801'),
229
+ BigInt('0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be'),
230
+ ]),
231
+ };
232
+ // Encoding utils
233
+ // Compressed point of infinity
234
+ // Set compressed & point-at-infinity bits
235
+ const COMPZERO = setMask(Fp.toBytes(_0n), { infinity: true, compressed: true });
236
+ function parseMask(bytes) {
237
+ // Copy, so we can remove mask data. It will be removed also later, when Fp.create will call modulo.
238
+ bytes = bytes.slice();
239
+ const mask = bytes[0] & 224;
240
+ const compressed = !!((mask >> 7) & 1); // compression bit (0b1000_0000)
241
+ const infinity = !!((mask >> 6) & 1); // point at infinity bit (0b0100_0000)
242
+ const sort = !!((mask >> 5) & 1); // sort bit (0b0010_0000)
243
+ bytes[0] &= 31; // clear mask (zero first 3 bits)
244
+ return { compressed, infinity, sort, value: bytes };
245
+ }
246
+ function setMask(bytes, mask) {
247
+ if (bytes[0] & 224)
248
+ throw new Error('setMask: non-empty mask');
249
+ if (mask.compressed)
250
+ bytes[0] |= 128;
251
+ if (mask.infinity)
252
+ bytes[0] |= 64;
253
+ if (mask.sort)
254
+ bytes[0] |= 32;
255
+ return bytes;
256
+ }
257
+ function pointG1ToBytes(_c, point, isComp) {
258
+ const { BYTES: L, ORDER: P } = Fp;
259
+ const is0 = point.is0();
260
+ const { x, y } = point.toAffine();
261
+ if (isComp) {
262
+ if (is0)
263
+ return COMPZERO.slice();
264
+ const sort = Boolean((y * _2n) / P);
265
+ return setMask((0, utils_ts_1.numberToBytesBE)(x, L), { compressed: true, sort });
266
+ }
267
+ else {
268
+ if (is0) {
269
+ return (0, utils_ts_1.concatBytes)(Uint8Array.of(0x40), new Uint8Array(2 * L - 1));
270
+ }
271
+ else {
272
+ return (0, utils_ts_1.concatBytes)((0, utils_ts_1.numberToBytesBE)(x, L), (0, utils_ts_1.numberToBytesBE)(y, L));
273
+ }
274
+ }
275
+ }
276
+ function signatureG1ToBytes(point) {
277
+ point.assertValidity();
278
+ const { BYTES: L, ORDER: P } = Fp;
279
+ const { x, y } = point.toAffine();
280
+ if (point.is0())
281
+ return COMPZERO.slice();
282
+ const sort = Boolean((y * _2n) / P);
283
+ return setMask((0, utils_ts_1.numberToBytesBE)(x, L), { compressed: true, sort });
284
+ }
285
+ function pointG1FromBytes(bytes) {
286
+ const { compressed, infinity, sort, value } = parseMask(bytes);
287
+ const { BYTES: L, ORDER: P } = Fp;
288
+ if (value.length === 48 && compressed) {
289
+ const compressedValue = (0, utils_ts_1.bytesToNumberBE)(value);
290
+ // Zero
291
+ const x = Fp.create(compressedValue & Fp.MASK);
292
+ if (infinity) {
293
+ if (x !== _0n)
294
+ throw new Error('invalid G1 point: non-empty, at infinity, with compression');
295
+ return { x: _0n, y: _0n };
296
+ }
297
+ const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381_CURVE_G1.b)); // y² = x³ + b
298
+ let y = Fp.sqrt(right);
299
+ if (!y)
300
+ throw new Error('invalid G1 point: compressed point');
301
+ if ((y * _2n) / P !== BigInt(sort))
302
+ y = Fp.neg(y);
303
+ return { x: Fp.create(x), y: Fp.create(y) };
304
+ }
305
+ else if (value.length === 96 && !compressed) {
306
+ // Check if the infinity flag is set
307
+ const x = (0, utils_ts_1.bytesToNumberBE)(value.subarray(0, L));
308
+ const y = (0, utils_ts_1.bytesToNumberBE)(value.subarray(L));
309
+ if (infinity) {
310
+ if (x !== _0n || y !== _0n)
311
+ throw new Error('G1: non-empty point at infinity');
312
+ return exports.bls12_381.G1.Point.ZERO.toAffine();
313
+ }
314
+ return { x: Fp.create(x), y: Fp.create(y) };
315
+ }
316
+ else {
317
+ throw new Error('invalid G1 point: expected 48/96 bytes');
318
+ }
319
+ }
320
+ function signatureG1FromBytes(hex) {
321
+ const { infinity, sort, value } = parseMask((0, utils_ts_1.ensureBytes)('signatureHex', hex, 48));
322
+ const P = Fp.ORDER;
323
+ const Point = exports.bls12_381.G1.Point;
324
+ const compressedValue = (0, utils_ts_1.bytesToNumberBE)(value);
325
+ // Zero
326
+ if (infinity)
327
+ return Point.ZERO;
328
+ const x = Fp.create(compressedValue & Fp.MASK);
329
+ const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381_CURVE_G1.b)); // y² = x³ + b
330
+ let y = Fp.sqrt(right);
331
+ if (!y)
332
+ throw new Error('invalid G1 point: compressed');
333
+ const aflag = BigInt(sort);
334
+ if ((y * _2n) / P !== aflag)
335
+ y = Fp.neg(y);
336
+ const point = Point.fromAffine({ x, y });
337
+ point.assertValidity();
338
+ return point;
339
+ }
340
+ function pointG2ToBytes(_c, point, isComp) {
341
+ const { BYTES: L, ORDER: P } = Fp;
342
+ const is0 = point.is0();
343
+ const { x, y } = point.toAffine();
344
+ if (isComp) {
345
+ if (is0)
346
+ return (0, utils_ts_1.concatBytes)(COMPZERO, (0, utils_ts_1.numberToBytesBE)(_0n, L));
347
+ const flag = Boolean(y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P);
348
+ return (0, utils_ts_1.concatBytes)(setMask((0, utils_ts_1.numberToBytesBE)(x.c1, L), { compressed: true, sort: flag }), (0, utils_ts_1.numberToBytesBE)(x.c0, L));
349
+ }
350
+ else {
351
+ if (is0)
352
+ return (0, utils_ts_1.concatBytes)(Uint8Array.of(0x40), new Uint8Array(4 * L - 1));
353
+ const { re: x0, im: x1 } = Fp2.reim(x);
354
+ const { re: y0, im: y1 } = Fp2.reim(y);
355
+ return (0, utils_ts_1.concatBytes)((0, utils_ts_1.numberToBytesBE)(x1, L), (0, utils_ts_1.numberToBytesBE)(x0, L), (0, utils_ts_1.numberToBytesBE)(y1, L), (0, utils_ts_1.numberToBytesBE)(y0, L));
356
+ }
357
+ }
358
+ function signatureG2ToBytes(point) {
359
+ point.assertValidity();
360
+ const { BYTES: L } = Fp;
361
+ if (point.is0())
362
+ return (0, utils_ts_1.concatBytes)(COMPZERO, (0, utils_ts_1.numberToBytesBE)(_0n, L));
363
+ const { x, y } = point.toAffine();
364
+ const { re: x0, im: x1 } = Fp2.reim(x);
365
+ const { re: y0, im: y1 } = Fp2.reim(y);
366
+ const tmp = y1 > _0n ? y1 * _2n : y0 * _2n;
367
+ const sort = Boolean((tmp / Fp.ORDER) & _1n);
368
+ const z2 = x0;
369
+ return (0, utils_ts_1.concatBytes)(setMask((0, utils_ts_1.numberToBytesBE)(x1, L), { sort, compressed: true }), (0, utils_ts_1.numberToBytesBE)(z2, L));
370
+ }
371
+ function pointG2FromBytes(bytes) {
372
+ const { BYTES: L, ORDER: P } = Fp;
373
+ const { compressed, infinity, sort, value } = parseMask(bytes);
374
+ if ((!compressed && !infinity && sort) || // 00100000
375
+ (!compressed && infinity && sort) || // 01100000
376
+ (sort && infinity && compressed) // 11100000
377
+ ) {
378
+ throw new Error('invalid encoding flag: ' + (bytes[0] & 224));
379
+ }
380
+ const slc = (b, from, to) => (0, utils_ts_1.bytesToNumberBE)(b.slice(from, to));
381
+ if (value.length === 96 && compressed) {
382
+ if (infinity) {
383
+ // check that all bytes are 0
384
+ if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) {
385
+ throw new Error('invalid G2 point: compressed');
386
+ }
387
+ return { x: Fp2.ZERO, y: Fp2.ZERO };
388
+ }
389
+ const x_1 = slc(value, 0, L);
390
+ const x_0 = slc(value, L, 2 * L);
391
+ const x = Fp2.create({ c0: Fp.create(x_0), c1: Fp.create(x_1) });
392
+ const right = Fp2.add(Fp2.pow(x, _3n), bls12_381_CURVE_G2.b); // y² = x³ + 4 * (u+1) = x³ + b
393
+ let y = Fp2.sqrt(right);
394
+ const Y_bit = y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P ? _1n : _0n;
395
+ y = sort && Y_bit > 0 ? y : Fp2.neg(y);
396
+ return { x, y };
397
+ }
398
+ else if (value.length === 192 && !compressed) {
399
+ if (infinity) {
400
+ if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) {
401
+ throw new Error('invalid G2 point: uncompressed');
402
+ }
403
+ return { x: Fp2.ZERO, y: Fp2.ZERO };
404
+ }
405
+ const x1 = slc(value, 0 * L, 1 * L);
406
+ const x0 = slc(value, 1 * L, 2 * L);
407
+ const y1 = slc(value, 2 * L, 3 * L);
408
+ const y0 = slc(value, 3 * L, 4 * L);
409
+ return { x: Fp2.fromBigTuple([x0, x1]), y: Fp2.fromBigTuple([y0, y1]) };
410
+ }
411
+ else {
412
+ throw new Error('invalid G2 point: expected 96/192 bytes');
413
+ }
414
+ }
415
+ function signatureG2FromBytes(hex) {
416
+ const { ORDER: P } = Fp;
417
+ // TODO: Optimize, it's very slow because of sqrt.
418
+ const { infinity, sort, value } = parseMask((0, utils_ts_1.ensureBytes)('signatureHex', hex));
419
+ const Point = exports.bls12_381.G2.Point;
420
+ const half = value.length / 2;
421
+ if (half !== 48 && half !== 96)
422
+ throw new Error('invalid compressed signature length, expected 96/192 bytes');
423
+ const z1 = (0, utils_ts_1.bytesToNumberBE)(value.slice(0, half));
424
+ const z2 = (0, utils_ts_1.bytesToNumberBE)(value.slice(half));
425
+ // Indicates the infinity point
426
+ if (infinity)
427
+ return Point.ZERO;
428
+ const x1 = Fp.create(z1 & Fp.MASK);
429
+ const x2 = Fp.create(z2);
430
+ const x = Fp2.create({ c0: x2, c1: x1 });
431
+ const y2 = Fp2.add(Fp2.pow(x, _3n), bls12_381_CURVE_G2.b); // y² = x³ + 4
432
+ // The slow part
433
+ let y = Fp2.sqrt(y2);
434
+ if (!y)
435
+ throw new Error('Failed to find a square root');
436
+ // Choose the y whose leftmost bit of the imaginary part is equal to the a_flag1
437
+ // If y1 happens to be zero, then use the bit of y0
438
+ const { re: y0, im: y1 } = Fp2.reim(y);
439
+ const aflag1 = BigInt(sort);
440
+ const isGreater = y1 > _0n && (y1 * _2n) / P !== aflag1;
441
+ const is0 = y1 === _0n && (y0 * _2n) / P !== aflag1;
442
+ if (isGreater || is0)
443
+ y = Fp2.neg(y);
444
+ const point = Point.fromAffine({ x, y });
445
+ point.assertValidity();
446
+ return point;
447
+ }
448
+ /**
449
+ * bls12-381 pairing-friendly curve.
450
+ * @example
451
+ * import { bls12_381 as bls } from '@noble/curves/bls12-381';
452
+ * // G1 keys, G2 signatures
453
+ * const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c';
454
+ * const message = '64726e3da8';
455
+ * const publicKey = bls.getPublicKey(privateKey);
456
+ * const signature = bls.sign(message, privateKey);
457
+ * const isValid = bls.verify(signature, message, publicKey);
458
+ */
459
+ exports.bls12_381 = (0, bls_ts_1.bls)({
460
+ // Fields
461
+ fields: {
462
+ Fp,
463
+ Fp2,
464
+ Fp6,
465
+ Fp12,
466
+ Fr: exports.bls12_381_Fr,
467
+ },
468
+ // G1: y² = x³ + 4
469
+ G1: {
470
+ ...bls12_381_CURVE_G1,
471
+ Fp,
472
+ htfDefaults: { ...htfDefaults, m: 1, DST: 'BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_' },
473
+ wrapPrivateKey: true,
474
+ allowInfinityPoint: true,
475
+ // Checks is the point resides in prime-order subgroup.
476
+ // point.isTorsionFree() should return true for valid points
477
+ // It returns false for shitty points.
478
+ // https://eprint.iacr.org/2021/1130.pdf
479
+ isTorsionFree: (c, point) => {
480
+ // GLV endomorphism ψ(P)
481
+ const beta = BigInt('0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe');
482
+ const phi = new c(Fp.mul(point.px, beta), point.py, point.pz);
483
+ // TODO: unroll
484
+ const xP = point.multiplyUnsafe(BLS_X).negate(); // [x]P
485
+ const u2P = xP.multiplyUnsafe(BLS_X); // [u2]P
486
+ return u2P.equals(phi);
487
+ },
488
+ // Clear cofactor of G1
489
+ // https://eprint.iacr.org/2019/403
490
+ clearCofactor: (_c, point) => {
491
+ // return this.multiplyUnsafe(CURVE.h);
492
+ return point.multiplyUnsafe(BLS_X).add(point); // x*P + P
493
+ },
494
+ mapToCurve: mapToG1,
495
+ fromBytes: pointG1FromBytes,
496
+ toBytes: pointG1ToBytes,
497
+ ShortSignature: {
498
+ fromBytes(bytes) {
499
+ (0, utils_ts_1.abytes)(bytes);
500
+ return signatureG1FromBytes(bytes);
501
+ },
502
+ fromHex(hex) {
503
+ return signatureG1FromBytes(hex);
504
+ },
505
+ toBytes(point) {
506
+ return signatureG1ToBytes(point);
507
+ },
508
+ toRawBytes(point) {
509
+ return signatureG1ToBytes(point);
510
+ },
511
+ toHex(point) {
512
+ return (0, utils_ts_1.bytesToHex)(signatureG1ToBytes(point));
513
+ },
514
+ },
515
+ },
516
+ G2: {
517
+ ...bls12_381_CURVE_G2,
518
+ Fp: Fp2,
519
+ // https://datatracker.ietf.org/doc/html/rfc9380#name-clearing-the-cofactor
520
+ // https://datatracker.ietf.org/doc/html/rfc9380#name-cofactor-clearing-for-bls12
521
+ hEff: BigInt('0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551'),
522
+ htfDefaults: { ...htfDefaults },
523
+ wrapPrivateKey: true,
524
+ allowInfinityPoint: true,
525
+ mapToCurve: mapToG2,
526
+ // Checks is the point resides in prime-order subgroup.
527
+ // point.isTorsionFree() should return true for valid points
528
+ // It returns false for shitty points.
529
+ // https://eprint.iacr.org/2021/1130.pdf
530
+ // Older version: https://eprint.iacr.org/2019/814.pdf
531
+ isTorsionFree: (c, P) => {
532
+ return P.multiplyUnsafe(BLS_X).negate().equals(G2psi(c, P)); // ψ(P) == [u](P)
533
+ },
534
+ // Maps the point into the prime-order subgroup G2.
535
+ // clear_cofactor_bls12381_g2 from RFC 9380.
536
+ // https://eprint.iacr.org/2017/419.pdf
537
+ // prettier-ignore
538
+ clearCofactor: (c, P) => {
539
+ const x = BLS_X;
540
+ let t1 = P.multiplyUnsafe(x).negate(); // [-x]P
541
+ let t2 = G2psi(c, P); // Ψ(P)
542
+ let t3 = P.double(); // 2P
543
+ t3 = G2psi2(c, t3); // Ψ²(2P)
544
+ t3 = t3.subtract(t2); // Ψ²(2P) - Ψ(P)
545
+ t2 = t1.add(t2); // [-x]P + Ψ(P)
546
+ t2 = t2.multiplyUnsafe(x).negate(); // [x²]P - [x]Ψ(P)
547
+ t3 = t3.add(t2); // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P)
548
+ t3 = t3.subtract(t1); // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P
549
+ const Q = t3.subtract(P); // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P - 1P
550
+ return Q; // [x²-x-1]P + [x-1]Ψ(P) + Ψ²(2P)
551
+ },
552
+ fromBytes: pointG2FromBytes,
553
+ toBytes: pointG2ToBytes,
554
+ Signature: {
555
+ fromBytes(bytes) {
556
+ (0, utils_ts_1.abytes)(bytes);
557
+ return signatureG2FromBytes(bytes);
558
+ },
559
+ fromHex(hex) {
560
+ return signatureG2FromBytes(hex);
561
+ },
562
+ toBytes(point) {
563
+ return signatureG2ToBytes(point);
564
+ },
565
+ toRawBytes(point) {
566
+ return signatureG2ToBytes(point);
567
+ },
568
+ toHex(point) {
569
+ return (0, utils_ts_1.bytesToHex)(signatureG2ToBytes(point));
570
+ },
571
+ },
572
+ },
573
+ params: {
574
+ ateLoopSize: BLS_X, // The BLS parameter x for BLS12-381
575
+ r: bls12_381_CURVE_G1.n, // order; z⁴ − z² + 1; CURVE.n from other curves
576
+ xNegative: true,
577
+ twistType: 'multiplicative',
578
+ },
579
+ htfDefaults,
580
+ hash: sha2_js_1.sha256,
581
+ });
154
582
  // 3-isogeny map from E' to E https://www.rfc-editor.org/rfc/rfc9380#appendix-E.3
155
583
  const isogenyMapG2 = (0, hash_to_curve_ts_1.isogenyMap)(Fp2, [
156
584
  // xNum
@@ -290,414 +718,24 @@ const isogenyMapG1 = (0, hash_to_curve_ts_1.isogenyMap)(Fp, [
290
718
  '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', // LAST 1
291
719
  ],
292
720
  ].map((i) => i.map((j) => BigInt(j))));
293
- // SWU Map - Fp2 to G2': y² = x³ + 240i * x + 1012 + 1012i
294
- const G2_SWU = (0, weierstrass_ts_1.mapToCurveSimpleSWU)(Fp2, {
295
- A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(BigInt(240)) }), // A' = 240 * I
296
- B: Fp2.create({ c0: Fp.create(BigInt(1012)), c1: Fp.create(BigInt(1012)) }), // B' = 1012 * (1 + I)
297
- Z: Fp2.create({ c0: Fp.create(BigInt(-2)), c1: Fp.create(BigInt(-1)) }), // Z: -(2 + I)
298
- });
299
721
  // Optimized SWU Map - Fp to G1
300
722
  const G1_SWU = (0, weierstrass_ts_1.mapToCurveSimpleSWU)(Fp, {
301
723
  A: Fp.create(BigInt('0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aefd881ac98936f8da0e0f97f5cf428082d584c1d')),
302
724
  B: Fp.create(BigInt('0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0')),
303
725
  Z: Fp.create(BigInt(11)),
304
726
  });
305
- // GLV endomorphism Ψ(P), for fast cofactor clearing
306
- const { G2psi, G2psi2 } = (0, tower_ts_1.psiFrobenius)(Fp, Fp2, Fp2.div(Fp2.ONE, Fp2.NONRESIDUE)); // 1/(u+1)
307
- // Default hash_to_field options are for hash to G2.
308
- //
309
- // Parameter definitions are in section 5.3 of the spec unless otherwise noted.
310
- // Parameter values come from section 8.8.2 of the spec.
311
- // https://www.rfc-editor.org/rfc/rfc9380#section-8.8.2
312
- //
313
- // Base field F is GF(p^m)
314
- // p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
315
- // m = 2 (or 1 for G1 see section 8.8.1)
316
- // k = 128
317
- const htfDefaults = Object.freeze({
318
- // DST: a domain separation tag
319
- // defined in section 2.2.5
320
- // Use utils.getDSTLabel(), utils.setDSTLabel(value)
321
- DST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_',
322
- encodeDST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_',
323
- // p: the characteristic of F
324
- // where F is a finite field of characteristic p and order q = p^m
325
- p: Fp.ORDER,
326
- // m: the extension degree of F, m >= 1
327
- // where F is a finite field of characteristic p and order q = p^m
328
- m: 2,
329
- // k: the target security level for the suite in bits
330
- // defined in section 5.1
331
- k: 128,
332
- // option to use a message that has already been processed by
333
- // expand_message_xmd
334
- expand: 'xmd',
335
- // Hash functions for: expand_message_xmd is appropriate for use with a
336
- // wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others.
337
- // BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247
338
- hash: sha2_1.sha256,
727
+ // SWU Map - Fp2 to G2': y² = x³ + 240i * x + 1012 + 1012i
728
+ const G2_SWU = (0, weierstrass_ts_1.mapToCurveSimpleSWU)(Fp2, {
729
+ A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(BigInt(240)) }), // A' = 240 * I
730
+ B: Fp2.create({ c0: Fp.create(BigInt(1012)), c1: Fp.create(BigInt(1012)) }), // B' = 1012 * (1 + I)
731
+ Z: Fp2.create({ c0: Fp.create(BigInt(-2)), c1: Fp.create(BigInt(-1)) }), // Z: -(2 + I)
339
732
  });
340
- // Encoding utils
341
- // Point on G1 curve: (x, y)
342
- // Compressed point of infinity
343
- const COMPRESSED_ZERO = setMask(Fp.toBytes(_0n), { infinity: true, compressed: true }); // set compressed & point-at-infinity bits
344
- function parseMask(bytes) {
345
- // Copy, so we can remove mask data. It will be removed also later, when Fp.create will call modulo.
346
- bytes = bytes.slice();
347
- const mask = bytes[0] & 224;
348
- const compressed = !!((mask >> 7) & 1); // compression bit (0b1000_0000)
349
- const infinity = !!((mask >> 6) & 1); // point at infinity bit (0b0100_0000)
350
- const sort = !!((mask >> 5) & 1); // sort bit (0b0010_0000)
351
- bytes[0] &= 31; // clear mask (zero first 3 bits)
352
- return { compressed, infinity, sort, value: bytes };
733
+ function mapToG1(scalars) {
734
+ const { x, y } = G1_SWU(Fp.create(scalars[0]));
735
+ return isogenyMapG1(x, y);
353
736
  }
354
- function setMask(bytes, mask) {
355
- if (bytes[0] & 224)
356
- throw new Error('setMask: non-empty mask');
357
- if (mask.compressed)
358
- bytes[0] |= 128;
359
- if (mask.infinity)
360
- bytes[0] |= 64;
361
- if (mask.sort)
362
- bytes[0] |= 32;
363
- return bytes;
737
+ function mapToG2(scalars) {
738
+ const { x, y } = G2_SWU(Fp2.fromBigTuple(scalars));
739
+ return isogenyMapG2(x, y);
364
740
  }
365
- function signatureG1ToRawBytes(point) {
366
- point.assertValidity();
367
- const isZero = point.equals(exports.bls12_381.G1.ProjectivePoint.ZERO);
368
- const { x, y } = point.toAffine();
369
- if (isZero)
370
- return COMPRESSED_ZERO.slice();
371
- const P = Fp.ORDER;
372
- const sort = Boolean((y * _2n) / P);
373
- return setMask((0, utils_ts_1.numberToBytesBE)(x, Fp.BYTES), { compressed: true, sort });
374
- }
375
- function signatureG2ToRawBytes(point) {
376
- // NOTE: by some reasons it was missed in bls12-381, looks like bug
377
- point.assertValidity();
378
- const len = Fp.BYTES;
379
- if (point.equals(exports.bls12_381.G2.ProjectivePoint.ZERO))
380
- return (0, utils_ts_1.concatBytes)(COMPRESSED_ZERO, (0, utils_ts_1.numberToBytesBE)(_0n, len));
381
- const { x, y } = point.toAffine();
382
- const { re: x0, im: x1 } = Fp2.reim(x);
383
- const { re: y0, im: y1 } = Fp2.reim(y);
384
- const tmp = y1 > _0n ? y1 * _2n : y0 * _2n;
385
- const sort = Boolean((tmp / Fp.ORDER) & _1n);
386
- const z2 = x0;
387
- return (0, utils_ts_1.concatBytes)(setMask((0, utils_ts_1.numberToBytesBE)(x1, len), { sort, compressed: true }), (0, utils_ts_1.numberToBytesBE)(z2, len));
388
- }
389
- /**
390
- * bls12-381 pairing-friendly curve.
391
- * @example
392
- * import { bls12_381 as bls } from '@noble/curves/bls12-381';
393
- * // G1 keys, G2 signatures
394
- * const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c';
395
- * const message = '64726e3da8';
396
- * const publicKey = bls.getPublicKey(privateKey);
397
- * const signature = bls.sign(message, privateKey);
398
- * const isValid = bls.verify(signature, message, publicKey);
399
- */
400
- exports.bls12_381 = (0, bls_ts_1.bls)({
401
- // Fields
402
- fields: {
403
- Fp,
404
- Fp2,
405
- Fp6,
406
- Fp12,
407
- Fr,
408
- },
409
- // G1 is the order-q subgroup of E1(Fp) : y² = x³ + 4, #E1(Fp) = h1q, where
410
- // characteristic; z + (z⁴ - z² + 1)(z - 1)²/3
411
- G1: {
412
- Fp,
413
- // cofactor; (z - 1)²/3
414
- h: BigInt('0x396c8c005555e1568c00aaab0000aaab'),
415
- // generator's coordinates
416
- // x = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507
417
- // y = 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569
418
- Gx: BigInt('0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb'),
419
- Gy: BigInt('0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1'),
420
- a: Fp.ZERO,
421
- b: _4n,
422
- htfDefaults: { ...htfDefaults, m: 1, DST: 'BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_' },
423
- wrapPrivateKey: true,
424
- allowInfinityPoint: true,
425
- // Checks is the point resides in prime-order subgroup.
426
- // point.isTorsionFree() should return true for valid points
427
- // It returns false for shitty points.
428
- // https://eprint.iacr.org/2021/1130.pdf
429
- isTorsionFree: (c, point) => {
430
- // GLV endomorphism ψ(P)
431
- const beta = BigInt('0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe');
432
- const phi = new c(Fp.mul(point.px, beta), point.py, point.pz);
433
- // TODO: unroll
434
- const xP = point.multiplyUnsafe(BLS_X).negate(); // [x]P
435
- const u2P = xP.multiplyUnsafe(BLS_X); // [u2]P
436
- return u2P.equals(phi);
437
- },
438
- // Clear cofactor of G1
439
- // https://eprint.iacr.org/2019/403
440
- clearCofactor: (_c, point) => {
441
- // return this.multiplyUnsafe(CURVE.h);
442
- return point.multiplyUnsafe(BLS_X).add(point); // x*P + P
443
- },
444
- mapToCurve: (scalars) => {
445
- const { x, y } = G1_SWU(Fp.create(scalars[0]));
446
- return isogenyMapG1(x, y);
447
- },
448
- fromBytes: (bytes) => {
449
- const { compressed, infinity, sort, value } = parseMask(bytes);
450
- if (value.length === 48 && compressed) {
451
- // TODO: Fp.bytes
452
- const P = Fp.ORDER;
453
- const compressedValue = (0, utils_ts_1.bytesToNumberBE)(value);
454
- // Zero
455
- const x = Fp.create(compressedValue & Fp.MASK);
456
- if (infinity) {
457
- if (x !== _0n)
458
- throw new Error('G1: non-empty compressed point at infinity');
459
- return { x: _0n, y: _0n };
460
- }
461
- const right = Fp.add(Fp.pow(x, _3n), Fp.create(exports.bls12_381.params.G1b)); // y² = x³ + b
462
- let y = Fp.sqrt(right);
463
- if (!y)
464
- throw new Error('invalid compressed G1 point');
465
- if ((y * _2n) / P !== BigInt(sort))
466
- y = Fp.neg(y);
467
- return { x: Fp.create(x), y: Fp.create(y) };
468
- }
469
- else if (value.length === 96 && !compressed) {
470
- // Check if the infinity flag is set
471
- const x = (0, utils_ts_1.bytesToNumberBE)(value.subarray(0, Fp.BYTES));
472
- const y = (0, utils_ts_1.bytesToNumberBE)(value.subarray(Fp.BYTES));
473
- if (infinity) {
474
- if (x !== _0n || y !== _0n)
475
- throw new Error('G1: non-empty point at infinity');
476
- return exports.bls12_381.G1.ProjectivePoint.ZERO.toAffine();
477
- }
478
- return { x: Fp.create(x), y: Fp.create(y) };
479
- }
480
- else {
481
- throw new Error('invalid point G1, expected 48/96 bytes');
482
- }
483
- },
484
- toBytes: (c, point, isCompressed) => {
485
- const isZero = point.equals(c.ZERO);
486
- const { x, y } = point.toAffine();
487
- if (isCompressed) {
488
- if (isZero)
489
- return COMPRESSED_ZERO.slice();
490
- const P = Fp.ORDER;
491
- const sort = Boolean((y * _2n) / P);
492
- return setMask((0, utils_ts_1.numberToBytesBE)(x, Fp.BYTES), { compressed: true, sort });
493
- }
494
- else {
495
- if (isZero) {
496
- // 2x PUBLIC_KEY_LENGTH
497
- const x = (0, utils_ts_1.concatBytes)(new Uint8Array([0x40]), new Uint8Array(2 * Fp.BYTES - 1));
498
- return x;
499
- }
500
- else {
501
- return (0, utils_ts_1.concatBytes)((0, utils_ts_1.numberToBytesBE)(x, Fp.BYTES), (0, utils_ts_1.numberToBytesBE)(y, Fp.BYTES));
502
- }
503
- }
504
- },
505
- ShortSignature: {
506
- fromHex(hex) {
507
- const { infinity, sort, value } = parseMask((0, utils_ts_1.ensureBytes)('signatureHex', hex, 48));
508
- const P = Fp.ORDER;
509
- const compressedValue = (0, utils_ts_1.bytesToNumberBE)(value);
510
- // Zero
511
- if (infinity)
512
- return exports.bls12_381.G1.ProjectivePoint.ZERO;
513
- const x = Fp.create(compressedValue & Fp.MASK);
514
- const right = Fp.add(Fp.pow(x, _3n), Fp.create(exports.bls12_381.params.G1b)); // y² = x³ + b
515
- let y = Fp.sqrt(right);
516
- if (!y)
517
- throw new Error('invalid compressed G1 point');
518
- const aflag = BigInt(sort);
519
- if ((y * _2n) / P !== aflag)
520
- y = Fp.neg(y);
521
- const point = exports.bls12_381.G1.ProjectivePoint.fromAffine({ x, y });
522
- point.assertValidity();
523
- return point;
524
- },
525
- toRawBytes(point) {
526
- return signatureG1ToRawBytes(point);
527
- },
528
- toHex(point) {
529
- return (0, utils_ts_1.bytesToHex)(signatureG1ToRawBytes(point));
530
- },
531
- },
532
- },
533
- // G2 is the order-q subgroup of E2(Fp²) : y² = x³+4(1+√−1),
534
- // where Fp2 is Fp[√−1]/(x2+1). #E2(Fp2 ) = h2q, where
535
- // G² - 1
536
- // h2q
537
- G2: {
538
- Fp: Fp2,
539
- // cofactor
540
- h: BigInt('0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5'),
541
- Gx: Fp2.fromBigTuple([
542
- BigInt('0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8'),
543
- BigInt('0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e'),
544
- ]),
545
- // y =
546
- // 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582,
547
- // 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905
548
- Gy: Fp2.fromBigTuple([
549
- BigInt('0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801'),
550
- BigInt('0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be'),
551
- ]),
552
- a: Fp2.ZERO,
553
- b: Fp2.fromBigTuple([_4n, _4n]),
554
- hEff: BigInt('0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551'),
555
- htfDefaults: { ...htfDefaults },
556
- wrapPrivateKey: true,
557
- allowInfinityPoint: true,
558
- mapToCurve: (scalars) => {
559
- const { x, y } = G2_SWU(Fp2.fromBigTuple(scalars));
560
- return isogenyMapG2(x, y);
561
- },
562
- // Checks is the point resides in prime-order subgroup.
563
- // point.isTorsionFree() should return true for valid points
564
- // It returns false for shitty points.
565
- // https://eprint.iacr.org/2021/1130.pdf
566
- // Older version: https://eprint.iacr.org/2019/814.pdf
567
- isTorsionFree: (c, P) => {
568
- return P.multiplyUnsafe(BLS_X).negate().equals(G2psi(c, P)); // ψ(P) == [u](P)
569
- },
570
- // Maps the point into the prime-order subgroup G2.
571
- // clear_cofactor_bls12381_g2 from RFC 9380.
572
- // https://eprint.iacr.org/2017/419.pdf
573
- // prettier-ignore
574
- clearCofactor: (c, P) => {
575
- const x = BLS_X;
576
- let t1 = P.multiplyUnsafe(x).negate(); // [-x]P
577
- let t2 = G2psi(c, P); // Ψ(P)
578
- let t3 = P.double(); // 2P
579
- t3 = G2psi2(c, t3); // Ψ²(2P)
580
- t3 = t3.subtract(t2); // Ψ²(2P) - Ψ(P)
581
- t2 = t1.add(t2); // [-x]P + Ψ(P)
582
- t2 = t2.multiplyUnsafe(x).negate(); // [x²]P - [x]Ψ(P)
583
- t3 = t3.add(t2); // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P)
584
- t3 = t3.subtract(t1); // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P
585
- const Q = t3.subtract(P); // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P - 1P
586
- return Q; // [x²-x-1]P + [x-1]Ψ(P) + Ψ²(2P)
587
- },
588
- fromBytes: (bytes) => {
589
- const { compressed, infinity, sort, value } = parseMask(bytes);
590
- if ((!compressed && !infinity && sort) || // 00100000
591
- (!compressed && infinity && sort) || // 01100000
592
- (sort && infinity && compressed) // 11100000
593
- ) {
594
- throw new Error('invalid encoding flag: ' + (bytes[0] & 224));
595
- }
596
- const L = Fp.BYTES;
597
- const slc = (b, from, to) => (0, utils_ts_1.bytesToNumberBE)(b.slice(from, to));
598
- if (value.length === 96 && compressed) {
599
- const b = exports.bls12_381.params.G2b;
600
- const P = Fp.ORDER;
601
- if (infinity) {
602
- // check that all bytes are 0
603
- if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) {
604
- throw new Error('invalid compressed G2 point');
605
- }
606
- return { x: Fp2.ZERO, y: Fp2.ZERO };
607
- }
608
- const x_1 = slc(value, 0, L);
609
- const x_0 = slc(value, L, 2 * L);
610
- const x = Fp2.create({ c0: Fp.create(x_0), c1: Fp.create(x_1) });
611
- const right = Fp2.add(Fp2.pow(x, _3n), b); // y² = x³ + 4 * (u+1) = x³ + b
612
- let y = Fp2.sqrt(right);
613
- const Y_bit = y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P ? _1n : _0n;
614
- y = sort && Y_bit > 0 ? y : Fp2.neg(y);
615
- return { x, y };
616
- }
617
- else if (value.length === 192 && !compressed) {
618
- if (infinity) {
619
- if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) {
620
- throw new Error('invalid uncompressed G2 point');
621
- }
622
- return { x: Fp2.ZERO, y: Fp2.ZERO };
623
- }
624
- const x1 = slc(value, 0, L);
625
- const x0 = slc(value, L, 2 * L);
626
- const y1 = slc(value, 2 * L, 3 * L);
627
- const y0 = slc(value, 3 * L, 4 * L);
628
- return { x: Fp2.fromBigTuple([x0, x1]), y: Fp2.fromBigTuple([y0, y1]) };
629
- }
630
- else {
631
- throw new Error('invalid point G2, expected 96/192 bytes');
632
- }
633
- },
634
- toBytes: (c, point, isCompressed) => {
635
- const { BYTES: len, ORDER: P } = Fp;
636
- const isZero = point.equals(c.ZERO);
637
- const { x, y } = point.toAffine();
638
- if (isCompressed) {
639
- if (isZero)
640
- return (0, utils_ts_1.concatBytes)(COMPRESSED_ZERO, (0, utils_ts_1.numberToBytesBE)(_0n, len));
641
- const flag = Boolean(y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P);
642
- return (0, utils_ts_1.concatBytes)(setMask((0, utils_ts_1.numberToBytesBE)(x.c1, len), { compressed: true, sort: flag }), (0, utils_ts_1.numberToBytesBE)(x.c0, len));
643
- }
644
- else {
645
- if (isZero)
646
- return (0, utils_ts_1.concatBytes)(new Uint8Array([0x40]), new Uint8Array(4 * len - 1)); // bytes[0] |= 1 << 6;
647
- const { re: x0, im: x1 } = Fp2.reim(x);
648
- const { re: y0, im: y1 } = Fp2.reim(y);
649
- return (0, utils_ts_1.concatBytes)((0, utils_ts_1.numberToBytesBE)(x1, len), (0, utils_ts_1.numberToBytesBE)(x0, len), (0, utils_ts_1.numberToBytesBE)(y1, len), (0, utils_ts_1.numberToBytesBE)(y0, len));
650
- }
651
- },
652
- Signature: {
653
- // TODO: Optimize, it's very slow because of sqrt.
654
- fromHex(hex) {
655
- const { infinity, sort, value } = parseMask((0, utils_ts_1.ensureBytes)('signatureHex', hex));
656
- const P = Fp.ORDER;
657
- const half = value.length / 2;
658
- if (half !== 48 && half !== 96)
659
- throw new Error('invalid compressed signature length, must be 96 or 192');
660
- const z1 = (0, utils_ts_1.bytesToNumberBE)(value.slice(0, half));
661
- const z2 = (0, utils_ts_1.bytesToNumberBE)(value.slice(half));
662
- // Indicates the infinity point
663
- if (infinity)
664
- return exports.bls12_381.G2.ProjectivePoint.ZERO;
665
- const x1 = Fp.create(z1 & Fp.MASK);
666
- const x2 = Fp.create(z2);
667
- const x = Fp2.create({ c0: x2, c1: x1 });
668
- const y2 = Fp2.add(Fp2.pow(x, _3n), exports.bls12_381.params.G2b); // y² = x³ + 4
669
- // The slow part
670
- let y = Fp2.sqrt(y2);
671
- if (!y)
672
- throw new Error('Failed to find a square root');
673
- // Choose the y whose leftmost bit of the imaginary part is equal to the a_flag1
674
- // If y1 happens to be zero, then use the bit of y0
675
- const { re: y0, im: y1 } = Fp2.reim(y);
676
- const aflag1 = BigInt(sort);
677
- const isGreater = y1 > _0n && (y1 * _2n) / P !== aflag1;
678
- const isZero = y1 === _0n && (y0 * _2n) / P !== aflag1;
679
- if (isGreater || isZero)
680
- y = Fp2.neg(y);
681
- const point = exports.bls12_381.G2.ProjectivePoint.fromAffine({ x, y });
682
- point.assertValidity();
683
- return point;
684
- },
685
- toRawBytes(point) {
686
- return signatureG2ToRawBytes(point);
687
- },
688
- toHex(point) {
689
- return (0, utils_ts_1.bytesToHex)(signatureG2ToRawBytes(point));
690
- },
691
- },
692
- },
693
- params: {
694
- ateLoopSize: BLS_X, // The BLS parameter x for BLS12-381
695
- r: Fr.ORDER, // order; z⁴ − z² + 1; CURVE.n from other curves
696
- xNegative: true,
697
- twistType: 'multiplicative',
698
- },
699
- htfDefaults,
700
- hash: sha2_1.sha256,
701
- randomBytes: utils_1.randomBytes,
702
- });
703
741
  //# sourceMappingURL=bls12-381.js.map