Botan  2.6.0
Crypto and TLS for C++11
rsa.cpp
Go to the documentation of this file.
1 /*
2 * RSA
3 * (C) 1999-2010,2015,2016,2018 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/rsa.h>
9 #include <botan/internal/pk_ops_impl.h>
10 #include <botan/keypair.h>
11 #include <botan/blinding.h>
12 #include <botan/reducer.h>
13 #include <botan/workfactor.h>
14 #include <botan/der_enc.h>
15 #include <botan/ber_dec.h>
16 #include <botan/pow_mod.h>
17 #include <botan/monty.h>
18 #include <botan/internal/monty_exp.h>
19 
20 #if defined(BOTAN_HAS_OPENSSL)
21  #include <botan/internal/openssl.h>
22 #endif
23 
24 #if defined(BOTAN_TARGET_OS_HAS_THREADS)
25  #include <future>
26 #endif
27 
28 namespace Botan {
29 
31  {
32  return m_n.bits();
33  }
34 
36  {
37  return if_work_factor(key_length());
38  }
39 
41  {
44  }
45 
46 std::vector<uint8_t> RSA_PublicKey::public_key_bits() const
47  {
48  return DER_Encoder()
50  .encode(m_n)
51  .encode(m_e)
52  .end_cons()
54  }
55 
57  const std::vector<uint8_t>& key_bits)
58  {
59  BER_Decoder(key_bits)
61  .decode(m_n)
62  .decode(m_e)
63  .end_cons();
64  }
65 
66 /*
67 * Check RSA Public Parameters
68 */
70  {
71  if(m_n < 35 || m_n.is_even() || m_e < 3 || m_e.is_even())
72  return false;
73  return true;
74  }
75 
77  {
78  return DER_Encoder()
80  .encode(static_cast<size_t>(0))
81  .encode(m_n)
82  .encode(m_e)
83  .encode(m_d)
84  .encode(m_p)
85  .encode(m_q)
86  .encode(m_d1)
87  .encode(m_d2)
88  .encode(m_c)
89  .end_cons()
90  .get_contents();
91  }
92 
94  const secure_vector<uint8_t>& key_bits)
95  {
96  BER_Decoder(key_bits)
98  .decode_and_check<size_t>(0, "Unknown PKCS #1 key format version")
99  .decode(m_n)
100  .decode(m_e)
101  .decode(m_d)
102  .decode(m_p)
103  .decode(m_q)
104  .decode(m_d1)
105  .decode(m_d2)
106  .decode(m_c)
107  .end_cons();
108  }
109 
111  const BigInt& prime2,
112  const BigInt& exp,
113  const BigInt& d_exp,
114  const BigInt& mod) :
115  m_d{ d_exp }, m_p{ prime1 }, m_q{ prime2 }, m_d1{}, m_d2{}, m_c{ inverse_mod( m_q, m_p ) }
116  {
117  m_n = mod.is_nonzero() ? mod : m_p * m_q;
118  m_e = exp;
119 
120  if(m_d == 0)
121  {
122  const BigInt phi_n = lcm(m_p - 1, m_q - 1);
123  m_d = inverse_mod(m_e, phi_n);
124  }
125 
126  m_d1 = m_d % (m_p - 1);
127  m_d2 = m_d % (m_q - 1);
128  }
129 
130 /*
131 * Create a RSA private key
132 */
134  size_t bits, size_t exp)
135  {
136  if(bits < 1024)
137  throw Invalid_Argument(algo_name() + ": Can't make a key that is only " +
138  std::to_string(bits) + " bits long");
139  if(exp < 3 || exp % 2 == 0)
140  throw Invalid_Argument(algo_name() + ": Invalid encryption exponent");
141 
142  m_e = exp;
143 
144  do
145  {
146  m_p = random_prime(rng, (bits + 1) / 2, m_e);
147  m_q = random_prime(rng, bits - m_p.bits(), m_e);
148  m_n = m_p * m_q;
149  } while(m_n.bits() != bits);
150 
151  const BigInt phi_n = lcm(m_p - 1, m_q - 1);
152  m_d = inverse_mod(m_e, phi_n);
153  m_d1 = m_d % (m_p - 1);
154  m_d2 = m_d % (m_q - 1);
155  m_c = inverse_mod(m_q, m_p);
156  }
157 
158 /*
159 * Check Private RSA Parameters
160 */
162  {
163  if(m_n < 35 || m_n.is_even() || m_e < 3 || m_e.is_even())
164  return false;
165 
166  if(m_d < 2 || m_p < 3 || m_q < 3 || m_p*m_q != m_n)
167  return false;
168 
169  if(m_d1 != m_d % (m_p - 1) || m_d2 != m_d % (m_q - 1) || m_c != inverse_mod(m_q, m_p))
170  return false;
171 
172  const size_t prob = (strong) ? 128 : 12;
173 
174  if(!is_prime(m_p, rng, prob) || !is_prime(m_q, rng, prob))
175  return false;
176 
177  if(strong)
178  {
179  if((m_e * m_d) % lcm(m_p - 1, m_q - 1) != 1)
180  return false;
181 
182  return KeyPair::signature_consistency_check(rng, *this, "EMSA4(SHA-256)");
183  }
184 
185  return true;
186  }
187 
188 namespace {
189 
190 /**
191 * RSA private (decrypt/sign) operation
192 */
193 class RSA_Private_Operation
194  {
195  protected:
196  size_t get_max_input_bits() const { return (m_mod_bits - 1); }
197 
198  explicit RSA_Private_Operation(const RSA_PrivateKey& rsa, RandomNumberGenerator& rng) :
199  m_key(rsa),
200  m_mod_p(m_key.get_p()),
201  m_mod_q(m_key.get_q()),
202  m_monty_p(std::make_shared<Montgomery_Params>(m_key.get_p(), m_mod_p)),
203  m_monty_q(std::make_shared<Montgomery_Params>(m_key.get_q(), m_mod_q)),
204  m_powermod_e_n(m_key.get_e(), m_key.get_n()),
205  m_blinder(m_key.get_n(),
206  rng,
207  [this](const BigInt& k) { return m_powermod_e_n(k); },
208  [this](const BigInt& k) { return inverse_mod(k, m_key.get_n()); }),
209  m_mod_bytes(m_key.get_n().bytes()),
210  m_mod_bits(m_key.get_n().bits())
211  {
212  }
213 
214  BigInt blinded_private_op(const BigInt& m) const
215  {
216  if(m >= m_key.get_n())
217  throw Invalid_Argument("RSA private op - input is too large");
218 
219  return m_blinder.unblind(private_op(m_blinder.blind(m)));
220  }
221 
222  BigInt private_op(const BigInt& m) const
223  {
224  const size_t powm_window = 4;
225  const size_t exp_blinding_bits = 64;
226 
227  const BigInt d1_mask(m_blinder.rng(), exp_blinding_bits);
228  const BigInt d2_mask(m_blinder.rng(), exp_blinding_bits);
229 
230  const BigInt masked_d1 = m_key.get_d1() + (d1_mask * (m_key.get_p() - 1));
231  const BigInt masked_d2 = m_key.get_d2() + (d2_mask * (m_key.get_q() - 1));
232 
233 #if defined(BOTAN_TARGET_OS_HAS_THREADS)
234  auto future_j1 = std::async(std::launch::async, [this, &m, &masked_d1, powm_window]() {
235  auto powm_d1_p = monty_precompute(m_monty_p, m, powm_window);
236  return monty_execute(*powm_d1_p, masked_d1);
237  });
238 
239  auto powm_d2_q = monty_precompute(m_monty_q, m, powm_window);
240  BigInt j2 = monty_execute(*powm_d2_q, masked_d2);
241  BigInt j1 = future_j1.get();
242 #else
243  auto powm_d1_p = monty_precompute(m_monty_p, m, powm_window);
244  auto powm_d2_q = monty_precompute(m_monty_q, m, powm_window);
245 
246  BigInt j1 = monty_execute(*powm_d1_p, masked_d1);
247  BigInt j2 = monty_execute(*powm_d2_q, masked_d2);
248 #endif
249 
250  j1 = m_mod_p.reduce(sub_mul(j1, j2, m_key.get_c()));
251 
252  return mul_add(j1, m_key.get_q(), j2);
253  }
254 
255  const RSA_PrivateKey& m_key;
256 
257  // TODO these could all be computed once and stored in the key object
258  Modular_Reducer m_mod_p;
259  Modular_Reducer m_mod_q;
260  std::shared_ptr<const Montgomery_Params> m_monty_p;
261  std::shared_ptr<const Montgomery_Params> m_monty_q;
262 
263  Fixed_Exponent_Power_Mod m_powermod_e_n;
264  Blinder m_blinder;
265  size_t m_mod_bytes;
266  size_t m_mod_bits;
267  };
268 
269 class RSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA,
270  private RSA_Private_Operation
271  {
272  public:
273 
274  size_t max_input_bits() const override { return get_max_input_bits(); }
275 
276  RSA_Signature_Operation(const RSA_PrivateKey& rsa, const std::string& emsa, RandomNumberGenerator& rng) :
277  PK_Ops::Signature_with_EMSA(emsa),
278  RSA_Private_Operation(rsa, rng)
279  {
280  }
281 
282  secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
283  RandomNumberGenerator&) override
284  {
285  const BigInt m(msg, msg_len);
286  const BigInt x = blinded_private_op(m);
287  const BigInt c = m_powermod_e_n(x);
288  BOTAN_ASSERT(m == c, "RSA sign consistency check");
289  return BigInt::encode_1363(x, m_mod_bytes);
290  }
291  };
292 
293 class RSA_Decryption_Operation final : public PK_Ops::Decryption_with_EME,
294  private RSA_Private_Operation
295  {
296  public:
297 
298  RSA_Decryption_Operation(const RSA_PrivateKey& rsa, const std::string& eme, RandomNumberGenerator& rng) :
299  PK_Ops::Decryption_with_EME(eme),
300  RSA_Private_Operation(rsa, rng)
301  {
302  }
303 
304  secure_vector<uint8_t> raw_decrypt(const uint8_t msg[], size_t msg_len) override
305  {
306  const BigInt m(msg, msg_len);
307  const BigInt x = blinded_private_op(m);
308  const BigInt c = m_powermod_e_n(x);
309  BOTAN_ASSERT(m == c, "RSA decrypt consistency check");
310  return BigInt::encode_1363(x, m_mod_bytes);
311  }
312  };
313 
314 class RSA_KEM_Decryption_Operation final : public PK_Ops::KEM_Decryption_with_KDF,
315  private RSA_Private_Operation
316  {
317  public:
318 
319  RSA_KEM_Decryption_Operation(const RSA_PrivateKey& key,
320  const std::string& kdf,
321  RandomNumberGenerator& rng) :
322  PK_Ops::KEM_Decryption_with_KDF(kdf),
323  RSA_Private_Operation(key, rng)
324  {}
325 
326  secure_vector<uint8_t>
327  raw_kem_decrypt(const uint8_t encap_key[], size_t len) override
328  {
329  const BigInt m(encap_key, len);
330  const BigInt x = blinded_private_op(m);
331  const BigInt c = m_powermod_e_n(x);
332  BOTAN_ASSERT(m == c, "RSA KEM consistency check");
333  return BigInt::encode_1363(x, m_mod_bytes);
334  }
335  };
336 
337 /**
338 * RSA public (encrypt/verify) operation
339 */
340 class RSA_Public_Operation
341  {
342  public:
343  explicit RSA_Public_Operation(const RSA_PublicKey& rsa) :
344  m_n(rsa.get_n()),
345  m_e(rsa.get_e()),
346  m_monty_n(std::make_shared<Montgomery_Params>(m_n))
347  {}
348 
349  size_t get_max_input_bits() const { return (m_n.bits() - 1); }
350 
351  protected:
352  BigInt public_op(const BigInt& m) const
353  {
354  if(m >= m_n)
355  throw Invalid_Argument("RSA public op - input is too large");
356 
357  const size_t powm_window = 1;
358 
359  auto powm_m_n = monty_precompute(m_monty_n, m, powm_window);
360  return monty_execute_vartime(*powm_m_n, m_e);
361  }
362 
363  const BigInt& get_n() const { return m_n; }
364 
365  const BigInt& m_n;
366  const BigInt& m_e;
367  std::shared_ptr<Montgomery_Params> m_monty_n;
368  };
369 
370 class RSA_Encryption_Operation final : public PK_Ops::Encryption_with_EME,
371  private RSA_Public_Operation
372  {
373  public:
374 
375  RSA_Encryption_Operation(const RSA_PublicKey& rsa, const std::string& eme) :
376  PK_Ops::Encryption_with_EME(eme),
377  RSA_Public_Operation(rsa)
378  {
379  }
380 
381  size_t max_raw_input_bits() const override { return get_max_input_bits(); }
382 
383  secure_vector<uint8_t> raw_encrypt(const uint8_t msg[], size_t msg_len,
384  RandomNumberGenerator&) override
385  {
386  BigInt m(msg, msg_len);
387  return BigInt::encode_1363(public_op(m), m_n.bytes());
388  }
389  };
390 
391 class RSA_Verify_Operation final : public PK_Ops::Verification_with_EMSA,
392  private RSA_Public_Operation
393  {
394  public:
395 
396  size_t max_input_bits() const override { return get_max_input_bits(); }
397 
398  RSA_Verify_Operation(const RSA_PublicKey& rsa, const std::string& emsa) :
399  PK_Ops::Verification_with_EMSA(emsa),
400  RSA_Public_Operation(rsa)
401  {
402  }
403 
404  bool with_recovery() const override { return true; }
405 
406  secure_vector<uint8_t> verify_mr(const uint8_t msg[], size_t msg_len) override
407  {
408  BigInt m(msg, msg_len);
409  return BigInt::encode_locked(public_op(m));
410  }
411  };
412 
413 class RSA_KEM_Encryption_Operation final : public PK_Ops::KEM_Encryption_with_KDF,
414  private RSA_Public_Operation
415  {
416  public:
417 
418  RSA_KEM_Encryption_Operation(const RSA_PublicKey& key,
419  const std::string& kdf) :
420  PK_Ops::KEM_Encryption_with_KDF(kdf),
421  RSA_Public_Operation(key) {}
422 
423  private:
424  void raw_kem_encrypt(secure_vector<uint8_t>& out_encapsulated_key,
425  secure_vector<uint8_t>& raw_shared_key,
426  Botan::RandomNumberGenerator& rng) override
427  {
428  const BigInt r = BigInt::random_integer(rng, 1, get_n());
429  const BigInt c = public_op(r);
430 
431  out_encapsulated_key = BigInt::encode_locked(c);
432  raw_shared_key = BigInt::encode_locked(r);
433  }
434  };
435 
436 }
437 
438 std::unique_ptr<PK_Ops::Encryption>
440  const std::string& params,
441  const std::string& provider) const
442  {
443 #if defined(BOTAN_HAS_OPENSSL)
444  if(provider == "openssl" || provider.empty())
445  {
446  try
447  {
448  return make_openssl_rsa_enc_op(*this, params);
449  }
450  catch(Exception& e)
451  {
452  /*
453  * If OpenSSL for some reason could not handle this (eg due to OAEP params),
454  * throw if openssl was specifically requested but otherwise just fall back
455  * to the normal version.
456  */
457  if(provider == "openssl")
458  throw Lookup_Error("OpenSSL RSA provider rejected key:" + std::string(e.what()));
459  }
460  }
461 #endif
462 
463  if(provider == "base" || provider.empty())
464  return std::unique_ptr<PK_Ops::Encryption>(new RSA_Encryption_Operation(*this, params));
465  throw Provider_Not_Found(algo_name(), provider);
466  }
467 
468 std::unique_ptr<PK_Ops::KEM_Encryption>
470  const std::string& params,
471  const std::string& provider) const
472  {
473  if(provider == "base" || provider.empty())
474  return std::unique_ptr<PK_Ops::KEM_Encryption>(new RSA_KEM_Encryption_Operation(*this, params));
475  throw Provider_Not_Found(algo_name(), provider);
476  }
477 
478 std::unique_ptr<PK_Ops::Verification>
479 RSA_PublicKey::create_verification_op(const std::string& params,
480  const std::string& provider) const
481  {
482 #if defined(BOTAN_HAS_OPENSSL)
483  if(provider == "openssl" || provider.empty())
484  {
485  std::unique_ptr<PK_Ops::Verification> res = make_openssl_rsa_ver_op(*this, params);
486  if(res)
487  return res;
488  }
489 #endif
490 
491  if(provider == "base" || provider.empty())
492  return std::unique_ptr<PK_Ops::Verification>(new RSA_Verify_Operation(*this, params));
493 
494  throw Provider_Not_Found(algo_name(), provider);
495  }
496 
497 std::unique_ptr<PK_Ops::Decryption>
499  const std::string& params,
500  const std::string& provider) const
501  {
502 #if defined(BOTAN_HAS_OPENSSL)
503  if(provider == "openssl" || provider.empty())
504  {
505  try
506  {
507  return make_openssl_rsa_dec_op(*this, params);
508  }
509  catch(Exception& e)
510  {
511  if(provider == "openssl")
512  throw Lookup_Error("OpenSSL RSA provider rejected key:" + std::string(e.what()));
513  }
514  }
515 #endif
516 
517  if(provider == "base" || provider.empty())
518  return std::unique_ptr<PK_Ops::Decryption>(new RSA_Decryption_Operation(*this, params, rng));
519 
520  throw Provider_Not_Found(algo_name(), provider);
521  }
522 
523 std::unique_ptr<PK_Ops::KEM_Decryption>
525  const std::string& params,
526  const std::string& provider) const
527  {
528  if(provider == "base" || provider.empty())
529  return std::unique_ptr<PK_Ops::KEM_Decryption>(new RSA_KEM_Decryption_Operation(*this, params, rng));
530 
531  throw Provider_Not_Found(algo_name(), provider);
532  }
533 
534 std::unique_ptr<PK_Ops::Signature>
536  const std::string& params,
537  const std::string& provider) const
538  {
539 #if defined(BOTAN_HAS_OPENSSL)
540  if(provider == "openssl" || provider.empty())
541  {
542  std::unique_ptr<PK_Ops::Signature> res = make_openssl_rsa_sig_op(*this, params);
543  if(res)
544  return res;
545  }
546 #endif
547 
548  if(provider == "base" || provider.empty())
549  return std::unique_ptr<PK_Ops::Signature>(new RSA_Signature_Operation(*this, params, rng));
550 
551  throw Provider_Not_Found(algo_name(), provider);
552  }
553 
554 }
BigInt mul_add(const BigInt &a, const BigInt &b, const BigInt &c)
Definition: mp_numth.cpp:30
std::unique_ptr< PK_Ops::Decryption > create_decryption_op(RandomNumberGenerator &rng, const std::string &params, const std::string &provider) const override
Definition: rsa.cpp:498
size_t if_work_factor(size_t bits)
Definition: workfactor.cpp:38
std::shared_ptr< const Montgomery_Exponentation_State > monty_precompute(std::shared_ptr< const Montgomery_Params > params, const BigInt &g, size_t window_bits)
Definition: monty_exp.cpp:142
bool check_key(RandomNumberGenerator &rng, bool) const override
Definition: rsa.cpp:69
size_t estimated_strength() const override
Definition: rsa.cpp:35
std::shared_ptr< const Montgomery_Params > m_monty_p
Definition: rsa.cpp:260
std::vector< uint8_t > get_contents_unlocked()
Definition: der_enc.h:27
size_t key_length() const override
Definition: rsa.cpp:30
Modular_Reducer m_mod_q
Definition: rsa.cpp:259
const BigInt & m_e
Definition: rsa.cpp:366
std::unique_ptr< PK_Ops::KEM_Encryption > create_kem_encryption_op(RandomNumberGenerator &rng, const std::string &params, const std::string &provider) const override
Definition: rsa.cpp:469
secure_vector< uint8_t > private_key_bits() const override
Definition: rsa.cpp:76
size_t bits() const
Definition: bigint.cpp:216
BER_Decoder & decode_and_check(const T &expected, const std::string &error_msg)
Definition: ber_dec.h:163
std::unique_ptr< PK_Ops::KEM_Decryption > create_kem_decryption_op(RandomNumberGenerator &rng, const std::string &params, const std::string &provider) const override
Definition: rsa.cpp:524
secure_vector< uint8_t > get_contents()
Definition: der_enc.cpp:123
Definition: bigint.h:719
size_t m_mod_bits
Definition: rsa.cpp:266
bool is_prime(const BigInt &n, RandomNumberGenerator &rng, size_t prob, bool is_random)
Definition: numthry.cpp:482
bool is_even() const
Definition: bigint.h:296
BER_Decoder & decode(bool &v)
Definition: ber_dec.cpp:338
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:145
Fixed_Exponent_Power_Mod m_powermod_e_n
Definition: rsa.cpp:263
bool is_nonzero() const
Definition: bigint.h:308
static BigInt random_integer(RandomNumberGenerator &rng, const BigInt &min, const BigInt &max)
Definition: big_rand.cpp:45
DER_Encoder & end_cons()
Definition: der_enc.cpp:146
BigInt m_e
Definition: rsa.h:76
static secure_vector< uint8_t > encode_locked(const BigInt &n, Base base=Binary)
Definition: big_code.cpp:68
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:30
BigInt sub_mul(const BigInt &a, const BigInt &b, const BigInt &c)
Definition: mp_numth.cpp:59
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:202
BigInt monty_execute_vartime(const Montgomery_Exponentation_State &precomputed_state, const BigInt &k)
Definition: monty_exp.cpp:155
bool signature_consistency_check(RandomNumberGenerator &rng, const Private_Key &private_key, const Public_Key &public_key, const std::string &padding)
Definition: keypair.cpp:49
virtual OID get_oid() const
Definition: pk_keys.cpp:51
BER_Decoder & end_cons()
Definition: ber_dec.cpp:253
std::shared_ptr< Montgomery_Params > m_monty_n
Definition: rsa.cpp:367
BigInt lcm(const BigInt &a, const BigInt &b)
Definition: numthry.cpp:74
std::vector< uint8_t > public_key_bits() const override
Definition: rsa.cpp:46
BigInt inverse_mod(const BigInt &n, const BigInt &mod)
Definition: numthry.cpp:279
BigInt monty_execute(const Montgomery_Exponentation_State &precomputed_state, const BigInt &k)
Definition: monty_exp.cpp:149
std::shared_ptr< const Montgomery_Params > m_monty_q
Definition: rsa.cpp:261
std::string algo_name() const override
Definition: rsa.h:38
const char * what() const BOTAN_NOEXCEPT override
Definition: exceptn.h:25
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
Definition: pem.cpp:68
BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: ber_dec.cpp:239
Definition: alg_id.cpp:13
AlgorithmIdentifier algorithm_identifier() const override
Definition: rsa.cpp:40
std::unique_ptr< PK_Ops::Verification > create_verification_op(const std::string &params, const std::string &provider) const override
Definition: rsa.cpp:479
RSA_PrivateKey(const AlgorithmIdentifier &alg_id, const secure_vector< uint8_t > &key_bits)
Definition: rsa.cpp:93
BigInt random_prime(RandomNumberGenerator &rng, size_t bits, const BigInt &coprime, size_t equiv, size_t modulo, size_t prob)
Definition: make_prm.cpp:18
Blinder m_blinder
Definition: rsa.cpp:264
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:136
static secure_vector< uint8_t > encode_1363(const BigInt &n, size_t bytes)
Definition: big_code.cpp:82
std::unique_ptr< PK_Ops::Encryption > create_encryption_op(RandomNumberGenerator &rng, const std::string &params, const std::string &provider) const override
Definition: rsa.cpp:439
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88
bool check_key(RandomNumberGenerator &rng, bool) const override
Definition: rsa.cpp:161
BigInt m_n
Definition: rsa.h:76
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &rng, const std::string &params, const std::string &provider) const override
Definition: rsa.cpp:535
const RSA_PrivateKey & m_key
Definition: rsa.cpp:255
const BigInt & m_n
Definition: rsa.cpp:365
Modular_Reducer m_mod_p
Definition: rsa.cpp:258
size_t m_mod_bytes
Definition: rsa.cpp:265