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