@@ -39,6 +39,7 @@ extern "C"
3939#include < cstddef>
4040#include < cstdint>
4141#include < mutex>
42+ #include < string_view>
4243
4344namespace crypto
4445{
@@ -68,14 +69,36 @@ constexpr public_key G = bytes_to<public_key>({ 0x58, 0x66, 0x66, 0x66, 0x66, 0x
6869// pedersen commitment generator H: toPoint(cn_fast_hash(G))
6970constexpr public_key H = bytes_to<public_key>({ 0x8b , 0x65 , 0x59 , 0x70 , 0x15 , 0x37 , 0x99 , 0xaf , 0x2a , 0xea , 0xdc , 0x9f , 0xf1 ,
7071 0xad , 0xd0 , 0xea , 0x6c , 0x72 , 0x51 , 0xd5 , 0x41 , 0x54 , 0xcf , 0xa9 , 0x2c , 0x17 , 0x3a , 0x0d , 0xd3 , 0x9c , 0x1f , 0x94 });
72+ // FCMP++ generator T: unbiased_hash_to_ec(keccak("Monero Generator T"))
73+ constexpr public_key T = bytes_to<public_key>({ 97 , 183 , 54 , 206 , 147 , 182 , 42 , 61 , 55 , 120 , 171 , 32 , 77 , 168 , 93 , 59 , 76 ,
74+ 220 , 7 , 37 , 15 , 93 , 167 , 227 , 223 , 38 , 41 , 146 , 129 , 52 , 213 , 38 });
75+ // FCMP++ generator U: unbiased_hash_to_ec(keccak("Monero FCMP++ Generator U"))
76+ constexpr public_key U = bytes_to<public_key>({ 80 , 107 , 35 , 246 , 214 , 229 , 48 , 153 , 122 , 188 , 172 , 198 , 253 , 52 , 119 , 52 ,
77+ 177 , 76 , 43 , 215 , 155 , 234 , 0 , 238 , 176 , 72 , 87 , 232 , 234 , 221 , 26 , 138 });
78+ // FCMP++ generator V: unbiased_hash_to_ec(keccak("Monero FCMP++ Generator V"))
79+ constexpr public_key V = bytes_to<public_key>({ 105 , 53 , 244 , 19 , 248 , 49 , 9 , 19 , 138 , 122 , 20 , 180 , 9 , 85 , 45 , 59 , 118 ,
80+ 216 , 143 , 202 , 129 , 187 , 89 , 39 , 233 , 161 , 225 , 48 , 205 , 254 , 41 , 249 });
7181static ge_p3 G_p3;
7282static ge_p3 H_p3;
83+ static ge_p3 T_p3;
84+ static ge_p3 U_p3;
85+ static ge_p3 V_p3;
7386static ge_cached G_cached;
7487static ge_cached H_cached;
88+ static ge_cached T_cached;
89+ static ge_cached U_cached;
90+ static ge_cached V_cached;
7591
7692// misc
7793static std::once_flag init_gens_once_flag;
7894
95+ // -------------------------------------------------------------------------------------------------------------------
96+ // hash-to-point: H_p(x) = unbiased_hash_to_ec(x)
97+ // -------------------------------------------------------------------------------------------------------------------
98+ static void hash_to_point (const crypto::hash &x, crypto::ec_point &point_out)
99+ {
100+ unbiased_hash_to_ec ((const unsigned char *)x.data , sizeof (crypto::hash), point_out);
101+ }
79102// -------------------------------------------------------------------------------------------------------------------
80103// -------------------------------------------------------------------------------------------------------------------
81104static public_key reproduce_generator_G ()
@@ -120,6 +143,39 @@ static public_key reproduce_generator_H()
120143 return reproduced_H;
121144}
122145// -------------------------------------------------------------------------------------------------------------------
146+ // -------------------------------------------------------------------------------------------------------------------
147+ static public_key reproduce_generator_T ()
148+ {
149+ // T = H_p(keccak("Monero Generator T"))
150+ const std::string_view T_seed{" Monero Generator T" };
151+ public_key reproduced_T;
152+ hash_to_point (cn_fast_hash (T_seed.data (), T_seed.size ()), reproduced_T);
153+
154+ return reproduced_T;
155+ }
156+ // -------------------------------------------------------------------------------------------------------------------
157+ // -------------------------------------------------------------------------------------------------------------------
158+ static public_key reproduce_generator_U ()
159+ {
160+ // U = H_p(keccak("Monero FCMP++ Generator U"))
161+ const std::string_view U_seed{" Monero FCMP++ Generator U" };
162+ public_key reproduced_U;
163+ hash_to_point (cn_fast_hash (U_seed.data (), U_seed.size ()), reproduced_U);
164+
165+ return reproduced_U;
166+ }
167+ // -------------------------------------------------------------------------------------------------------------------
168+ // -------------------------------------------------------------------------------------------------------------------
169+ static public_key reproduce_generator_V ()
170+ {
171+ // V = H_p(keccak("Monero FCMP++ Generator V"))
172+ const std::string_view V_seed{" Monero FCMP++ Generator V" };
173+ public_key reproduced_V;
174+ hash_to_point (cn_fast_hash (V_seed.data (), V_seed.size ()), reproduced_V);
175+
176+ return reproduced_V;
177+ }
178+ // -------------------------------------------------------------------------------------------------------------------
123179// Make generators, but only once
124180// -------------------------------------------------------------------------------------------------------------------
125181static void init_gens ()
@@ -130,21 +186,36 @@ static void init_gens()
130186 // sanity check the generators
131187 static_assert (static_cast <unsigned char >(G.data [0 ]) == 0x58 , " compile-time constant sanity check" );
132188 static_assert (static_cast <unsigned char >(H.data [0 ]) == 0x8b , " compile-time constant sanity check" );
189+ static_assert (static_cast <unsigned char >(T.data [0 ]) == 97 , " compile-time constant sanity check" );
190+ static_assert (static_cast <unsigned char >(U.data [0 ]) == 80 , " compile-time constant sanity check" );
191+ static_assert (static_cast <unsigned char >(V.data [0 ]) == 105 , " compile-time constant sanity check" );
133192
134193 // build ge_p3 representations of generators
135194 const int G_deserialize = ge_frombytes_vartime (&G_p3, to_bytes (G));
136195 const int H_deserialize = ge_frombytes_vartime (&H_p3, to_bytes (H));
196+ const int T_deserialize = ge_frombytes_vartime (&T_p3, to_bytes (T));
197+ const int U_deserialize = ge_frombytes_vartime (&U_p3, to_bytes (U));
198+ const int V_deserialize = ge_frombytes_vartime (&V_p3, to_bytes (V));
137199
138200 (void )G_deserialize; assert (G_deserialize == 0 );
139201 (void )H_deserialize; assert (H_deserialize == 0 );
202+ (void )T_deserialize; assert (T_deserialize == 0 );
203+ (void )U_deserialize; assert (U_deserialize == 0 );
204+ (void )V_deserialize; assert (V_deserialize == 0 );
140205
141206 // get cached versions
142207 ge_p3_to_cached (&G_cached, &G_p3);
143208 ge_p3_to_cached (&H_cached, &H_p3);
209+ ge_p3_to_cached (&T_cached, &T_p3);
210+ ge_p3_to_cached (&U_cached, &U_p3);
211+ ge_p3_to_cached (&V_cached, &V_p3);
144212
145213 // in debug mode, check that generators are reproducible
146214 (void )reproduce_generator_G; assert (reproduce_generator_G () == G);
147215 (void )reproduce_generator_H; assert (reproduce_generator_H () == H);
216+ (void )reproduce_generator_T; assert (reproduce_generator_T () == T);
217+ (void )reproduce_generator_U; assert (reproduce_generator_U () == U);
218+ (void )reproduce_generator_V; assert (reproduce_generator_V () == V);
148219
149220 });
150221}
@@ -159,6 +230,21 @@ public_key get_H()
159230 return H;
160231}
161232// -------------------------------------------------------------------------------------------------------------------
233+ public_key get_T ()
234+ {
235+ return T;
236+ }
237+ // -------------------------------------------------------------------------------------------------------------------
238+ public_key get_U ()
239+ {
240+ return U;
241+ }
242+ // -------------------------------------------------------------------------------------------------------------------
243+ public_key get_V ()
244+ {
245+ return V;
246+ }
247+ // -------------------------------------------------------------------------------------------------------------------
162248ge_p3 get_G_p3 ()
163249{
164250 init_gens ();
@@ -171,6 +257,24 @@ ge_p3 get_H_p3()
171257 return H_p3;
172258}
173259// -------------------------------------------------------------------------------------------------------------------
260+ ge_p3 get_T_p3 ()
261+ {
262+ init_gens ();
263+ return T_p3;
264+ }
265+ // -------------------------------------------------------------------------------------------------------------------
266+ ge_p3 get_U_p3 ()
267+ {
268+ init_gens ();
269+ return U_p3;
270+ }
271+ // -------------------------------------------------------------------------------------------------------------------
272+ ge_p3 get_V_p3 ()
273+ {
274+ init_gens ();
275+ return V_p3;
276+ }
277+ // -------------------------------------------------------------------------------------------------------------------
174278ge_cached get_G_cached ()
175279{
176280 init_gens ();
@@ -183,4 +287,22 @@ ge_cached get_H_cached()
183287 return H_cached;
184288}
185289// -------------------------------------------------------------------------------------------------------------------
290+ ge_cached get_T_cached ()
291+ {
292+ init_gens ();
293+ return T_cached;
294+ }
295+ // -------------------------------------------------------------------------------------------------------------------
296+ ge_cached get_U_cached ()
297+ {
298+ init_gens ();
299+ return U_cached;
300+ }
301+ // -------------------------------------------------------------------------------------------------------------------
302+ ge_cached get_V_cached ()
303+ {
304+ init_gens ();
305+ return V_cached;
306+ }
307+ // -------------------------------------------------------------------------------------------------------------------
186308} // namespace crypto
0 commit comments