Botan 3.6.1
Crypto and TLS for C&
dl_group.cpp
Go to the documentation of this file.
1/*
2* Discrete Logarithm Parameters
3* (C) 1999-2008,2015,2018 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/dl_group.h>
9
10#include <botan/ber_dec.h>
11#include <botan/der_enc.h>
12#include <botan/numthry.h>
13#include <botan/pem.h>
14#include <botan/reducer.h>
15#include <botan/internal/divide.h>
16#include <botan/internal/fmt.h>
17#include <botan/internal/monty.h>
18#include <botan/internal/monty_exp.h>
19#include <botan/internal/primality.h>
20#include <botan/internal/workfactor.h>
21#include <string_view>
22
23namespace Botan {
24
25class DL_Group_Data final {
26 public:
27 DL_Group_Data(const BigInt& p, const BigInt& q, const BigInt& g, DL_Group_Source source) :
28 m_p(p),
29 m_q(q),
30 m_g(g),
31 m_mod_p(p),
32 m_mod_q(q),
33 m_monty_params(std::make_shared<Montgomery_Params>(m_p, m_mod_p)),
34 m_monty(monty_precompute(m_monty_params, m_g, /*window bits=*/4)),
35 m_p_bits(p.bits()),
36 m_q_bits(q.bits()),
37 m_estimated_strength(dl_work_factor(m_p_bits)),
38 m_exponent_bits(dl_exponent_size(m_p_bits)),
39 m_source(source) {}
40
41 ~DL_Group_Data() = default;
42
43 DL_Group_Data(const DL_Group_Data& other) = delete;
44 DL_Group_Data(DL_Group_Data&& other) = delete;
45 DL_Group_Data& operator=(const DL_Group_Data& other) = delete;
46 DL_Group_Data& operator=(DL_Group_Data&& other) = delete;
47
48 const BigInt& p() const { return m_p; }
49
50 const BigInt& q() const { return m_q; }
51
52 const BigInt& g() const { return m_g; }
53
54 BigInt mod_p(const BigInt& x) const { return m_mod_p.reduce(x); }
55
56 BigInt multiply_mod_p(const BigInt& x, const BigInt& y) const { return m_mod_p.multiply(x, y); }
57
58 BigInt mod_q(const BigInt& x) const { return m_mod_q.reduce(x); }
59
60 BigInt multiply_mod_q(const BigInt& x, const BigInt& y) const { return m_mod_q.multiply(x, y); }
61
62 BigInt square_mod_q(const BigInt& x) const { return m_mod_q.square(x); }
63
64 std::shared_ptr<const Montgomery_Params> monty_params_p() const { return m_monty_params; }
65
66 size_t p_bits() const { return m_p_bits; }
67
68 size_t q_bits() const { return m_q_bits; }
69
70 size_t p_bytes() const { return (m_p_bits + 7) / 8; }
71
72 size_t q_bytes() const { return (m_q_bits + 7) / 8; }
73
74 size_t estimated_strength() const { return m_estimated_strength; }
75
76 size_t exponent_bits() const { return m_exponent_bits; }
77
78 BigInt power_g_p(const BigInt& k, size_t max_k_bits) const { return monty_execute(*m_monty, k, max_k_bits); }
79
80 BigInt power_g_p_vartime(const BigInt& k) const { return monty_execute_vartime(*m_monty, k); }
81
82 BigInt power_b_p(const BigInt& b, const BigInt& k, size_t max_k_bits) const {
83 return monty_exp(m_monty_params, b, k, max_k_bits);
84 }
85
86 BigInt power_b_p_vartime(const BigInt& b, const BigInt& k) const {
87 return monty_exp_vartime(m_monty_params, b, k);
88 }
89
90 bool q_is_set() const { return m_q_bits > 0; }
91
92 void assert_q_is_set(std::string_view function) const {
93 if(q_is_set() == false) {
94 throw Invalid_State(fmt("DL_Group::{}: q is not set for this group", function));
95 }
96 }
97
98 DL_Group_Source source() const { return m_source; }
99
100 private:
101 BigInt m_p;
102 BigInt m_q;
103 BigInt m_g;
104 Modular_Reducer m_mod_p;
105 Modular_Reducer m_mod_q;
106 std::shared_ptr<const Montgomery_Params> m_monty_params;
107 std::shared_ptr<const Montgomery_Exponentation_State> m_monty;
108 size_t m_p_bits;
109 size_t m_q_bits;
110 size_t m_estimated_strength;
111 size_t m_exponent_bits;
112 DL_Group_Source m_source;
113};
114
115//static
116std::shared_ptr<DL_Group_Data> DL_Group::BER_decode_DL_group(const uint8_t data[],
117 size_t data_len,
118 DL_Group_Format format,
119 DL_Group_Source source) {
120 BigInt p, q, g;
121
122 BER_Decoder decoder(data, data_len);
123 BER_Decoder ber = decoder.start_sequence();
124
125 if(format == DL_Group_Format::ANSI_X9_57) {
126 ber.decode(p).decode(q).decode(g).verify_end();
127 } else if(format == DL_Group_Format::ANSI_X9_42) {
128 ber.decode(p).decode(g).decode(q).discard_remaining();
129 } else if(format == DL_Group_Format::PKCS_3) {
130 // q is left as zero
131 ber.decode(p).decode(g).discard_remaining();
132 } else {
133 throw Invalid_Argument("Unknown DL_Group encoding");
134 }
135
136 return std::make_shared<DL_Group_Data>(p, q, g, source);
137}
138
139//static
140std::shared_ptr<DL_Group_Data> DL_Group::load_DL_group_info(const char* p_str, const char* q_str, const char* g_str) {
141 const BigInt p(p_str);
142 const BigInt q(q_str);
143 const BigInt g(g_str);
144
145 return std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::Builtin);
146}
147
148//static
149std::shared_ptr<DL_Group_Data> DL_Group::load_DL_group_info(const char* p_str, const char* g_str) {
150 const BigInt p(p_str);
151 const BigInt q = (p - 1) / 2;
152 const BigInt g(g_str);
153
154 return std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::Builtin);
155}
156
157namespace {
158
159DL_Group_Format pem_label_to_dl_format(std::string_view label) {
160 if(label == "DH PARAMETERS") {
162 } else if(label == "DSA PARAMETERS") {
164 } else if(label == "X942 DH PARAMETERS" || label == "X9.42 DH PARAMETERS") {
166 } else {
167 throw Decoding_Error(fmt("DL_Group: Unknown PEM label '{}'", label));
168 }
169}
170
171} // namespace
172
173/*
174* DL_Group Constructor
175*/
176DL_Group::DL_Group(std::string_view str) {
177 // Either a name or a PEM block, try name first
178 m_data = DL_group_info(str);
179
180 if(m_data == nullptr) {
181 try {
182 std::string label;
183 const std::vector<uint8_t> ber = unlock(PEM_Code::decode(str, label));
184 DL_Group_Format format = pem_label_to_dl_format(label);
185
186 m_data = BER_decode_DL_group(ber.data(), ber.size(), format, DL_Group_Source::ExternalSource);
187 } catch(...) {}
188 }
189
190 if(m_data == nullptr) {
191 throw Invalid_Argument(fmt("DL_Group: Unknown group '{}'", str));
192 }
193}
194
195namespace {
196
197/*
198* Create generator of the q-sized subgroup (DSA style generator)
199*/
200BigInt make_dsa_generator(const BigInt& p, const BigInt& q) {
201 BigInt e, r;
202 vartime_divide(p - 1, q, e, r);
203
204 if(e == 0 || r > 0) {
205 throw Invalid_Argument("make_dsa_generator q does not divide p-1");
206 }
207
208 for(size_t i = 0; i != PRIME_TABLE_SIZE; ++i) {
209 // TODO precompute!
210 BigInt g = power_mod(BigInt::from_word(PRIMES[i]), e, p);
211 if(g > 1) {
212 return g;
213 }
214 }
215
216 throw Internal_Error("DL_Group: Couldn't create a suitable generator");
217}
218
219} // namespace
220
221/*
222* DL_Group Constructor
223*/
224DL_Group::DL_Group(RandomNumberGenerator& rng, PrimeType type, size_t pbits, size_t qbits) {
225 if(pbits < 1024) {
226 throw Invalid_Argument(fmt("DL_Group: requested prime size {} is too small", pbits));
227 }
228
229 if(qbits >= pbits) {
230 throw Invalid_Argument(fmt("DL_Group: requested q size {} is too big for p {}", qbits, pbits));
231 }
232
233 if(type == Strong) {
234 if(qbits != 0 && qbits != pbits - 1) {
235 throw Invalid_Argument("Cannot create strong-prime DL_Group with specified q bits");
236 }
237
238 const BigInt p = random_safe_prime(rng, pbits);
239 const BigInt q = (p - 1) / 2;
240
241 /*
242 Always choose a generator that is quadratic reside mod p,
243 this forces g to be a generator of the subgroup of size q.
244 */
246 if(jacobi(g, p) != 1) {
247 // prime table does not contain 2
248 for(size_t i = 0; i < PRIME_TABLE_SIZE; ++i) {
250 if(jacobi(g, p) == 1) {
251 break;
252 }
253 }
254 }
255
256 m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::RandomlyGenerated);
257 } else if(type == Prime_Subgroup) {
258 if(qbits == 0) {
259 qbits = dl_exponent_size(pbits);
260 }
261
262 const BigInt q = random_prime(rng, qbits);
263 Modular_Reducer mod_2q(2 * q);
264 BigInt X;
265 BigInt p;
266 while(p.bits() != pbits || !is_prime(p, rng, 128, true)) {
267 X.randomize(rng, pbits);
268 p = X - mod_2q.reduce(X) + 1;
269 }
270
271 const BigInt g = make_dsa_generator(p, q);
272 m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::RandomlyGenerated);
273 } else if(type == DSA_Kosherizer) {
274 if(qbits == 0) {
275 qbits = ((pbits <= 1024) ? 160 : 256);
276 }
277
278 BigInt p, q;
279 generate_dsa_primes(rng, p, q, pbits, qbits);
280 const BigInt g = make_dsa_generator(p, q);
281 m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::RandomlyGenerated);
282 } else {
283 throw Invalid_Argument("DL_Group unknown PrimeType");
284 }
285}
286
287/*
288* DL_Group Constructor
289*/
290DL_Group::DL_Group(RandomNumberGenerator& rng, const std::vector<uint8_t>& seed, size_t pbits, size_t qbits) {
291 BigInt p, q;
292
293 if(!generate_dsa_primes(rng, p, q, pbits, qbits, seed)) {
294 throw Invalid_Argument("DL_Group: The seed given does not generate a DSA group");
295 }
296
297 BigInt g = make_dsa_generator(p, q);
298
299 m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::RandomlyGenerated);
300}
301
302/*
303* DL_Group Constructor
304*/
305DL_Group::DL_Group(const BigInt& p, const BigInt& g) {
306 m_data = std::make_shared<DL_Group_Data>(p, BigInt::zero(), g, DL_Group_Source::ExternalSource);
307}
308
309/*
310* DL_Group Constructor
311*/
312DL_Group::DL_Group(const BigInt& p, const BigInt& q, const BigInt& g) {
313 m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::ExternalSource);
314}
315
316const DL_Group_Data& DL_Group::data() const {
317 if(m_data) {
318 return *m_data;
319 }
320
321 throw Invalid_State("DL_Group uninitialized");
322}
323
325 const BigInt& p = get_p();
326 const BigInt& q = get_q();
327
328 if(y <= 1 || y >= p) {
329 return false;
330 }
331
332 if(q.is_zero() == false) {
333 if(data().power_b_p_vartime(y, q) != 1) {
334 return false;
335 }
336 }
337
338 return true;
339}
340
342 const BigInt& p = get_p();
343 const BigInt& q = get_q();
344
345 if(x <= 1 || x >= p) {
346 return false;
347 }
348
349 if(q > 0 && x > q) {
350 return false;
351 }
352
353 return true;
354}
355
356bool DL_Group::verify_element_pair(const BigInt& y, const BigInt& x) const {
357 const BigInt& p = get_p();
358
359 if(y <= 1 || y >= p || x <= 1 || x >= p) {
360 return false;
361 }
362
363 if(y != this->power_g_p(x)) {
364 return false;
365 }
366
367 return true;
368}
369
370/*
371* Verify the parameters
372*/
373bool DL_Group::verify_group(RandomNumberGenerator& rng, bool strong) const {
374 const bool from_builtin = (source() == DL_Group_Source::Builtin);
375
376 if(!strong && from_builtin) {
377 return true;
378 }
379
380 const BigInt& p = get_p();
381 const BigInt& q = get_q();
382 const BigInt& g = get_g();
383
384 if(g < 2 || p < 3 || q < 0) {
385 return false;
386 }
387
388 const size_t test_prob = 128;
389 const bool is_randomly_generated = (source() != DL_Group_Source::ExternalSource);
390
391 if(!is_prime(p, rng, test_prob, is_randomly_generated)) {
392 return false;
393 }
394
395 if(q != 0) {
396 if((p - 1) % q != 0) {
397 return false;
398 }
399 if(data().power_g_p_vartime(q) != 1) {
400 return false;
401 }
402 if(!is_prime(q, rng, test_prob, is_randomly_generated)) {
403 return false;
404 }
405 } else {
406 if(!from_builtin && !is_randomly_generated) {
407 // If we got this p,g from some unknown source, try to verify
408 // that the group order is not too absurdly small.
409
410 const size_t upper_bound = strong ? 1000 : 100;
411
412 for(size_t i = 2; i != upper_bound; ++i) {
413 if(data().power_g_p_vartime(BigInt::from_word(i)) == 1) {
414 return false;
415 }
416 }
417 }
418 }
419
420 return true;
421}
422
423/*
424* Return the prime
425*/
426const BigInt& DL_Group::get_p() const {
427 return data().p();
428}
429
430/*
431* Return the generator
432*/
433const BigInt& DL_Group::get_g() const {
434 return data().g();
435}
436
437/*
438* Return the subgroup
439*/
440const BigInt& DL_Group::get_q() const {
441 return data().q();
442}
443
444std::shared_ptr<const Montgomery_Params> DL_Group::monty_params_p() const {
445 return data().monty_params_p();
446}
447
448bool DL_Group::has_q() const {
449 return data().q_is_set();
450}
451
452size_t DL_Group::p_bits() const {
453 return data().p_bits();
454}
455
456size_t DL_Group::p_bytes() const {
457 return data().p_bytes();
458}
459
460size_t DL_Group::q_bits() const {
461 data().assert_q_is_set("q_bits");
462 return data().q_bits();
463}
464
465size_t DL_Group::q_bytes() const {
466 data().assert_q_is_set("q_bytes");
467 return data().q_bytes();
468}
469
471 return data().estimated_strength();
472}
473
475 return data().exponent_bits();
476}
477
479 // precompute??
480 return inverse_mod(x, get_p());
481}
482
484 return data().mod_p(x);
485}
486
487BigInt DL_Group::multiply_mod_p(const BigInt& x, const BigInt& y) const {
488 return data().multiply_mod_p(x, y);
489}
490
492 data().assert_q_is_set("inverse_mod_q");
493 // precompute??
494 return inverse_mod(x, get_q());
495}
496
498 data().assert_q_is_set("mod_q");
499 return data().mod_q(x);
500}
501
502BigInt DL_Group::multiply_mod_q(const BigInt& x, const BigInt& y) const {
503 data().assert_q_is_set("multiply_mod_q");
504 return data().multiply_mod_q(x, y);
505}
506
507BigInt DL_Group::multiply_mod_q(const BigInt& x, const BigInt& y, const BigInt& z) const {
508 data().assert_q_is_set("multiply_mod_q");
509 return data().multiply_mod_q(data().multiply_mod_q(x, y), z);
510}
511
513 data().assert_q_is_set("square_mod_q");
514 return data().square_mod_q(x);
515}
516
517BigInt DL_Group::multi_exponentiate(const BigInt& x, const BigInt& y, const BigInt& z) const {
518 return monty_multi_exp(data().monty_params_p(), get_g(), x, y, z);
519}
520
522 return data().power_g_p(x, x.bits());
523}
524
525BigInt DL_Group::power_g_p(const BigInt& x, size_t max_x_bits) const {
526 return data().power_g_p(x, max_x_bits);
527}
528
529BigInt DL_Group::power_b_p(const BigInt& b, const BigInt& x) const {
530 return this->power_b_p(b, x, data().p_bits());
531}
532
533BigInt DL_Group::power_b_p(const BigInt& b, const BigInt& x, size_t max_x_bits) const {
534 return data().power_b_p(b, x, max_x_bits);
535}
536
538 return data().source();
539}
540
541/*
542* DER encode the parameters
543*/
544std::vector<uint8_t> DL_Group::DER_encode(DL_Group_Format format) const {
545 if(get_q().is_zero() && (format != DL_Group_Format::PKCS_3)) {
546 throw Encoding_Error("Cannot encode DL_Group in ANSI formats when q param is missing");
547 }
548
549 std::vector<uint8_t> output;
550 DER_Encoder der(output);
551
552 if(format == DL_Group_Format::ANSI_X9_57) {
554 } else if(format == DL_Group_Format::ANSI_X9_42) {
556 } else if(format == DL_Group_Format::PKCS_3) {
558 } else {
559 throw Invalid_Argument("Unknown DL_Group encoding");
560 }
561
562 return output;
563}
564
565/*
566* PEM encode the parameters
567*/
568std::string DL_Group::PEM_encode(DL_Group_Format format) const {
569 const std::vector<uint8_t> encoding = DER_encode(format);
570
571 if(format == DL_Group_Format::PKCS_3) {
572 return PEM_Code::encode(encoding, "DH PARAMETERS");
573 } else if(format == DL_Group_Format::ANSI_X9_57) {
574 return PEM_Code::encode(encoding, "DSA PARAMETERS");
575 } else if(format == DL_Group_Format::ANSI_X9_42) {
576 return PEM_Code::encode(encoding, "X9.42 DH PARAMETERS");
577 } else {
578 throw Invalid_Argument("Unknown DL_Group encoding");
579 }
580}
581
582DL_Group::DL_Group(const uint8_t ber[], size_t ber_len, DL_Group_Format format) {
583 m_data = BER_decode_DL_group(ber, ber_len, format, DL_Group_Source::ExternalSource);
584}
585
586void DL_Group::BER_decode(const std::vector<uint8_t>& ber, DL_Group_Format format) {
587 m_data = BER_decode_DL_group(ber.data(), ber.size(), format, DL_Group_Source::ExternalSource);
588}
589
590//static
592 std::string label;
593 const std::vector<uint8_t> ber = unlock(PEM_Code::decode(pem, label));
594 DL_Group_Format format = pem_label_to_dl_format(label);
595 return DL_Group(ber, format);
596}
597
598} // namespace Botan
static BigInt zero()
Definition bigint.h:50
size_t bits() const
Definition bigint.cpp:295
static BigInt from_word(word n)
Definition bigint.cpp:42
bool is_zero() const
Definition bigint.h:458
DER_Encoder & start_sequence()
Definition der_enc.h:64
DER_Encoder & end_cons()
Definition der_enc.cpp:171
DER_Encoder & encode(bool b)
Definition der_enc.cpp:250
bool verify_private_element(const BigInt &x) const
Definition dl_group.cpp:341
std::vector< uint8_t > DER_encode(DL_Group_Format format) const
Definition dl_group.cpp:544
BigInt power_g_p(const BigInt &x) const
Definition dl_group.cpp:521
BigInt mod_p(const BigInt &x) const
Definition dl_group.cpp:483
BigInt multiply_mod_p(const BigInt &x, const BigInt &y) const
Definition dl_group.cpp:487
std::shared_ptr< const Montgomery_Params > monty_params_p() const
Definition dl_group.cpp:444
size_t p_bits() const
Definition dl_group.cpp:452
std::string PEM_encode(DL_Group_Format format) const
Definition dl_group.cpp:568
const BigInt & get_p() const
Definition dl_group.cpp:426
BigInt multi_exponentiate(const BigInt &x, const BigInt &y, const BigInt &z) const
Definition dl_group.cpp:517
bool verify_public_element(const BigInt &y) const
Definition dl_group.cpp:324
BigInt square_mod_q(const BigInt &x) const
Definition dl_group.cpp:512
void BER_decode(const std::vector< uint8_t > &ber, DL_Group_Format format)
Definition dl_group.cpp:586
BigInt inverse_mod_q(const BigInt &x) const
Definition dl_group.cpp:491
size_t p_bytes() const
Definition dl_group.cpp:456
bool verify_element_pair(const BigInt &y, const BigInt &x) const
Definition dl_group.cpp:356
size_t estimated_strength() const
Definition dl_group.cpp:470
size_t q_bytes() const
Definition dl_group.cpp:465
bool has_q() const
Definition dl_group.cpp:448
DL_Group_Source source() const
Definition dl_group.cpp:537
BigInt multiply_mod_q(const BigInt &x, const BigInt &y) const
Definition dl_group.cpp:502
BigInt inverse_mod_p(const BigInt &x) const
Definition dl_group.cpp:478
size_t q_bits() const
Definition dl_group.cpp:460
DL_Group()=default
static DL_Group DL_Group_from_PEM(std::string_view pem)
Definition dl_group.cpp:591
BigInt power_b_p(const BigInt &b, const BigInt &x, size_t max_x_bits) const
Definition dl_group.cpp:533
size_t exponent_bits() const
Definition dl_group.cpp:474
BigInt mod_q(const BigInt &x) const
Definition dl_group.cpp:497
bool verify_group(RandomNumberGenerator &rng, bool strong=true) const
Definition dl_group.cpp:373
const BigInt & get_g() const
Definition dl_group.cpp:433
static std::shared_ptr< DL_Group_Data > DL_group_info(std::string_view name)
Definition dl_named.cpp:13
const BigInt & get_q() const
Definition dl_group.cpp:440
BigInt square(const BigInt &x) const
Definition reducer.h:45
BigInt multiply(const BigInt &x, const BigInt &y) const
Definition reducer.h:32
BigInt reduce(const BigInt &x) const
Definition reducer.cpp:37
int(* final)(unsigned char *, CTX *)
FE_25519 X
Definition ge.cpp:25
std::string encode(const uint8_t der[], size_t length, std::string_view label, size_t width)
Definition pem.cpp:39
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
Definition pem.cpp:62
BigInt monty_exp(const std::shared_ptr< const Montgomery_Params > &params_p, const BigInt &g, const BigInt &k, size_t max_k_bits)
Definition monty_exp.h:41
BigInt power_mod(const BigInt &base, const BigInt &exp, const BigInt &mod)
Definition numthry.cpp:284
void vartime_divide(const BigInt &x, const BigInt &y_arg, BigInt &q_out, BigInt &r_out)
Definition divide.cpp:155
BigInt random_prime(RandomNumberGenerator &rng, size_t bits, const BigInt &coprime, size_t equiv, size_t modulo, size_t prob)
Definition make_prm.cpp:97
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
DL_Group_Format
Definition dl_group.h:28
const uint16_t PRIMES[]
Definition primes.cpp:12
const size_t PRIME_TABLE_SIZE
Definition numthry.h:172
size_t dl_work_factor(size_t bits)
DL_Group_Source
Definition dl_group.h:19
BigInt monty_multi_exp(const std::shared_ptr< const Montgomery_Params > &params_p, const BigInt &x_bn, const BigInt &z1, const BigInt &y_bn, const BigInt &z2)
bool is_prime(const BigInt &n, RandomNumberGenerator &rng, size_t prob, bool is_random)
Definition numthry.cpp:355
std::vector< T > unlock(const secure_vector< T > &in)
Definition secmem.h:75
bool generate_dsa_primes(RandomNumberGenerator &rng, BigInt &p, BigInt &q, size_t pbits, size_t qbits, const std::vector< uint8_t > &seed_c, size_t offset)
Definition dsa_gen.cpp:53
BigInt monty_exp_vartime(const std::shared_ptr< const Montgomery_Params > &params_p, const BigInt &g, const BigInt &k)
Definition monty_exp.h:49
size_t dl_exponent_size(size_t bits)
const SIMD_8x32 & b
BigInt monty_execute_vartime(const Montgomery_Exponentation_State &precomputed_state, const BigInt &k)
int32_t jacobi(const BigInt &a, const BigInt &n)
Definition numthry.cpp:116
BigInt random_safe_prime(RandomNumberGenerator &rng, size_t bits)
Definition make_prm.cpp:294
BigInt inverse_mod(const BigInt &n, const BigInt &mod)
Definition mod_inv.cpp:179
BigInt monty_execute(const Montgomery_Exponentation_State &precomputed_state, const BigInt &k, size_t max_k_bits)
std::shared_ptr< const Montgomery_Exponentation_State > monty_precompute(const std::shared_ptr< const Montgomery_Params > &params, const BigInt &g, size_t window_bits, bool const_time)