1 /*****************************************************************************\
3 * Name : RSA public key encryption *
4 * Author : Chris Koeritz *
8 * Supports public (and private) key encryption and decryption using the *
9 * OpenSSL package's support for RSA encryption. *
11 *******************************************************************************
12 * Copyright (c) 2005-$now By Author. This program is free software; you can *
13 * redistribute it and/or modify it under the terms of the GNU General Public *
14 * License as published by the Free Software Foundation; either version 2 of *
15 * the License or (at your option) any later version. This is online at: *
16 * http://www.fsf.org/copyleft/gpl.html *
17 * Please send any updates to: fred@gruntose.com *
18 \*****************************************************************************/
20 #include "rsa_crypto.h"
23 #include <basis/functions.h>
24 #include <loggers/critical_events.h>
25 #include <mathematics/chaos.h>
26 #include <structures/object_packers.h>
28 #include <openssl/bn.h>
29 #include <openssl/rsa.h>
31 using namespace basis;
32 using namespace loggers;
33 using namespace mathematics;
34 using namespace structures;
38 // notes from openssl docs: length to be encrypted in a chunk must be less than
39 // RSA_size(rsa) - 11 for the PKCS #1 v1.5 based padding modes, less than
40 // RSA_size(rsa) - 41 for RSA_PKCS1_OAEP_PADDING and exactly RSA_size(rsa)
41 // for RSA_NO_PADDING.
44 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
46 //nice printing method... RSA_print_fp(stdout, private_key, 0);
48 rsa_crypto::rsa_crypto(int key_size)
51 _key = generate_key(key_size); // generate_key initializes ssl for us.
54 rsa_crypto::rsa_crypto(const byte_array &key)
57 static_ssl_initializer();
58 byte_array key_copy = key;
62 rsa_crypto::rsa_crypto(rsa_st *key)
65 static_ssl_initializer();
69 rsa_crypto::rsa_crypto(const rsa_crypto &to_copy)
73 static_ssl_initializer();
74 set_key(to_copy._key);
77 rsa_crypto::~rsa_crypto()
82 const rsa_crypto &rsa_crypto::operator = (const rsa_crypto &to_copy)
84 if (this == &to_copy) return *this;
85 set_key(to_copy._key);
89 rsa_st *rsa_crypto::generate_key(int key_size)
91 FUNCDEF("generate_key");
92 if (key_size < 4) key_size = 4; // laughable lower default.
93 static_ssl_initializer();
94 rsa_st *to_return = RSA_generate_key(key_size, 65537, NIL, NIL);
96 continuable_error(static_class_name(), func,
97 a_sprintf("failed to generate a key of %d bits.", key_size));
102 bool rsa_crypto::check_key(rsa_st *key) { return RSA_check_key(key) == 1; }
104 bool rsa_crypto::set_key(byte_array &key)
106 FUNCDEF("set_key [byte_array]");
107 if (!key.length()) return false;
108 if (_key) RSA_free(_key);
111 if (!structures::detach(key, type)) return false;
112 if ( (type != 'r') && (type != 'u') ) return false;
113 // get the public key bits first.
115 if (!structures::detach(key, n)) return false;
116 _key->n = BN_bin2bn(n.access(), n.length(), NIL);
117 if (!_key->n) return false;
119 if (!structures::detach(key, e)) return false;
120 _key->e = BN_bin2bn(e.access(), e.length(), NIL);
121 if (!_key->e) return false;
122 if (type == 'u') return true; // done with public key.
124 // the rest is for a private key.
126 if (!structures::detach(key, d)) return false;
127 _key->d = BN_bin2bn(d.access(), d.length(), NIL);
128 if (!_key->d) return false;
130 if (!structures::detach(key, p)) return false;
131 _key->p = BN_bin2bn(p.access(), p.length(), NIL);
132 if (!_key->p) return false;
134 if (!structures::detach(key, q)) return false;
135 _key->q = BN_bin2bn(q.access(), q.length(), NIL);
136 if (!_key->q) return false;
138 if (!structures::detach(key, dmp1)) return false;
139 _key->dmp1 = BN_bin2bn(dmp1.access(), dmp1.length(), NIL);
140 if (!_key->dmp1) return false;
142 if (!structures::detach(key, dmq1)) return false;
143 _key->dmq1 = BN_bin2bn(dmq1.access(), dmq1.length(), NIL);
144 if (!_key->dmq1) return false;
146 if (!structures::detach(key, iqmp)) return false;
147 _key->iqmp = BN_bin2bn(iqmp.access(), iqmp.length(), NIL);
148 if (!_key->iqmp) return false;
149 int check = RSA_check_key(_key);
151 continuable_error(static_class_name(), func, "failed to check the private "
152 "portion of the key!");
159 bool rsa_crypto::set_key(rsa_st *key)
161 FUNCDEF("set_key [rsa_st]");
162 if (!key) return NIL;
163 // test the incoming key.
164 int check = RSA_check_key(key);
165 if (check != 1) return false;
166 // clean out the old key.
167 if (_key) RSA_free(_key);
168 _key = RSAPrivateKey_dup(key);
170 continuable_error(static_class_name(), func, "failed to create a "
171 "duplicate of the key!");
177 bool rsa_crypto::public_key(byte_array &pubkey) const
179 // FUNCDEF("public_key");
180 if (!_key) return false;
181 structures::attach(pubkey, abyte('u')); // signal a public key.
182 // convert the two public portions into binary.
183 byte_array n(BN_num_bytes(_key->n));
184 int ret = BN_bn2bin(_key->n, n.access());
185 byte_array e(BN_num_bytes(_key->e));
186 ret = BN_bn2bin(_key->e, e.access());
187 // pack those two chunks.
188 structures::attach(pubkey, n);
189 structures::attach(pubkey, e);
193 bool rsa_crypto::private_key(byte_array &privkey) const
195 // FUNCDEF("private_key");
196 if (!_key) return false;
197 int posn = privkey.length();
198 bool worked = public_key(privkey); // get the public pieces first.
199 if (!worked) return false;
200 privkey[posn] = abyte('r'); // switch public key flag to private.
201 // convert the multiple private portions into binary.
202 byte_array d(BN_num_bytes(_key->d));
203 int ret = BN_bn2bin(_key->d, d.access());
204 byte_array p(BN_num_bytes(_key->p));
205 ret = BN_bn2bin(_key->p, p.access());
206 byte_array q(BN_num_bytes(_key->q));
207 ret = BN_bn2bin(_key->q, q.access());
208 byte_array dmp1(BN_num_bytes(_key->dmp1));
209 ret = BN_bn2bin(_key->dmp1, dmp1.access());
210 byte_array dmq1(BN_num_bytes(_key->dmq1));
211 ret = BN_bn2bin(_key->dmq1, dmq1.access());
212 byte_array iqmp(BN_num_bytes(_key->iqmp));
213 ret = BN_bn2bin(_key->iqmp, iqmp.access());
214 // pack all those in now.
215 structures::attach(privkey, d);
216 structures::attach(privkey, p);
217 structures::attach(privkey, q);
218 structures::attach(privkey, dmp1);
219 structures::attach(privkey, dmq1);
220 structures::attach(privkey, iqmp);
224 bool rsa_crypto::public_encrypt(const byte_array &source,
225 byte_array &target) const
227 // FUNCDEF("public_encrypt");
229 if (!source.length()) return false;
230 const int max_chunk = RSA_size(_key) - 12;
232 byte_array encoded(RSA_size(_key));
233 for (int i = 0; i < source.length(); i += max_chunk) {
234 int edge = i + max_chunk - 1;
235 if (edge > source.last())
236 edge = source.last();
237 int next_chunk = edge - i + 1;
238 RSA_public_encrypt(next_chunk, &source[i],
239 encoded.access(), _key, RSA_PKCS1_PADDING);
245 bool rsa_crypto::private_decrypt(const byte_array &source,
246 byte_array &target) const
248 // FUNCDEF("private_decrypt");
250 if (!source.length()) return false;
251 const int max_chunk = RSA_size(_key);
253 byte_array decoded(max_chunk);
254 for (int i = 0; i < source.length(); i += max_chunk) {
255 int edge = i + max_chunk - 1;
256 if (edge > source.last())
257 edge = source.last();
258 int next_chunk = edge - i + 1;
259 int dec_size = RSA_private_decrypt(next_chunk, &source[i],
260 decoded.access(), _key, RSA_PKCS1_PADDING);
261 if (dec_size < 0) return false; // that didn't work.
262 decoded.zap(dec_size, decoded.last());
264 decoded.reset(max_chunk);
269 bool rsa_crypto::private_encrypt(const byte_array &source,
270 byte_array &target) const
272 // FUNCDEF("private_encrypt");
274 if (!source.length()) return false;
275 const int max_chunk = RSA_size(_key) - 12;
277 byte_array encoded(RSA_size(_key));
278 for (int i = 0; i < source.length(); i += max_chunk) {
279 int edge = i + max_chunk - 1;
280 if (edge > source.last())
281 edge = source.last();
282 int next_chunk = edge - i + 1;
283 RSA_private_encrypt(next_chunk, &source[i],
284 encoded.access(), _key, RSA_PKCS1_PADDING);
290 bool rsa_crypto::public_decrypt(const byte_array &source,
291 byte_array &target) const
293 // FUNCDEF("public_decrypt");
295 if (!source.length()) return false;
296 const int max_chunk = RSA_size(_key);
298 byte_array decoded(max_chunk);
299 for (int i = 0; i < source.length(); i += max_chunk) {
300 int edge = i + max_chunk - 1;
301 if (edge > source.last())
302 edge = source.last();
303 int next_chunk = edge - i + 1;
304 int dec_size = RSA_public_decrypt(next_chunk, &source[i],
305 decoded.access(), _key, RSA_PKCS1_PADDING);
306 if (dec_size < 0) return false; // that didn't work.
307 decoded.zap(dec_size, decoded.last());
309 decoded.reset(max_chunk);