MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
rsa.hpp
1 /*
2  Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; see the file COPYING. If not, write to the
15  Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
16  MA 02110-1301 USA.
17 */
18 
19 /* rsa.hpp provides RSA ES encrypt/decrypt, SSL (block type 1) sign and verify
20 */
21 
22 #ifndef TAO_CRYPT_RSA_HPP
23 #define TAO_CRYPT_RSA_HPP
24 
25 #include "integer.hpp"
26 #include "random.hpp"
27 
28 
29 namespace TaoCrypt {
30 
31 class Source;
32 
33 
34 // Public Key Length helper
35 class PK_Lengths {
36  const Integer& image_;
37 public:
38  explicit PK_Lengths(const Integer& i) : image_(i) {}
39 
40  word32 PaddedBlockBitLength() const {return image_.BitCount() - 1;}
41  word32 PaddedBlockByteLength() const
42  {return BitsToBytes(PaddedBlockBitLength());}
43 
44  word32 FixedCiphertextLength() const {return image_.ByteCount();}
45  word32 FixedMaxPlaintextLength() const
46  {return SaturatingSubtract(PaddedBlockBitLength() / 8, 10U); }
47 };
48 
49 
50 // RSA Public Key
52 protected:
53  Integer n_;
54  Integer e_;
55 public:
56  RSA_PublicKey() {}
57  explicit RSA_PublicKey(Source&);
58 
59  void Initialize(const Integer& n, const Integer& e) {n_ = n; e_ = e;}
60  void Initialize(Source&);
61 
62  Integer ApplyFunction(const Integer& x) const;
63 
64  const Integer& GetModulus() const {return n_;}
65  const Integer& GetPublicExponent() const {return e_;}
66 
67  void SetModulus(const Integer& n) {n_ = n;}
68  void SetPublicExponent(const Integer& e) {e_ = e;}
69 
70  word32 FixedCiphertextLength()
71  {
72  return PK_Lengths(n_).FixedCiphertextLength();
73  }
74 
75  RSA_PublicKey(const RSA_PublicKey& other) : n_(other.n_), e_(other.e_) {}
76  RSA_PublicKey& operator=(const RSA_PublicKey& that)
77  {
78  RSA_PublicKey tmp(that);
79  Swap(tmp);
80  return *this;
81  }
82 
83  void Swap(RSA_PublicKey& other)
84  {
85  n_.Swap(other.n_);
86  e_.Swap(other.e_);
87  }
88 };
89 
90 
91 // RSA Private Key
92 class RSA_PrivateKey : public RSA_PublicKey {
93  Integer d_;
94  Integer p_;
95  Integer q_;
96  Integer dp_;
97  Integer dq_;
98  Integer u_;
99 public:
100  RSA_PrivateKey() {}
101  explicit RSA_PrivateKey(Source&);
102 
103  void Initialize(const Integer& n, const Integer& e, const Integer& d,
104  const Integer& p, const Integer& q, const Integer& dp,
105  const Integer& dq, const Integer& u)
106  {n_ = n; e_ = e; d_ = d; p_ = p; q_ = q; dp_ = dp; dq_ = dq; u_ = u;}
107  void Initialize(Source&);
108 
109  Integer CalculateInverse(RandomNumberGenerator&, const Integer&) const;
110 
111  const Integer& GetPrime1() const {return p_;}
112  const Integer& GetPrime2() const {return q_;}
113  const Integer& GetPrivateExponent() const {return d_;}
114  const Integer& GetModPrime1PrivateExponent() const {return dp_;}
115  const Integer& GetModPrime2PrivateExponent() const {return dq_;}
116  const Integer& GetMultiplicativeInverseOfPrime2ModPrime1() const
117  {return u_;}
118 
119  void SetPrime1(const Integer& p) {p_ = p;}
120  void SetPrime2(const Integer& q) {q_ = q;}
121  void SetPrivateExponent(const Integer& d) {d_ = d;}
122  void SetModPrime1PrivateExponent(const Integer& dp) {dp_ = dp;}
123  void SetModPrime2PrivateExponent(const Integer& dq) {dq_ = dq;}
124  void SetMultiplicativeInverseOfPrime2ModPrime1(const Integer& u) {u_ = u;}
125 private:
126  RSA_PrivateKey(const RSA_PrivateKey&); // hide copy
127  RSA_PrivateKey& operator=(const RSA_PrivateKey&); // and assign
128 };
129 
130 
131 // block type 2 padding
133 public:
134  void Pad(const byte*, word32, byte*, word32,
135  RandomNumberGenerator&) const;
136  word32 UnPad(const byte*, word32, byte*) const;
137 };
138 
139 
140 // block type 1 padding
142 public:
143  void Pad(const byte*, word32, byte*, word32,
144  RandomNumberGenerator&) const;
145  word32 UnPad(const byte*, word32, byte*) const;
146 };
147 
148 
149 // RSA Encryptor, can use any padding
150 template<class Pad = RSA_BlockType2>
152  const RSA_PublicKey& key_;
153  Pad padding_;
154 public:
155  explicit RSA_Encryptor(const RSA_PublicKey& k) : key_(k) {}
156 
157  void Encrypt(const byte*, word32, byte*, RandomNumberGenerator&);
158  bool SSL_Verify(const byte* msg, word32 sz, const byte* sig);
159 };
160 
161 
162 // RSA Decryptor, can use any padding
163 template<class Pad = RSA_BlockType2>
165  const RSA_PrivateKey& key_;
166  Pad padding_;
167 public:
168  explicit RSA_Decryptor(const RSA_PrivateKey& k) : key_(k) {}
169 
170  word32 Decrypt(const byte*, word32, byte*, RandomNumberGenerator&);
171  void SSL_Sign(const byte*, word32, byte*, RandomNumberGenerator&);
172 };
173 
174 
175 // Public Encrypt
176 template<class Pad>
177 void RSA_Encryptor<Pad>::Encrypt(const byte* plain, word32 sz, byte* cipher,
179 {
180  PK_Lengths lengths(key_.GetModulus());
181  if (sz > lengths.FixedMaxPlaintextLength())
182  return;
183 
184  ByteBlock paddedBlock(lengths.PaddedBlockByteLength());
185  padding_.Pad(plain, sz, paddedBlock.get_buffer(),
186  lengths.PaddedBlockBitLength(), rng);
187 
188  key_.ApplyFunction(Integer(paddedBlock.get_buffer(), paddedBlock.size())).
189  Encode(cipher, lengths.FixedCiphertextLength());
190 }
191 
192 
193 // Private Decrypt
194 template<class Pad>
195 word32 RSA_Decryptor<Pad>::Decrypt(const byte* cipher, word32 sz, byte* plain,
196  RandomNumberGenerator& rng)
197 {
198  PK_Lengths lengths(key_.GetModulus());
199 
200  if (sz != lengths.FixedCiphertextLength())
201  return 0;
202 
203  ByteBlock paddedBlock(lengths.PaddedBlockByteLength());
204  Integer x = key_.CalculateInverse(rng, Integer(cipher,
205  lengths.FixedCiphertextLength()).Ref());
206  if (x.ByteCount() > paddedBlock.size())
207  x = Integer::Zero(); // don't return false, prevents timing attack
208  x.Encode(paddedBlock.get_buffer(), paddedBlock.size());
209  return padding_.UnPad(paddedBlock.get_buffer(),
210  lengths.PaddedBlockBitLength(), plain);
211 }
212 
213 
214 // Private SSL type (block 1) Encrypt
215 template<class Pad>
216 void RSA_Decryptor<Pad>::SSL_Sign(const byte* message, word32 sz, byte* sig,
217  RandomNumberGenerator& rng)
218 {
219  RSA_PublicKey inverse;
220  inverse.Initialize(key_.GetModulus(), key_.GetPrivateExponent());
221  RSA_Encryptor<RSA_BlockType1> enc(inverse); // SSL Type
222  enc.Encrypt(message, sz, sig, rng);
223 }
224 
225 
226 word32 SSL_Decrypt(const RSA_PublicKey& key, const byte* sig, byte* plain);
227 
228 
229 // Public SSL type (block 1) Decrypt
230 template<class Pad>
231 bool RSA_Encryptor<Pad>::SSL_Verify(const byte* message, word32 sz,
232  const byte* sig)
233 {
234  ByteBlock plain(PK_Lengths(key_.GetModulus()).FixedMaxPlaintextLength());
235  if (SSL_Decrypt(key_, sig, plain.get_buffer()) != sz)
236  return false; // not right justified or bad padding
237 
238  if ( (memcmp(plain.get_buffer(), message, sz)) == 0)
239  return true;
240  return false;
241 }
242 
243 
244 typedef RSA_Encryptor<> RSAES_Encryptor;
245 typedef RSA_Decryptor<> RSAES_Decryptor;
246 
247 
248 } // namespace
249 
250 #endif // TAO_CRYPT_RSA_HPP