aboutsummaryrefslogtreecommitdiffstats
path: root/src/pubkey/rsa/rsa.cpp
blob: 51c9fd19c6fe68fae89d553cfa3c28ccd8b5aab5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
* RSA
* (C) 1999-2010 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/

#include <botan/rsa.h>
#include <botan/parsing.h>
#include <botan/numthry.h>
#include <botan/keypair.h>
#include <future>

namespace Botan {

/*
* Create a RSA private key
*/
RSA_PrivateKey::RSA_PrivateKey(RandomNumberGenerator& rng,
                               u32bit bits, u32bit exp)
   {
   if(bits < 512)
      throw Invalid_Argument(algo_name() + ": Can't make a key that is only " +
                             std::to_string(bits) + " bits long");
   if(exp < 3 || exp % 2 == 0)
      throw Invalid_Argument(algo_name() + ": Invalid encryption exponent");

   e = exp;
   p = random_prime(rng, (bits + 1) / 2, e);
   q = random_prime(rng, bits - p.bits(), e);
   n = p * q;

   if(n.bits() != bits)
      throw Self_Test_Failure(algo_name() + " private key generation failed");

   d = inverse_mod(e, lcm(p - 1, q - 1));
   d1 = d % (p - 1);
   d2 = d % (q - 1);
   c = inverse_mod(q, p);

   gen_check(rng);
   }

/*
* Check Private RSA Parameters
*/
bool RSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const
   {
   if(!IF_Scheme_PrivateKey::check_key(rng, strong))
      return false;

   if(!strong)
      return true;

   if((e * d) % lcm(p - 1, q - 1) != 1)
      return false;

   try
      {
      PK_Signer this_signer(*this, "EMSA4(SHA-1)");
      PK_Verifier this_verifier(*this, "EMSA4(SHA-1)");

      KeyPair::check_key(rng,
                         this_signer,
                         this_verifier);
      }
   catch(Self_Test_Failure)
      {
      return false;
      }

   return true;
   }

RSA_Private_Operation::RSA_Private_Operation(const RSA_PrivateKey& rsa) :
   n(rsa.get_n()),
   q(rsa.get_q()),
   c(rsa.get_c()),
   powermod_e_n(rsa.get_e(), rsa.get_n()),
   powermod_d1_p(rsa.get_d1(), rsa.get_p()),
   powermod_d2_q(rsa.get_d2(), rsa.get_q()),
   mod_p(rsa.get_p())
   {
   BigInt k = Blinder::choose_nonce(powermod_e_n(q), n);
   blinder = Blinder(powermod_e_n(k), inverse_mod(k, n), n);
   }

BigInt RSA_Private_Operation::private_op(const BigInt& m) const
   {
   if(m >= n)
      throw Invalid_Argument("RSA private op - input is too large");

   auto future_j1 = std::async(std::launch::async, powermod_d1_p, m);
   BigInt j2 = powermod_d2_q(m);
   BigInt j1 = future_j1.get();

   j1 = mod_p.reduce(sub_mul(j1, j2, c));

   return mul_add(j1, q, j2);
   }

SecureVector<byte>
RSA_Private_Operation::sign(const byte msg[], u32bit msg_len,
                            RandomNumberGenerator&)
   {
   /* We don't check signatures against powermod_e_n here because
      PK_Signer checks verification consistency for all signature
      algorithms.
   */

   BigInt m(msg, msg_len);
   BigInt x = blinder.unblind(private_op(blinder.blind(m)));
   return BigInt::encode_1363(x, n.bytes());
   }

/*
* RSA Decryption Operation
*/
SecureVector<byte>
RSA_Private_Operation::decrypt(const byte msg[], u32bit msg_len)
   {
   BigInt m(msg, msg_len);
   BigInt x = blinder.unblind(private_op(blinder.blind(m)));

   if(m != powermod_e_n(x))
      throw Internal_Error("RSA private op failed consistency check");

   return BigInt::encode(x);
   }

}