33 #include <openssl/bn.h>
34 #include <openssl/err.h>
35 #include <openssl/rsa.h>
37 using namespace basis;
47 #ifdef DEBUG_RSA_CRYPTO
49 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
62 LOG(
"prior to generating key");
63 _key = generate_key(key_size);
64 LOG(
"after generating key");
73 LOG(
"prior to set key");
83 LOG(
"prior to set key");
94 LOG(
"prior to set key");
102 LOG(
"prior to rsa free");
105 LOG(
"after rsa free");
110 if (
this == &to_copy)
return *
this;
118 if (key_size < 4) key_size = 4;
120 LOG(
"into generate key");
122 RSA *to_return = RSA_new();
123 BIGNUM *e = BN_new();
124 BN_set_word(e, 65537);
126 int ret = RSA_generate_key_ex(to_return, key_size, e,
NULL_POINTER);
129 a_sprintf(
"failed to generate a key of %d bits: error is %ld.", key_size, ERR_get_error()));
134 LOG(
"after key generated");
142 return RSA_check_key(key) == 1;
147 FUNCDEF(
"set_key [byte_array]");
148 if (!key.
length())
return false;
150 if (_key) RSA_free(_key);
154 if ( (type !=
'r') && (type !=
'u') )
return false;
159 if (!the_n)
return false;
163 if (!the_e)
return false;
170 _key->n = the_n; _key->e = the_e;
179 if (!the_d)
return false;
184 if (!the_p)
return false;
188 if (!the_q)
return false;
192 if (!the_dmp1)
return false;
196 if (!the_dmq1)
return false;
200 if (!the_iqmp)
return false;
204 int ret = RSA_set0_key(_key, the_n, the_e, the_d);
205 if (ret != 1)
return false;
206 ret = RSA_set0_factors(_key, the_p, the_q);
207 if (ret != 1)
return false;
208 ret = RSA_set0_crt_params(_key, the_dmp1, the_dmq1, the_iqmp);
209 if (ret != 1)
return false;
211 _key->n = the_n; _key->e = the_e; _key->d = the_d;
212 _key->p = the_p; _key->q = the_q;
213 _key->dmp1 = the_dmp1; _key->dmq1 = the_dmq1; _key->iqmp = the_iqmp;
216 int check = RSA_check_key(_key);
219 "portion of the key!");
232 int check = RSA_check_key(key);
233 if (check != 1)
return false;
235 if (_key) RSA_free(_key);
236 _key = RSAPrivateKey_dup(key);
239 "duplicate of the key!");
248 if (!_key)
return false;
251 BIGNUM **the_n =
new BIGNUM *, **the_e =
new BIGNUM *, **the_d =
new BIGNUM *;
253 RSA_get0_key(_key, (
const BIGNUM **)the_n, (
const BIGNUM **)the_e, (
const BIGNUM **)the_d);
255 *the_n = _key->n; *the_e = _key->e; *the_d = _key->d;
258 int ret = BN_bn2bin(*the_n, n.
access());
260 ret = BN_bn2bin(*the_e, e.
access());
272 if (!_key)
return false;
273 int posn = privkey.
length();
275 if (!worked)
return false;
276 privkey[posn] =
abyte(
'r');
279 BIGNUM **the_n =
new BIGNUM *, **the_e =
new BIGNUM *, **the_d =
new BIGNUM *;
280 BIGNUM **the_p =
new BIGNUM *, **the_q =
new BIGNUM *;
281 BIGNUM **the_dmp1 =
new BIGNUM *, **the_dmq1 =
new BIGNUM *, **the_iqmp =
new BIGNUM *;
283 RSA_get0_key(_key, (
const BIGNUM **)the_n, (
const BIGNUM **)the_e, (
const BIGNUM **)the_d);
284 RSA_get0_factors(_key, (
const BIGNUM **)the_p, (
const BIGNUM **)the_q);
285 RSA_get0_crt_params(_key, (
const BIGNUM **)the_dmp1, (
const BIGNUM **)the_dmq1, (
const BIGNUM **)the_iqmp);
287 *the_n = _key->n; *the_e = _key->e; *the_d = _key->d;
288 *the_p = _key->p; *the_q = _key->q;
289 *the_dmp1 = _key->dmp1; *the_dmq1 = _key->dmq1; *the_iqmp = _key->iqmp;
292 int ret = BN_bn2bin(*the_d, d.
access());
294 ret = BN_bn2bin(*the_p, p.
access());
296 ret = BN_bn2bin(*the_q, q.
access());
298 ret = BN_bn2bin(*the_dmp1, dmp1.
access());
300 ret = BN_bn2bin(*the_dmq1, dmq1.
access());
302 ret = BN_bn2bin(*the_iqmp, iqmp.
access());
318 if (!source.
length())
return false;
321 const int max_chunk = RSA_size(_key) - 12;
324 for (
int i = 0; i < source.
length(); i += max_chunk) {
325 int edge = i + max_chunk - 1;
326 if (edge > source.
last())
327 edge = source.
last();
328 int next_chunk = edge - i + 1;
329 RSA_public_encrypt(next_chunk, &source[i],
330 encoded.
access(), _key, RSA_PKCS1_PADDING);
341 if (!source.
length())
return false;
344 const int max_chunk = RSA_size(_key);
347 for (
int i = 0; i < source.
length(); i += max_chunk) {
348 int edge = i + max_chunk - 1;
349 if (edge > source.
last())
350 edge = source.
last();
351 int next_chunk = edge - i + 1;
352 int dec_size = RSA_private_decrypt(next_chunk, &source[i],
353 decoded.
access(), _key, RSA_PKCS1_PADDING);
354 if (dec_size < 0)
return false;
355 decoded.
zap(dec_size, decoded.
last());
357 decoded.
reset(max_chunk);
367 if (!source.
length())
return false;
370 const int max_chunk = RSA_size(_key) - 12;
373 for (
int i = 0; i < source.
length(); i += max_chunk) {
374 int edge = i + max_chunk - 1;
375 if (edge > source.
last())
376 edge = source.
last();
377 int next_chunk = edge - i + 1;
378 RSA_private_encrypt(next_chunk, &source[i],
379 encoded.
access(), _key, RSA_PKCS1_PADDING);
390 if (!source.
length())
return false;
393 const int max_chunk = RSA_size(_key);
396 for (
int i = 0; i < source.
length(); i += max_chunk) {
397 int edge = i + max_chunk - 1;
398 if (edge > source.
last())
399 edge = source.
last();
400 int next_chunk = edge - i + 1;
401 int dec_size = RSA_public_decrypt(next_chunk, &source[i],
402 decoded.
access(), _key, RSA_PKCS1_PADDING);
403 if (dec_size < 0)
return false;
404 decoded.
zap(dec_size, decoded.
last());
406 decoded.
reset(max_chunk);
a_sprintf is a specialization of astring that provides printf style support.
void reset(int number=0, const contents *initial_contents=NULL_POINTER)
Resizes this array and sets the contents from an array of contents.
contents * access()
A non-constant access of the underlying C-array. BE REALLY CAREFUL.
int length() const
Returns the current reported length of the allocated C array.
outcome zap(int start, int end)
Deletes from "this" the objects inclusively between "start" and "end".
int last() const
Returns the last valid element in the array.
auto_synchronizer simplifies concurrent code by automatically unlocking.
A very common template for a dynamic array of bytes.
Supports public key encryption and decryption.
const rsa_crypto & operator=(const rsa_crypto &to_copy)
bool public_encrypt(const basis::byte_array &source, basis::byte_array &target) const
encrypts "source" using our public key and stores it in "target".
bool set_key(basis::byte_array &key)
resets this object's key to "key".
bool private_key(basis::byte_array &privkey) const
makes a copy of the private key held here.
static RSA * generate_key(int key_size)
creates a random RSA key using the lower-level openssl methods.
bool private_decrypt(const basis::byte_array &source, basis::byte_array &target) const
decrypts "source" using our private key and stores it in "target".
bool public_decrypt(const basis::byte_array &source, basis::byte_array &target) const
decrypts "source" using our public key and stores it in "target".
bool check_key(RSA *key)
checks the RSA "key" provided for validity.
bool private_encrypt(const basis::byte_array &source, basis::byte_array &target) const
encrypts "source" using our private key and stores it in "target".
bool public_key(basis::byte_array &pubkey) const
makes a copy of the public key held here.
rsa_crypto(int key_size)
constructs using a randomized private key of the "key_size".
#define continuable_error(c, f, i)
#define NULL_POINTER
The value representing a pointer to nothing.
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
The guards collection helps in testing preconditions and reporting errors.
void WHACK(contents *&ptr)
deletion with clearing of the pointer.
unsigned char abyte
A fairly important unit which is seldom defined...
const ssl_init & static_ssl_initializer()
the main method for accessing the SSL initialization support.
A logger that sends to the console screen using the standard output device.
An extension to floating point primitives providing approximate equality.
A dynamic container class that holds any kind of object via pointers.
void attach(byte_array &packed_form, const byte_array &to_attach)
Packs a byte_array "to_attach" into "packed_form".
bool detach(byte_array &packed_form, byte_array &to_detach)
Unpacks a byte_array "to_detach" from "packed_form".
#define SAFE_STATIC(type, func_name, parms)
Statically defines a singleton object whose scope is the program's lifetime.
#define static_class_name()