From: Fred T. Hamster Date: Sat, 14 Mar 2026 00:05:29 +0000 (-0400) Subject: breaking changes, not finished X-Git-Url: https://feistymeow.org/gitweb/?a=commitdiff_plain;h=01d10552f7daf4cc5fea727ecb6c997c62921277;p=feisty_meow.git breaking changes, not finished will not build quite yet, but nearly there... --- diff --git a/nucleus/library/crypto/blowfish_crypto.cpp b/nucleus/library/crypto/blowfish_crypto.cpp index b68c7d45..3c0596d6 100644 --- a/nucleus/library/crypto/blowfish_crypto.cpp +++ b/nucleus/library/crypto/blowfish_crypto.cpp @@ -1,16 +1,14 @@ -/*****************************************************************************\ -* * -* Name : blowfish encryption * -* Author : Chris Koeritz * -* * -******************************************************************************* -* Copyright (c) 2005-$now By Author. This program is free software; you can * -* redistribute it and/or modify it under the terms of the GNU General Public * -* License as published by the Free Software Foundation; either version 2 of * -* the License or (at your option) any later version. This is online at: * -* http://www.fsf.org/copyleft/gpl.html * -* Please send any updates to: fred@gruntose.com * -\*****************************************************************************/ +/* +* Name : blowfish encryption +* Author : Chris Koeritz +***** +* Copyright (c) 2005-$now By Author. This program is free software; you can +* redistribute it and/or modify it under the terms of the GNU General Public +* License as published by the Free Software Foundation; either version 2 of +* the License or (at your option) any later version. This is online at: +* http://www.fsf.org/copyleft/gpl.html +* Please send any updates to: fred@gruntose.com +*/ #include "blowfish_crypto.h" #include "ssl_init.h" @@ -34,7 +32,7 @@ using namespace structures; namespace crypto { -const int FUDGE = 128; +////const int FUDGE = 128; // extra space for the cipher's block size. blowfish is only 8 bytes for // the cipher block size, but we ensure there will definitely be no // problems. @@ -42,9 +40,8 @@ const int FUDGE = 128; //#undef set_key // get rid of a macro we don't want. -#define DEBUG_BLOWFISH +//#define DEBUG_BLOWFISH // uncomment for noisier version. - #undef ALWAYS_LOG #define ALWAYS_LOG(t) CLASS_EMERGENCY_LOG(program_wide_logger::get(), t) #ifdef DEBUG_BLOWFISH @@ -56,9 +53,10 @@ const int FUDGE = 128; #endif // helpful macro for the error string of last failure. -#define GET_SSL_ERROR() \ - ERR_error_string(ERR_get_error(), NULL_POINTER) +//#define GET_SSL_ERROR() \ +// ERR_error_string(ERR_get_error(), NULL_POINTER) +/* #ifdef DEBUG_BLOWFISH // this macro checks on the validity of the key sizes (in bits). #define DISCUSS_KEY_SIZE(key_size) \ @@ -85,11 +83,14 @@ const int FUDGE = 128; #define DISCUSS_PROVIDED_KEY(key_size, key) #define DISCUSS_KEY_SIZE(key_size) #endif +*/ blowfish_crypto::blowfish_crypto(int key_size) -: _key_size(key_size), - _key(new byte_array) +: cryptical_envelopment(key_size, EVP_bf_cbc()) +///_key_size(key_size), +/// _key(new byte_array) { +/* FUNCDEF("ctor(int)"); static_ssl_initializer(); LOG("prior to key size discuss"); @@ -101,12 +102,15 @@ blowfish_crypto::blowfish_crypto(int key_size) LOG("prior to generate key"); generate_key(_key_size, *_key); LOG("after generate key"); +*/ } blowfish_crypto::blowfish_crypto(const byte_array &key, int key_size) -: _key_size(key_size), - _key(new byte_array(key)) +: cryptical_envelopment(key, key_size, EVP_bf_cbc()) +//: _key_size(key_size), +// _key(new byte_array(key)) { +/* FUNCDEF("ctor(byte_array,int)"); static_ssl_initializer(); // any problems with the key provided are horrid. they will yield a @@ -117,26 +121,31 @@ blowfish_crypto::blowfish_crypto(const byte_array &key, int key_size) DISCUSS_PROVIDED_KEY(key_size, key); LOG("prior to ssl static init"); LOG("after ssl static init"); +*/ } blowfish_crypto::blowfish_crypto(const blowfish_crypto &to_copy) : root_object(), - _key_size(to_copy._key_size), - _key(new byte_array(*to_copy._key)) + cryptical_envelopment(*this) +/// _key_size(to_copy._key_size), +/// _key(new byte_array(*to_copy._key)) { - FUNCDEF("copy ctor"); - static_ssl_initializer(); - LOG("after ssl static init"); +/// FUNCDEF("copy ctor"); +/// static_ssl_initializer(); +/// LOG("after ssl static init"); } blowfish_crypto::~blowfish_crypto() { +/* FUNCDEF("destructor"); LOG("prior to key whack"); WHACK(_key); LOG("after key whack"); +*/ } +/* int blowfish_crypto::key_size() const { return _key_size; } const byte_array &blowfish_crypto::get_key() const { return *_key; } @@ -144,15 +153,20 @@ const byte_array &blowfish_crypto::get_key() const { return *_key; } int blowfish_crypto::minimum_key_size() { return 64; } int blowfish_crypto::maximum_key_size() { return 448; } +*/ blowfish_crypto &blowfish_crypto::operator = (const blowfish_crypto &to_copy) { if (this == &to_copy) return *this; - _key_size = to_copy._key_size; - *_key = *to_copy._key; + *((cryptical_envelopment *)this) = *((cryptical_envelopment *)&to_copy); +//hmmm: is that the best way to do this? + +// _key_size = to_copy._key_size; +// *_key = *to_copy._key; return *this; } +/* bool blowfish_crypto::set_key(const byte_array &new_key, int key_size) { FUNCDEF("set_key"); @@ -349,6 +363,7 @@ ALWAYS_LOG(">>decrypt>>"); ALWAYS_LOG("< #include +#include "cryptical_envelopment.h" + namespace crypto { //! Provides BlowFish encryption on byte_arrays using the OpenSSL package. -class blowfish_crypto : public virtual basis::root_object +class blowfish_crypto : public cryptical_envelopment +//: public virtual basis::root_object { public: blowfish_crypto(int key_size); @@ -46,30 +49,30 @@ public: DEFINE_CLASS_NAME("blowfish_crypto"); - int key_size() const; // returns the size of our key, in bits. +/// int key_size() const; // returns the size of our key, in bits. - static int minimum_key_size(); - //!< returns the minimum key size (in bits) supported here. - static int maximum_key_size(); - //!< returns the maximum key size (in bits) supported here. +/// static int minimum_key_size(); +/// //!< returns the minimum key size (in bits) supported here. +/// static int maximum_key_size(); +/// //!< returns the maximum key size (in bits) supported here. - const basis::byte_array &get_key() const; //!< returns our current key. +/// const basis::byte_array &get_key() const; //!< returns our current key. - bool set_key(const basis::byte_array &new_key, int key_size); +/// bool set_key(const basis::byte_array &new_key, int key_size); //!< sets the encryption key to "new_key". - static void generate_key(int size, basis::byte_array &new_key); +/// static void generate_key(int size, basis::byte_array &new_key); //!< creates a "new_key" of the "size" (in bits) specified. - bool encrypt(const basis::byte_array &source, basis::byte_array &target) const; +/// bool encrypt(const basis::byte_array &source, basis::byte_array &target) const; //!< encrypts the "source" array into the "target" array. - bool decrypt(const basis::byte_array &source, basis::byte_array &target) const; +/// bool decrypt(const basis::byte_array &source, basis::byte_array &target) const; //!< decrypts the "target" array from the encrypted "source" array. // seldom-needed methods... - static const basis::byte_array &init_vector(); +/// static const basis::byte_array &init_vector(); //!< returns the initialization vector that is used by this class. /*!< decryption of chunks that were encrypted by this class will require the same init vector as this function returns. this is mainly provided @@ -80,8 +83,8 @@ public: (currently named blowfish_crypto.cpp). */ private: - int _key_size; //!< number of bits in the key. - basis::byte_array *_key; //!< our secret key. +/// int _key_size; //!< number of bits in the key. +/// basis::byte_array *_key; //!< our secret key. }; } //namespace. diff --git a/nucleus/library/crypto/cryptical_envelopment.cpp b/nucleus/library/crypto/cryptical_envelopment.cpp new file mode 100644 index 00000000..e717d1be --- /dev/null +++ b/nucleus/library/crypto/cryptical_envelopment.cpp @@ -0,0 +1,367 @@ +/*****************************************************************************\ +* * +* Name : cryptical_envelopment * +* Author : Chris Koeritz * +* * +******************************************************************************* +* Copyright (c) 2005-$now By Author. This program is free software; you can * +* redistribute it and/or modify it under the terms of the GNU General Public * +* License as published by the Free Software Foundation; either version 2 of * +* the License or (at your option) any later version. This is online at: * +* http://www.fsf.org/copyleft/gpl.html * +* Please send any updates to: fred@gruntose.com * +\*****************************************************************************/ + +#include "cryptical_envelopment.h" +#include "ssl_init.h" + +#include +#include +#include +#include +#include +#include +#include + +///#include +#include +#include + +using namespace basis; +using namespace loggers; +using namespace mathematics; +using namespace structures; + +namespace crypto { + +const int FUDGE = 1024; + /* extra space for the cipher's block size. blowfish, e.g., is only 8 bytes for + the cipher block size, so we'd only ever need possibly 8 bytes padding? + */ +//hmmm: guarantee the fudge space is enough for other algorithms! + +//#undef set_key + // get rid of a macro we don't want. + +#define DEBUG_CRYPTICAL_ENVELOPMENT + // uncomment for noisier version. + +// our logging via LOG is disabled unless the debugging flag above is turned on. +// but the ALWAYS_LOG macro is unfazed and will log regardless of the flag. +#undef ALWAYS_LOG +#define ALWAYS_LOG(t) CLASS_EMERGENCY_LOG(program_wide_logger::get(), t) +#ifdef DEBUG_CRYPTICAL_ENVELOPMENT + #undef LOG + #define LOG(t) CLASS_EMERGENCY_LOG(program_wide_logger::get(), t) +#else + #undef LOG + #define LOG(t) +#endif + +// helpful macro for the error string of last failure. +#define GET_SSL_ERROR() \ + ERR_error_string(ERR_get_error(), NULL_POINTER) + +#ifdef DEBUG_CRYPTICAL_ENVELOPMENT + +/// // this macro checks on the validity of the key sizes (in bits). +/// #define DISCUSS_KEY_SIZE(key_size) \ +/// if (key_size < minimum_key_size()) { \ +/// deadly_error(static_class_name(), func, \ +/// a_sprintf("key size (%d bits) is less than minimum key size %d.", \ +/// key_size, minimum_key_size())); \ +/// } \ +/// if (key_size > maximum_key_size()) { \ +/// deadly_error(static_class_name(), func, \ +/// a_sprintf("key size (%d bits) is greater than maximum key size %d.", \ +/// key_size, maximum_key_size())); \ +/// } + + // this macro checks that the key in the byte array has enough bytes for + // the key size bits. + #define DISCUSS_PROVIDED_KEY(key_size, key) \ + if (key.length() * BITS_PER_BYTE < key_size) { \ + deadly_error(static_class_name(), func, \ + a_sprintf("key array length (%d) is less than required by key size " \ + "(%d bits).", key.length(), key_size)); \ + } +#else + #define DISCUSS_PROVIDED_KEY(key_size, key) +//// #define DISCUSS_KEY_SIZE(key_size) +#endif + +cryptical_envelopment::cryptical_envelopment(int key_size, const EVP_CIPHER *cipher_type) +: _key_size(key_size), + _key(new byte_array), + _cipher_type(cipher_type) +{ + FUNCDEF("ctor(int)"); + static_ssl_initializer(); +//// LOG("prior to key size discuss"); +//// DISCUSS_KEY_SIZE(key_size); +//// if (key_size < minimum_key_size()) +//// _key_size = minimum_key_size(); +//// if (key_size > maximum_key_size()) +//// _key_size = maximum_key_size(); + LOG("prior to generate key"); + generate_key(_key_size, *_key); + LOG("after generate key"); +} + +cryptical_envelopment::cryptical_envelopment(const byte_array &key, int key_size, const EVP_CIPHER *cipher_type) +: _key_size(key_size), + _key(new byte_array(key)), + _cipher_type(cipher_type) +{ + FUNCDEF("ctor(byte_array,int)"); + static_ssl_initializer(); + // any problems with the key provided are horrid. they will yield a + // non-working blowfish object. +//// LOG("prior to key size discuss"); +//// DISCUSS_KEY_SIZE(key_size); + LOG("prior to provided key discuss"); + DISCUSS_PROVIDED_KEY(key_size, key); + LOG("prior to ssl static init"); + LOG("after ssl static init"); +} + +cryptical_envelopment::cryptical_envelopment(const cryptical_envelopment &to_copy) +: root_object(), + _key_size(to_copy._key_size), + _key(new byte_array(*to_copy._key)) +{ + FUNCDEF("copy ctor"); + static_ssl_initializer(); + LOG("after ssl static init"); +} + +cryptical_envelopment::~cryptical_envelopment() +{ + FUNCDEF("destructor"); + LOG("prior to key whack"); + WHACK(_key); + LOG("after key whack"); +} + +int cryptical_envelopment::key_size() const { return _key_size; } + +const byte_array &cryptical_envelopment::get_key() const { return *_key; } + +/////hmmm: these are not right for all encryption types. +///int cryptical_envelopment::minimum_key_size() { return 64; } +/// +///int cryptical_envelopment::maximum_key_size() { return 448; } + +cryptical_envelopment &cryptical_envelopment::operator = (const cryptical_envelopment &to_copy) +{ + if (this == &to_copy) return *this; + _key_size = to_copy._key_size; + *_key = *to_copy._key; + _cipher_type = to_copy._cipher_type; + return *this; +} + +bool cryptical_envelopment::set_key(const byte_array &new_key, int key_size) +{ + FUNCDEF("set_key"); + if (!new_key.length()) return false; +//// DISCUSS_KEY_SIZE(key_size); + DISCUSS_PROVIDED_KEY(key_size, new_key); +//// if ( (key_size < minimum_key_size()) || (key_size > maximum_key_size()) ) +//// return false; + if (new_key.length() * BITS_PER_BYTE < key_size) return false; + _key_size = key_size; + *_key = new_key; + return true; +} + +void cryptical_envelopment::generate_key(int size, byte_array &new_key) +{ + FUNCDEF("generate_key"); + static_ssl_initializer(); +//// DISCUSS_KEY_SIZE(size); +//// if (size < minimum_key_size()) +//// size = minimum_key_size(); +//// else if (size > maximum_key_size()) +//// size = maximum_key_size(); + int bytes = size / BITS_PER_BYTE; // calculate the number of bytes needed. + if (size % BITS_PER_BYTE) bytes++; // add one for non-integral portion. + new_key.reset(bytes); + for (int i = 0; i < bytes; i++) + new_key[i] = static_ssl_initializer().randomizer().inclusive(0, 255); + +//hmmm: if we leave non-zero stuff in the last byte, that's not quite right! +// also a question of endian-ness of where to zap those bits. argh! + + // clear the bits that cannot be non-zero for a key whose bits are not evenly divisible by 8. + +} + +SAFE_STATIC(mutex, __vector_init_lock, ) + +//hmmm: this seems like a bad security situation, because we are using a single process for +// creating init vectors, so it's super easy to guess these (by reading the code, for +// example). is this still secure, given that the keys are not known to an attacker? +const byte_array &cryptical_envelopment::init_vector() +{ + FUNCDEF("init_vector"); + static_ssl_initializer(); + auto_synchronizer locking(__vector_init_lock()); + static byte_array to_return(EVP_MAX_IV_LENGTH); + static bool initted = false; + if (!initted) { + LOG(">> actually creating init_vector >>"); +//hmmm: we're okay with the wrap-around on the byte type (going negative) if the init vector length is longer than 214? + for (int i = 0; i < to_return.length(); i++) + to_return[i] = abyte(214 - i); + initted = true; + LOG("<< finished init_vector creation <<"); + } + return to_return; +} + +bool cryptical_envelopment::encrypt(const byte_array &source, + byte_array &target) const +{ + FUNCDEF("encrypt"); +ALWAYS_LOG(">>encrypt>>"); + target.reset(); + if (!_key->length() || !source.length()) return false; + bool to_return = true; + +LOG(a_sprintf(" encrypting %d bytes", source.length())); + + // initialize an encoding session. + EVP_CIPHER_CTX *session = EVP_CIPHER_CTX_new(); + EVP_CIPHER_CTX_init(session); + +//new rules! +//EVP_EncryptInit to set the cipher, but leave key and IV null and unset +//EVP_CIPHER_CTX_set_key_length and EVP_CTRL_AEAD_SET_IVLEN +//EVP_EncryptInit again. This time leave cipher null, because you've already set it, and set the key and IV. + + int initret = EVP_EncryptInit_ex(session, _cipher_type, NULL_POINTER, NULL_POINTER, NULL_POINTER); + if (!initret) { + // zero means a failure of the initialization. + deadly_error(class_name(), func, a_sprintf("failure in calling EVP_EncryptInit_ex, with error %s", GET_SSL_ERROR())); + } + LOG(a_sprintf(" calling set key len with key size of %d", _key_size)); + // new fancy footwork needed to keep openssl from blowing up and claiming we didn't set the key. +//hmmm: check returns on these setters? + EVP_CIPHER_CTX_set_key_length(session, _key_size); + EVP_CIPHER_CTX_ctrl(session, EVP_CTRL_AEAD_SET_IVLEN, init_vector().length(), NULL); + // and round and round we go... + initret = EVP_EncryptInit_ex(session, NULL_POINTER, NULL_POINTER, _key->observe(), init_vector().observe()); + if (!initret) { + // zero means a failure of the initialization. + deadly_error(class_name(), func, a_sprintf("second phase failure in calling EVP_EncryptInit_ex, with error %s", GET_SSL_ERROR())); + } + + // allocate temporary space for encrypted data. + byte_array encoded(source.length() + FUDGE); + + // encrypt the entire source buffer. + int encoded_len = 0; + int enc_ret = EVP_EncryptUpdate(session, encoded.access(), &encoded_len, + source.observe(), source.length()); + if (enc_ret != 1) { + deadly_error(class_name(), func, a_sprintf("encryption failed, " + "result=%d with error=%s.", enc_ret, GET_SSL_ERROR())); + to_return = false; + } else { + // chop any extra space off. + LOG(a_sprintf(" chopping extra bytes %d to %d.", encoded_len, encoded.last())); + encoded.zap(encoded_len, encoded.last()); + target = encoded; + } + + // only add padding if we succeeded with the encryption. + if (enc_ret == 1) { + // finalize the encryption. + encoded.reset(FUDGE); // reinflate for padding. + int pad_len = 0; + enc_ret = EVP_EncryptFinal_ex(session, encoded.access(), &pad_len); + if (enc_ret != 1) { + deadly_error(class_name(), func, a_sprintf("finalizing encryption " + "failed, result=%d with error=%s.", enc_ret, GET_SSL_ERROR())); + to_return = false; + } else { + LOG(a_sprintf(" encryption padding added %d bytes.", pad_len)); + encoded.zap(pad_len, encoded.last()); + target += encoded; + } + } + + EVP_CIPHER_CTX_cleanup(session); + EVP_CIPHER_CTX_free(session); +ALWAYS_LOG("<>decrypt>>"); + target.reset(); + if (!_key->length() || !source.length()) return false; + bool to_return = true; + EVP_CIPHER_CTX *session = EVP_CIPHER_CTX_new(); + EVP_CIPHER_CTX_init(session); + LOG(a_sprintf(" using key size with %d bits.", _key_size)); + int initret = EVP_DecryptInit_ex(session, _cipher_type, NULL_POINTER, NULL_POINTER, NULL_POINTER); + if (!initret) { + // zero means a failure of the initialization. + deadly_error(class_name(), func, a_sprintf("failure in calling EVP_DecryptInit_ex, with error %s", GET_SSL_ERROR())); + } + // more fancy fupwork. +//hmmm: check returns on these setters? + EVP_CIPHER_CTX_set_key_length(session, _key_size); + EVP_CIPHER_CTX_ctrl(session, EVP_CTRL_AEAD_SET_IVLEN, init_vector().length(), NULL); + initret = EVP_DecryptInit_ex(session, NULL_POINTER, NULL_POINTER, _key->observe(), init_vector().observe()); + if (!initret) { + // zero means a failure of the initialization. + deadly_error(class_name(), func, a_sprintf("second phase failure in calling EVP_DecryptInit_ex, with error %s", GET_SSL_ERROR())); + } + + // allocate enough space for decoded bytes. + byte_array decoded(source.length() + FUDGE); + + int decoded_len = 0; + int dec_ret = EVP_DecryptUpdate(session, decoded.access(), &decoded_len, + source.observe(), source.length()); + if (dec_ret != 1) { + deadly_error(class_name(), func, a_sprintf("decryption failed with error=%s", GET_SSL_ERROR())); + to_return = false; + } else { + LOG(a_sprintf(" first part decrypted size in bytes is %d.", decoded_len)); + decoded.zap(decoded_len, decoded.last()); + target = decoded; + } + + // only process padding if the first part of decryption succeeded. + if (dec_ret == 1) { + decoded.reset(FUDGE); // reinflate for padding. + int pad_len = 0; + dec_ret = EVP_DecryptFinal_ex(session, decoded.access(), &pad_len); + if (dec_ret != 1) { + deadly_error(class_name(), func, a_sprintf("finalizing decryption " + "failed, result=%d, padlen=%d, target had %d bytes, error=%s.", dec_ret, + pad_len, target.length(), GET_SSL_ERROR())); + to_return = false; + } else { + LOG(a_sprintf(" decryption final had %d bytes padding.", pad_len)); + decoded.zap(pad_len, decoded.last()); + target += decoded; + } + } + + EVP_CIPHER_CTX_cleanup(session); + EVP_CIPHER_CTX_free(session); +ALWAYS_LOG("< +#include + +// forward. +struct evp_cipher_st; +typedef struct evp_cipher_st EVP_CIPHER; + +namespace crypto { + +class cryptical_envelopment : public virtual basis::root_object +{ +public: + cryptical_envelopment(int key_size, const EVP_CIPHER *cipher_type); + //!< this will create a new random key of the "key_size", in bits. + /*!< the valid sizes for keys depend on the algorithm in question. */ + + cryptical_envelopment(const basis::byte_array &key, int key_size, const EVP_CIPHER *cipher_type); + //!< uses a pre-existing "key" for encryption. + + cryptical_envelopment(const cryptical_envelopment &to_copy); //!< copy constructor. + + virtual ~cryptical_envelopment(); + + cryptical_envelopment &operator = (const cryptical_envelopment &to_copy); + + DEFINE_CLASS_NAME("cryptical_envelopment"); + + int key_size() const; // returns the size of our key, in bits. + +/// static int minimum_key_size(); +/// //!< returns the minimum key size (in bits) supported here. +/// static int maximum_key_size(); +/// //!< returns the maximum key size (in bits) supported here. + + const basis::byte_array &get_key() const; //!< returns our current key. + + bool set_key(const basis::byte_array &new_key, int key_size); + //!< sets the encryption key to "new_key" with a "key_size" in bits. + + static void generate_key(int size, basis::byte_array &new_key); + //!< creates a "new_key" of the "size" (in bits) specified. + + bool encrypt(const basis::byte_array &source, basis::byte_array &target) const; + //!< encrypts the "source" array into the "target" array. + + bool decrypt(const basis::byte_array &source, basis::byte_array &target) const; + //!< decrypts the "target" array from the encrypted "source" array. + + // seldom-needed methods... + + static const basis::byte_array &init_vector(); + //!< returns the initialization vector that is used by this class. + /*!< decryption of chunks that were encrypted by this class will require + the same init vector as this function returns. this is mainly provided + for third-party applications that want to be able to decrypt interoperably + with this class. if you are creating such an application but for some + reason cannot run this class in order to invoke this method, the vector + is created by the algorithm in this class's implementation file + (currently named cryptical_envelopment.cpp). */ + +private: + int _key_size; //!< number of bits in the key. + basis::byte_array *_key; //!< our secret key. + const EVP_CIPHER *_cipher_type; //!< what kind of encryption are we using? +}; + +} //namespace. + +#endif + diff --git a/nucleus/library/crypto/makefile b/nucleus/library/crypto/makefile index 97c7376a..06b612c4 100644 --- a/nucleus/library/crypto/makefile +++ b/nucleus/library/crypto/makefile @@ -4,7 +4,7 @@ include cpp/variables.def TYPE = library PROJECT = crypto -SOURCE = blowfish_crypto.cpp rsa_crypto.cpp ssl_init.cpp +SOURCE = blowfish_crypto.cpp cryptical_envelopment.cpp old_school_rsa_crypto.cpp ssl_init.cpp USE_SSL = t TARGETS = crypto.lib diff --git a/nucleus/library/crypto/old_school_rsa_crypto.cpp b/nucleus/library/crypto/old_school_rsa_crypto.cpp new file mode 100644 index 00000000..43a7017f --- /dev/null +++ b/nucleus/library/crypto/old_school_rsa_crypto.cpp @@ -0,0 +1,412 @@ +/* +* Name : RSA public key encryption +* Author : Chris Koeritz +* Purpose: +* Supports public (and private) key encryption and decryption using the +* OpenSSL package's support for RSA encryption. +**** +* Copyright (c) 2005-$now By Author. This program is free software; you can * +* redistribute it and/or modify it under the terms of the GNU General Public * +* License as published by the Free Software Foundation; either version 2 of * +* the License or (at your option) any later version. This is online at: * +* http://www.fsf.org/copyleft/gpl.html * +* Please send any updates to: fred@gruntose.com * +*/ + +//note: rsa crypto provides a nice printing method... RSA_print_fp(stdout, private_key, 0); + +// notes from openssl docs: length to be encrypted in a chunk must be less than +// RSA_size(rsa) - 11 for the PKCS #1 v1.5 based padding modes, less than +// RSA_size(rsa) - 41 for RSA_PKCS1_OAEP_PADDING and exactly RSA_size(rsa) +// for RSA_NO_PADDING. + +#include "old_school_rsa_crypto.h" +#include "ssl_init.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace basis; +using namespace loggers; +using namespace mathematics; +using namespace structures; + +namespace crypto { + +//#define DEBUG_RSA_CRYPTO + // uncomment for noisier version. + +#ifdef DEBUG_RSA_CRYPTO + #undef LOG + #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s) +#else + #undef LOG + #define LOG(s) +#endif + +SAFE_STATIC(mutex, __single_stepper, ) + // protects unsafe areas of rsa crypto from access by multiple threads at once. + +old_school_rsa_crypto::old_school_rsa_crypto(int key_size) +: _key(NULL_POINTER) +{ + FUNCDEF("ctor(int)"); + LOG("prior to generating key"); + _key = generate_key(key_size); // generate_key initializes ssl for us. + LOG("after generating key"); +} + +old_school_rsa_crypto::old_school_rsa_crypto(const byte_array &key) +: _key(NULL_POINTER) +{ + FUNCDEF("ctor(byte_array)"); + static_ssl_initializer(); + byte_array key_copy = key; + LOG("prior to set key"); + set_key(key_copy); + LOG("after set key"); +} + +old_school_rsa_crypto::old_school_rsa_crypto(RSA *key) +: _key(NULL_POINTER) +{ + FUNCDEF("ctor(RSA)"); + static_ssl_initializer(); + LOG("prior to set key"); + set_key(key); + LOG("after set key"); +} + +old_school_rsa_crypto::old_school_rsa_crypto(const old_school_rsa_crypto &to_copy) +: root_object(), + _key(NULL_POINTER) +{ + FUNCDEF("copy ctor"); + static_ssl_initializer(); + LOG("prior to set key"); + set_key(to_copy._key); + LOG("after set key"); +} + +old_school_rsa_crypto::~old_school_rsa_crypto() +{ + FUNCDEF("destructor"); + LOG("prior to rsa free"); + auto_synchronizer mutt(__single_stepper()); + RSA_free(_key); + LOG("after rsa free"); +} + +const old_school_rsa_crypto &old_school_rsa_crypto::operator = (const old_school_rsa_crypto &to_copy) +{ + if (this == &to_copy) return *this; + set_key(to_copy._key); + return *this; +} + +RSA *old_school_rsa_crypto::generate_key(int key_size) +{ + FUNCDEF("generate_key"); + if (key_size < 4) key_size = 4; // laughable lower default. + static_ssl_initializer(); + LOG("into generate key"); + auto_synchronizer mutt(__single_stepper()); + RSA *to_return = RSA_new(); + BIGNUM *e = BN_new(); + BN_set_word(e, 65537); +//hmmm: only one value of e? + int ret = RSA_generate_key_ex(to_return, key_size, e, NULL_POINTER); + if (!ret) { + continuable_error(static_class_name(), func, + a_sprintf("failed to generate a key of %d bits: error is %ld.", key_size, ERR_get_error())); + BN_free(e); + RSA_free(to_return); + return NULL; + } + LOG("after key generated"); + BN_free(e); + return to_return; +} + +bool old_school_rsa_crypto::check_key(RSA *key) +{ + auto_synchronizer mutt(__single_stepper()); + return RSA_check_key(key) == 1; +} + +bool old_school_rsa_crypto::set_key(byte_array &key) +{ + FUNCDEF("set_key [byte_array]"); + if (!key.length()) return false; + auto_synchronizer mutt(__single_stepper()); + if (_key) RSA_free(_key); + _key = RSA_new(); + abyte type; + if (!structures::detach(key, type)) return false; + if ( (type != 'r') && (type != 'u') ) return false; + // get the public key bits first. + byte_array n; + if (!structures::detach(key, n)) return false; + BIGNUM *the_n = BN_bin2bn(n.access(), n.length(), NULL_POINTER); + if (!the_n) return false; + byte_array e; + if (!structures::detach(key, e)) return false; + BIGNUM *the_e = BN_bin2bn(e.access(), e.length(), NULL_POINTER); + if (!the_e) return false; + + if (type == 'u') { + // done with public key. +#ifdef NEWER_OPENSSL + RSA_set0_key(_key, the_n, the_e, NULL_POINTER); +#else + _key->n = the_n; _key->e = the_e; +#endif + return true; + } + + // the rest is for a private key. + byte_array d; + if (!structures::detach(key, d)) return false; + BIGNUM *the_d = BN_bin2bn(d.access(), d.length(), NULL_POINTER); + if (!the_d) return false; + + byte_array p; + if (!structures::detach(key, p)) return false; + BIGNUM *the_p = BN_bin2bn(p.access(), p.length(), NULL_POINTER); + if (!the_p) return false; + byte_array q; + if (!structures::detach(key, q)) return false; + BIGNUM *the_q = BN_bin2bn(q.access(), q.length(), NULL_POINTER); + if (!the_q) return false; + byte_array dmp1; + if (!structures::detach(key, dmp1)) return false; + BIGNUM *the_dmp1 = BN_bin2bn(dmp1.access(), dmp1.length(), NULL_POINTER); + if (!the_dmp1) return false; + byte_array dmq1; + if (!structures::detach(key, dmq1)) return false; + BIGNUM *the_dmq1 = BN_bin2bn(dmq1.access(), dmq1.length(), NULL_POINTER); + if (!the_dmq1) return false; + byte_array iqmp; + if (!structures::detach(key, iqmp)) return false; + BIGNUM *the_iqmp = BN_bin2bn(iqmp.access(), iqmp.length(), NULL_POINTER); + if (!the_iqmp) return false; + + // we can set the n, e and d now. +#ifdef NEWER_OPENSSL + int ret = RSA_set0_key(_key, the_n, the_e, the_d); + if (ret != 1) return false; + ret = RSA_set0_factors(_key, the_p, the_q); + if (ret != 1) return false; + ret = RSA_set0_crt_params(_key, the_dmp1, the_dmq1, the_iqmp); + if (ret != 1) return false; +#else + _key->n = the_n; _key->e = the_e; _key->d = the_d; + _key->p = the_p; _key->q = the_q; + _key->dmp1 = the_dmp1; _key->dmq1 = the_dmq1; _key->iqmp = the_iqmp; +#endif + + int check = RSA_check_key(_key); + if (check != 1) { + continuable_error(static_class_name(), func, "failed to check the private " + "portion of the key!"); + return false; + } + + return true; +} + +bool old_school_rsa_crypto::set_key(RSA *key) +{ + FUNCDEF("set_key [RSA]"); + if (!key) return NULL_POINTER; + // test the incoming key. + auto_synchronizer mutt(__single_stepper()); + int check = RSA_check_key(key); + if (check != 1) return false; + // clean out the old key. + if (_key) RSA_free(_key); + _key = RSAPrivateKey_dup(key); + if (!_key) { + continuable_error(static_class_name(), func, "failed to create a " + "duplicate of the key!"); + return false; + } + return true; +} + +bool old_school_rsa_crypto::public_key(byte_array &pubkey) const +{ + FUNCDEF("public_key"); + if (!_key) return false; + structures::attach(pubkey, abyte('u')); // signal a public key. + // convert the two public portions into binary. + BIGNUM **the_n = new BIGNUM *, **the_e = new BIGNUM *, **the_d = new BIGNUM *; +#ifdef NEWER_OPENSSL + RSA_get0_key(_key, (const BIGNUM **)the_n, (const BIGNUM **)the_e, (const BIGNUM **)the_d); +#else + *the_n = _key->n; *the_e = _key->e; *the_d = _key->d; +#endif + byte_array n(BN_num_bytes(*the_n)); + int ret = BN_bn2bin(*the_n, n.access()); + byte_array e(BN_num_bytes(*the_e)); + ret = BN_bn2bin(*the_e, e.access()); + // pack those two chunks. + structures::attach(pubkey, n); + structures::attach(pubkey, e); + WHACK(the_n); WHACK(the_e); WHACK(the_d); + + return true; +} + +bool old_school_rsa_crypto::private_key(byte_array &privkey) const +{ + FUNCDEF("private_key"); + if (!_key) return false; + int posn = privkey.length(); + bool worked = public_key(privkey); // get the public pieces first. + if (!worked) return false; + privkey[posn] = abyte('r'); // switch public key flag to private. + // convert the multiple private portions into binary. + //const BIGNUM **the_n = NULL_POINTER, **the_e = NULL_POINTER, **the_d = NULL_POINTER; + BIGNUM **the_n = new BIGNUM *, **the_e = new BIGNUM *, **the_d = new BIGNUM *; + BIGNUM **the_p = new BIGNUM *, **the_q = new BIGNUM *; + BIGNUM **the_dmp1 = new BIGNUM *, **the_dmq1 = new BIGNUM *, **the_iqmp = new BIGNUM *; +#ifdef NEWER_OPENSSL + RSA_get0_key(_key, (const BIGNUM **)the_n, (const BIGNUM **)the_e, (const BIGNUM **)the_d); + RSA_get0_factors(_key, (const BIGNUM **)the_p, (const BIGNUM **)the_q); + RSA_get0_crt_params(_key, (const BIGNUM **)the_dmp1, (const BIGNUM **)the_dmq1, (const BIGNUM **)the_iqmp); +#else + *the_n = _key->n; *the_e = _key->e; *the_d = _key->d; + *the_p = _key->p; *the_q = _key->q; + *the_dmp1 = _key->dmp1; *the_dmq1 = _key->dmq1; *the_iqmp = _key->iqmp; +#endif + byte_array d(BN_num_bytes(*the_d)); + int ret = BN_bn2bin(*the_d, d.access()); + byte_array p(BN_num_bytes(*the_p)); + ret = BN_bn2bin(*the_p, p.access()); + byte_array q(BN_num_bytes(*the_q)); + ret = BN_bn2bin(*the_q, q.access()); + byte_array dmp1(BN_num_bytes(*the_dmp1)); + ret = BN_bn2bin(*the_dmp1, dmp1.access()); + byte_array dmq1(BN_num_bytes(*the_dmq1)); + ret = BN_bn2bin(*the_dmq1, dmq1.access()); + byte_array iqmp(BN_num_bytes(*the_iqmp)); + ret = BN_bn2bin(*the_iqmp, iqmp.access()); + // pack all those in now. + structures::attach(privkey, d); + structures::attach(privkey, p); + structures::attach(privkey, q); + structures::attach(privkey, dmp1); + structures::attach(privkey, dmq1); + structures::attach(privkey, iqmp); + return true; +} + +bool old_school_rsa_crypto::public_encrypt(const byte_array &source, + byte_array &target) const +{ + FUNCDEF("public_encrypt"); + target.reset(); + if (!source.length()) return false; + + auto_synchronizer mutt(__single_stepper()); + const int max_chunk = RSA_size(_key) - 12; + + byte_array encoded(RSA_size(_key)); + for (int i = 0; i < source.length(); i += max_chunk) { + int edge = i + max_chunk - 1; + if (edge > source.last()) + edge = source.last(); + int next_chunk = edge - i + 1; + RSA_public_encrypt(next_chunk, &source[i], + encoded.access(), _key, RSA_PKCS1_PADDING); + target += encoded; + } + return true; +} + +bool old_school_rsa_crypto::private_decrypt(const byte_array &source, + byte_array &target) const +{ + FUNCDEF("private_decrypt"); + target.reset(); + if (!source.length()) return false; + + auto_synchronizer mutt(__single_stepper()); + const int max_chunk = RSA_size(_key); + + byte_array decoded(max_chunk); + for (int i = 0; i < source.length(); i += max_chunk) { + int edge = i + max_chunk - 1; + if (edge > source.last()) + edge = source.last(); + int next_chunk = edge - i + 1; + int dec_size = RSA_private_decrypt(next_chunk, &source[i], + decoded.access(), _key, RSA_PKCS1_PADDING); + if (dec_size < 0) return false; // that didn't work. + decoded.zap(dec_size, decoded.last()); + target += decoded; + decoded.reset(max_chunk); + } + return true; +} + +bool old_school_rsa_crypto::private_encrypt(const byte_array &source, + byte_array &target) const +{ + FUNCDEF("private_encrypt"); + target.reset(); + if (!source.length()) return false; + + auto_synchronizer mutt(__single_stepper()); + const int max_chunk = RSA_size(_key) - 12; + + byte_array encoded(RSA_size(_key)); + for (int i = 0; i < source.length(); i += max_chunk) { + int edge = i + max_chunk - 1; + if (edge > source.last()) + edge = source.last(); + int next_chunk = edge - i + 1; + RSA_private_encrypt(next_chunk, &source[i], + encoded.access(), _key, RSA_PKCS1_PADDING); + target += encoded; + } + return true; +} + +bool old_school_rsa_crypto::public_decrypt(const byte_array &source, + byte_array &target) const +{ + FUNCDEF("public_decrypt"); + target.reset(); + if (!source.length()) return false; + + auto_synchronizer mutt(__single_stepper()); + const int max_chunk = RSA_size(_key); + + byte_array decoded(max_chunk); + for (int i = 0; i < source.length(); i += max_chunk) { + int edge = i + max_chunk - 1; + if (edge > source.last()) + edge = source.last(); + int next_chunk = edge - i + 1; + int dec_size = RSA_public_decrypt(next_chunk, &source[i], + decoded.access(), _key, RSA_PKCS1_PADDING); + if (dec_size < 0) return false; // that didn't work. + decoded.zap(dec_size, decoded.last()); + target += decoded; + decoded.reset(max_chunk); + } + return true; +} + +} //namespace. + diff --git a/nucleus/library/crypto/old_school_rsa_crypto.h b/nucleus/library/crypto/old_school_rsa_crypto.h new file mode 100644 index 00000000..524fb39b --- /dev/null +++ b/nucleus/library/crypto/old_school_rsa_crypto.h @@ -0,0 +1,102 @@ +#ifndef OLD_SCHOOL_RSA_CRYPTO_CLASS +#define OLD_SCHOOL_RSA_CRYPTO_CLASS + +/*****************************************************************************\ +* * +* Name : RSA public key encryption * +* Author : Chris Koeritz * +* * +******************************************************************************* +* Copyright (c) 2005-$now By Author. This program is free software; you can * +* redistribute it and/or modify it under the terms of the GNU General Public * +* License as published by the Free Software Foundation; either version 2 of * +* the License or (at your option) any later version. This is online at: * +* http://www.fsf.org/copyleft/gpl.html * +* Please send any updates to: fred@gruntose.com * +\*****************************************************************************/ + +#include +#include + +// forward. +typedef struct rsa_st RSA; + +namespace crypto { + +//! Supports public key encryption and decryption. +/*! + This class uses the OpenSSL package's support for RSA encryption. +*/ + +class old_school_rsa_crypto : public virtual basis::nameable +{ +public: + old_school_rsa_crypto(int key_size); + //!< constructs using a randomized private key of the "key_size". + /*!< the "key_size" must be at least 1024 bits for acceptable security. + smaller keys are considered insecure. */ + + old_school_rsa_crypto(const basis::byte_array &key); + //!< constructs with the specified "key" as our private key. + /*!< the "key" is used for encryption rather than generating a random one. + the key is only valid if it was created with this class. also, if the key + is a public key, then only the public_encryption and public_decryption + methods will be available. */ + + old_school_rsa_crypto(RSA *key); + //!< starts with a pre-existing "key" in the low-level form. + + old_school_rsa_crypto(const old_school_rsa_crypto &to_copy); + + virtual ~old_school_rsa_crypto(); + + const old_school_rsa_crypto &operator = (const old_school_rsa_crypto &to_copy); + + DEFINE_CLASS_NAME("old_school_rsa_crypto"); + + bool set_key(basis::byte_array &key); + //!< resets this object's key to "key". + /*!< the key is only valid if this class created it. note: the "key" + is destructively consumed during the set method; do not pass in your + only copy. */ + + bool set_key(RSA *key); + //!< sets our new "key". + /*!< this must be a valid key created via the RSA algorithms. */ + + bool check_key(RSA *key); + //!< checks the RSA "key" provided for validity. + + bool public_encrypt(const basis::byte_array &source, basis::byte_array &target) const; + //!< encrypts "source" using our public key and stores it in "target". + /*!< public_encrypt and private_decrypt are a pair. an untrusted user can + encrypt with the public key and only the possessor of the private key + should be able to decrypt it. */ + 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 private_encrypt(const basis::byte_array &source, basis::byte_array &target) const; + //!< encrypts "source" using our private key and stores it in "target". + /*!< private_encrypt and public_decrypt are also a pair. the trusted + user with the private key can create encrypted chunks that anyone with + the public key can decrypt. */ + 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 public_key(basis::byte_array &pubkey) const; + //!< makes a copy of the public key held here. + bool private_key(basis::byte_array &privkey) const; + //!< makes a copy of the private key held here. + /*!< the private key should never be exposed to anyone else. */ + + static RSA *generate_key(int key_size); + //!< creates a random RSA key using the lower-level openssl methods. + +private: + RSA *_key; //!< our internal key. +}; + +} //namespace. + +#endif + diff --git a/nucleus/library/crypto/rsa_crypto.cpp b/nucleus/library/crypto/rsa_crypto.cpp deleted file mode 100644 index b96b3cdc..00000000 --- a/nucleus/library/crypto/rsa_crypto.cpp +++ /dev/null @@ -1,412 +0,0 @@ -/* -* Name : RSA public key encryption -* Author : Chris Koeritz -* Purpose: -* Supports public (and private) key encryption and decryption using the -* OpenSSL package's support for RSA encryption. -**** -* Copyright (c) 2005-$now By Author. This program is free software; you can * -* redistribute it and/or modify it under the terms of the GNU General Public * -* License as published by the Free Software Foundation; either version 2 of * -* the License or (at your option) any later version. This is online at: * -* http://www.fsf.org/copyleft/gpl.html * -* Please send any updates to: fred@gruntose.com * -*/ - -//note: rsa crypto provides a nice printing method... RSA_print_fp(stdout, private_key, 0); - -// notes from openssl docs: length to be encrypted in a chunk must be less than -// RSA_size(rsa) - 11 for the PKCS #1 v1.5 based padding modes, less than -// RSA_size(rsa) - 41 for RSA_PKCS1_OAEP_PADDING and exactly RSA_size(rsa) -// for RSA_NO_PADDING. - -#include "rsa_crypto.h" -#include "ssl_init.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -using namespace basis; -using namespace loggers; -using namespace mathematics; -using namespace structures; - -namespace crypto { - -//#define DEBUG_RSA_CRYPTO - // uncomment for noisier version. - -#ifdef DEBUG_RSA_CRYPTO - #undef LOG - #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s) -#else - #undef LOG - #define LOG(s) -#endif - -SAFE_STATIC(mutex, __single_stepper, ) - // protects unsafe areas of rsa crypto from access by multiple threads at once. - -rsa_crypto::rsa_crypto(int key_size) -: _key(NULL_POINTER) -{ - FUNCDEF("ctor(int)"); - LOG("prior to generating key"); - _key = generate_key(key_size); // generate_key initializes ssl for us. - LOG("after generating key"); -} - -rsa_crypto::rsa_crypto(const byte_array &key) -: _key(NULL_POINTER) -{ - FUNCDEF("ctor(byte_array)"); - static_ssl_initializer(); - byte_array key_copy = key; - LOG("prior to set key"); - set_key(key_copy); - LOG("after set key"); -} - -rsa_crypto::rsa_crypto(RSA *key) -: _key(NULL_POINTER) -{ - FUNCDEF("ctor(RSA)"); - static_ssl_initializer(); - LOG("prior to set key"); - set_key(key); - LOG("after set key"); -} - -rsa_crypto::rsa_crypto(const rsa_crypto &to_copy) -: root_object(), - _key(NULL_POINTER) -{ - FUNCDEF("copy ctor"); - static_ssl_initializer(); - LOG("prior to set key"); - set_key(to_copy._key); - LOG("after set key"); -} - -rsa_crypto::~rsa_crypto() -{ - FUNCDEF("destructor"); - LOG("prior to rsa free"); - auto_synchronizer mutt(__single_stepper()); - RSA_free(_key); - LOG("after rsa free"); -} - -const rsa_crypto &rsa_crypto::operator = (const rsa_crypto &to_copy) -{ - if (this == &to_copy) return *this; - set_key(to_copy._key); - return *this; -} - -RSA *rsa_crypto::generate_key(int key_size) -{ - FUNCDEF("generate_key"); - if (key_size < 4) key_size = 4; // laughable lower default. - static_ssl_initializer(); - LOG("into generate key"); - auto_synchronizer mutt(__single_stepper()); - RSA *to_return = RSA_new(); - BIGNUM *e = BN_new(); - BN_set_word(e, 65537); -//hmmm: only one value of e? - int ret = RSA_generate_key_ex(to_return, key_size, e, NULL_POINTER); - if (!ret) { - continuable_error(static_class_name(), func, - a_sprintf("failed to generate a key of %d bits: error is %ld.", key_size, ERR_get_error())); - BN_free(e); - RSA_free(to_return); - return NULL; - } - LOG("after key generated"); - BN_free(e); - return to_return; -} - -bool rsa_crypto::check_key(RSA *key) -{ - auto_synchronizer mutt(__single_stepper()); - return RSA_check_key(key) == 1; -} - -bool rsa_crypto::set_key(byte_array &key) -{ - FUNCDEF("set_key [byte_array]"); - if (!key.length()) return false; - auto_synchronizer mutt(__single_stepper()); - if (_key) RSA_free(_key); - _key = RSA_new(); - abyte type; - if (!structures::detach(key, type)) return false; - if ( (type != 'r') && (type != 'u') ) return false; - // get the public key bits first. - byte_array n; - if (!structures::detach(key, n)) return false; - BIGNUM *the_n = BN_bin2bn(n.access(), n.length(), NULL_POINTER); - if (!the_n) return false; - byte_array e; - if (!structures::detach(key, e)) return false; - BIGNUM *the_e = BN_bin2bn(e.access(), e.length(), NULL_POINTER); - if (!the_e) return false; - - if (type == 'u') { - // done with public key. -#ifdef NEWER_OPENSSL - RSA_set0_key(_key, the_n, the_e, NULL_POINTER); -#else - _key->n = the_n; _key->e = the_e; -#endif - return true; - } - - // the rest is for a private key. - byte_array d; - if (!structures::detach(key, d)) return false; - BIGNUM *the_d = BN_bin2bn(d.access(), d.length(), NULL_POINTER); - if (!the_d) return false; - - byte_array p; - if (!structures::detach(key, p)) return false; - BIGNUM *the_p = BN_bin2bn(p.access(), p.length(), NULL_POINTER); - if (!the_p) return false; - byte_array q; - if (!structures::detach(key, q)) return false; - BIGNUM *the_q = BN_bin2bn(q.access(), q.length(), NULL_POINTER); - if (!the_q) return false; - byte_array dmp1; - if (!structures::detach(key, dmp1)) return false; - BIGNUM *the_dmp1 = BN_bin2bn(dmp1.access(), dmp1.length(), NULL_POINTER); - if (!the_dmp1) return false; - byte_array dmq1; - if (!structures::detach(key, dmq1)) return false; - BIGNUM *the_dmq1 = BN_bin2bn(dmq1.access(), dmq1.length(), NULL_POINTER); - if (!the_dmq1) return false; - byte_array iqmp; - if (!structures::detach(key, iqmp)) return false; - BIGNUM *the_iqmp = BN_bin2bn(iqmp.access(), iqmp.length(), NULL_POINTER); - if (!the_iqmp) return false; - - // we can set the n, e and d now. -#ifdef NEWER_OPENSSL - int ret = RSA_set0_key(_key, the_n, the_e, the_d); - if (ret != 1) return false; - ret = RSA_set0_factors(_key, the_p, the_q); - if (ret != 1) return false; - ret = RSA_set0_crt_params(_key, the_dmp1, the_dmq1, the_iqmp); - if (ret != 1) return false; -#else - _key->n = the_n; _key->e = the_e; _key->d = the_d; - _key->p = the_p; _key->q = the_q; - _key->dmp1 = the_dmp1; _key->dmq1 = the_dmq1; _key->iqmp = the_iqmp; -#endif - - int check = RSA_check_key(_key); - if (check != 1) { - continuable_error(static_class_name(), func, "failed to check the private " - "portion of the key!"); - return false; - } - - return true; -} - -bool rsa_crypto::set_key(RSA *key) -{ - FUNCDEF("set_key [RSA]"); - if (!key) return NULL_POINTER; - // test the incoming key. - auto_synchronizer mutt(__single_stepper()); - int check = RSA_check_key(key); - if (check != 1) return false; - // clean out the old key. - if (_key) RSA_free(_key); - _key = RSAPrivateKey_dup(key); - if (!_key) { - continuable_error(static_class_name(), func, "failed to create a " - "duplicate of the key!"); - return false; - } - return true; -} - -bool rsa_crypto::public_key(byte_array &pubkey) const -{ - FUNCDEF("public_key"); - if (!_key) return false; - structures::attach(pubkey, abyte('u')); // signal a public key. - // convert the two public portions into binary. - BIGNUM **the_n = new BIGNUM *, **the_e = new BIGNUM *, **the_d = new BIGNUM *; -#ifdef NEWER_OPENSSL - RSA_get0_key(_key, (const BIGNUM **)the_n, (const BIGNUM **)the_e, (const BIGNUM **)the_d); -#else - *the_n = _key->n; *the_e = _key->e; *the_d = _key->d; -#endif - byte_array n(BN_num_bytes(*the_n)); - int ret = BN_bn2bin(*the_n, n.access()); - byte_array e(BN_num_bytes(*the_e)); - ret = BN_bn2bin(*the_e, e.access()); - // pack those two chunks. - structures::attach(pubkey, n); - structures::attach(pubkey, e); - WHACK(the_n); WHACK(the_e); WHACK(the_d); - - return true; -} - -bool rsa_crypto::private_key(byte_array &privkey) const -{ - FUNCDEF("private_key"); - if (!_key) return false; - int posn = privkey.length(); - bool worked = public_key(privkey); // get the public pieces first. - if (!worked) return false; - privkey[posn] = abyte('r'); // switch public key flag to private. - // convert the multiple private portions into binary. - //const BIGNUM **the_n = NULL_POINTER, **the_e = NULL_POINTER, **the_d = NULL_POINTER; - BIGNUM **the_n = new BIGNUM *, **the_e = new BIGNUM *, **the_d = new BIGNUM *; - BIGNUM **the_p = new BIGNUM *, **the_q = new BIGNUM *; - BIGNUM **the_dmp1 = new BIGNUM *, **the_dmq1 = new BIGNUM *, **the_iqmp = new BIGNUM *; -#ifdef NEWER_OPENSSL - RSA_get0_key(_key, (const BIGNUM **)the_n, (const BIGNUM **)the_e, (const BIGNUM **)the_d); - RSA_get0_factors(_key, (const BIGNUM **)the_p, (const BIGNUM **)the_q); - RSA_get0_crt_params(_key, (const BIGNUM **)the_dmp1, (const BIGNUM **)the_dmq1, (const BIGNUM **)the_iqmp); -#else - *the_n = _key->n; *the_e = _key->e; *the_d = _key->d; - *the_p = _key->p; *the_q = _key->q; - *the_dmp1 = _key->dmp1; *the_dmq1 = _key->dmq1; *the_iqmp = _key->iqmp; -#endif - byte_array d(BN_num_bytes(*the_d)); - int ret = BN_bn2bin(*the_d, d.access()); - byte_array p(BN_num_bytes(*the_p)); - ret = BN_bn2bin(*the_p, p.access()); - byte_array q(BN_num_bytes(*the_q)); - ret = BN_bn2bin(*the_q, q.access()); - byte_array dmp1(BN_num_bytes(*the_dmp1)); - ret = BN_bn2bin(*the_dmp1, dmp1.access()); - byte_array dmq1(BN_num_bytes(*the_dmq1)); - ret = BN_bn2bin(*the_dmq1, dmq1.access()); - byte_array iqmp(BN_num_bytes(*the_iqmp)); - ret = BN_bn2bin(*the_iqmp, iqmp.access()); - // pack all those in now. - structures::attach(privkey, d); - structures::attach(privkey, p); - structures::attach(privkey, q); - structures::attach(privkey, dmp1); - structures::attach(privkey, dmq1); - structures::attach(privkey, iqmp); - return true; -} - -bool rsa_crypto::public_encrypt(const byte_array &source, - byte_array &target) const -{ - FUNCDEF("public_encrypt"); - target.reset(); - if (!source.length()) return false; - - auto_synchronizer mutt(__single_stepper()); - const int max_chunk = RSA_size(_key) - 12; - - byte_array encoded(RSA_size(_key)); - for (int i = 0; i < source.length(); i += max_chunk) { - int edge = i + max_chunk - 1; - if (edge > source.last()) - edge = source.last(); - int next_chunk = edge - i + 1; - RSA_public_encrypt(next_chunk, &source[i], - encoded.access(), _key, RSA_PKCS1_PADDING); - target += encoded; - } - return true; -} - -bool rsa_crypto::private_decrypt(const byte_array &source, - byte_array &target) const -{ - FUNCDEF("private_decrypt"); - target.reset(); - if (!source.length()) return false; - - auto_synchronizer mutt(__single_stepper()); - const int max_chunk = RSA_size(_key); - - byte_array decoded(max_chunk); - for (int i = 0; i < source.length(); i += max_chunk) { - int edge = i + max_chunk - 1; - if (edge > source.last()) - edge = source.last(); - int next_chunk = edge - i + 1; - int dec_size = RSA_private_decrypt(next_chunk, &source[i], - decoded.access(), _key, RSA_PKCS1_PADDING); - if (dec_size < 0) return false; // that didn't work. - decoded.zap(dec_size, decoded.last()); - target += decoded; - decoded.reset(max_chunk); - } - return true; -} - -bool rsa_crypto::private_encrypt(const byte_array &source, - byte_array &target) const -{ - FUNCDEF("private_encrypt"); - target.reset(); - if (!source.length()) return false; - - auto_synchronizer mutt(__single_stepper()); - const int max_chunk = RSA_size(_key) - 12; - - byte_array encoded(RSA_size(_key)); - for (int i = 0; i < source.length(); i += max_chunk) { - int edge = i + max_chunk - 1; - if (edge > source.last()) - edge = source.last(); - int next_chunk = edge - i + 1; - RSA_private_encrypt(next_chunk, &source[i], - encoded.access(), _key, RSA_PKCS1_PADDING); - target += encoded; - } - return true; -} - -bool rsa_crypto::public_decrypt(const byte_array &source, - byte_array &target) const -{ - FUNCDEF("public_decrypt"); - target.reset(); - if (!source.length()) return false; - - auto_synchronizer mutt(__single_stepper()); - const int max_chunk = RSA_size(_key); - - byte_array decoded(max_chunk); - for (int i = 0; i < source.length(); i += max_chunk) { - int edge = i + max_chunk - 1; - if (edge > source.last()) - edge = source.last(); - int next_chunk = edge - i + 1; - int dec_size = RSA_public_decrypt(next_chunk, &source[i], - decoded.access(), _key, RSA_PKCS1_PADDING); - if (dec_size < 0) return false; // that didn't work. - decoded.zap(dec_size, decoded.last()); - target += decoded; - decoded.reset(max_chunk); - } - return true; -} - -} //namespace. - diff --git a/nucleus/library/crypto/rsa_crypto.h b/nucleus/library/crypto/rsa_crypto.h deleted file mode 100644 index b2419309..00000000 --- a/nucleus/library/crypto/rsa_crypto.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef RSA_CRYPTO_CLASS -#define RSA_CRYPTO_CLASS - -/*****************************************************************************\ -* * -* Name : RSA public key encryption * -* Author : Chris Koeritz * -* * -******************************************************************************* -* Copyright (c) 2005-$now By Author. This program is free software; you can * -* redistribute it and/or modify it under the terms of the GNU General Public * -* License as published by the Free Software Foundation; either version 2 of * -* the License or (at your option) any later version. This is online at: * -* http://www.fsf.org/copyleft/gpl.html * -* Please send any updates to: fred@gruntose.com * -\*****************************************************************************/ - -#include -#include - -// forward. -//struct RSA; -typedef struct rsa_st RSA; - -namespace crypto { - -//! Supports public key encryption and decryption. -/*! - This class uses the OpenSSL package's support for RSA encryption. -*/ - -class rsa_crypto : public virtual basis::nameable -{ -public: - rsa_crypto(int key_size); - //!< constructs using a randomized private key of the "key_size". - /*!< the "key_size" must be at least 1024 bits for acceptable security. - smaller keys are considered insecure. */ - - rsa_crypto(const basis::byte_array &key); - //!< constructs with the specified "key" as our private key. - /*!< the "key" is used for encryption rather than generating a random one. - the key is only valid if it was created with this class. also, if the key - is a public key, then only the public_encryption and public_decryption - methods will be available. */ - - rsa_crypto(RSA *key); - //!< starts with a pre-existing "key" in the low-level form. - - rsa_crypto(const rsa_crypto &to_copy); - - virtual ~rsa_crypto(); - - const rsa_crypto &operator = (const rsa_crypto &to_copy); - - DEFINE_CLASS_NAME("rsa_crypto"); - - bool set_key(basis::byte_array &key); - //!< resets this object's key to "key". - /*!< the key is only valid if this class created it. note: the "key" - is destructively consumed during the set method; do not pass in your - only copy. */ - - bool set_key(RSA *key); - //!< sets our new "key". - /*!< this must be a valid key created via the RSA algorithms. */ - - bool check_key(RSA *key); - //!< checks the RSA "key" provided for validity. - - bool public_encrypt(const basis::byte_array &source, basis::byte_array &target) const; - //!< encrypts "source" using our public key and stores it in "target". - /*!< public_encrypt and private_decrypt are a pair. an untrusted user can - encrypt with the public key and only the possessor of the private key - should be able to decrypt it. */ - 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 private_encrypt(const basis::byte_array &source, basis::byte_array &target) const; - //!< encrypts "source" using our private key and stores it in "target". - /*!< private_encrypt and public_decrypt are also a pair. the trusted - user with the private key can create encrypted chunks that anyone with - the public key can decrypt. */ - 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 public_key(basis::byte_array &pubkey) const; - //!< makes a copy of the public key held here. - bool private_key(basis::byte_array &privkey) const; - //!< makes a copy of the private key held here. - /*!< the private key should never be exposed to anyone else. */ - - static RSA *generate_key(int key_size); - //!< creates a random RSA key using the lower-level openssl methods. - -private: - RSA *_key; //!< our internal key. -}; - -} //namespace. - -#endif - diff --git a/nucleus/library/tests_crypto/makefile b/nucleus/library/tests_crypto/makefile index d7d3f49e..e0854cbb 100644 --- a/nucleus/library/tests_crypto/makefile +++ b/nucleus/library/tests_crypto/makefile @@ -2,7 +2,7 @@ include cpp/variables.def PROJECT = tests_crypto TYPE = test -TARGETS = test_blowfish_crypto.exe test_rsa_crypto.exe +TARGETS = test_blowfish_crypto.exe test_old_school_rsa_crypto.exe LOCAL_LIBS_USED = unit_test crypto application processes loggers configuration textual timely \ filesystem structures basis USE_SSL = t diff --git a/nucleus/library/tests_crypto/test_blowfish_crypto.cpp b/nucleus/library/tests_crypto/test_blowfish_crypto.cpp index abf9f7d8..23f622c0 100644 --- a/nucleus/library/tests_crypto/test_blowfish_crypto.cpp +++ b/nucleus/library/tests_crypto/test_blowfish_crypto.cpp @@ -57,6 +57,10 @@ const int ITERATIONS = 80; // number of test runs in our testing threads. const int MAX_STRING = 20000; // largest chunk that we'll try to encrypt. +// some constants snagged from older version of blowfish_crypto class... +const int blowfish_crypto_minimum_key_size_in_bits = 64; +const int blowfish_crypto_maximum_key_size_in_bits = 448; + ////////////// class test_blowfish; // forward. @@ -137,9 +141,8 @@ void blowfish_thread::perform_activity(void *) int left = ITERATIONS; while (left--) { time_stamp key_start; - blowfish_crypto bc(_parent.randomizer().inclusive - (blowfish_crypto::minimum_key_size(), - blowfish_crypto::maximum_key_size())); + blowfish_crypto bc(_parent.randomizer().inclusive(blowfish_crypto_minimum_key_size_in_bits, + blowfish_crypto_maximum_key_size_in_bits)); #ifdef DEBUG_BLOWFISH LOG(a_sprintf("%d bit key has:", bc.key_size())); astring dumped_key = byte_formatter::text_dump(bc.get_key()); diff --git a/nucleus/library/tests_crypto/test_old_school_rsa_crypto.cpp b/nucleus/library/tests_crypto/test_old_school_rsa_crypto.cpp new file mode 100644 index 00000000..c0dacda1 --- /dev/null +++ b/nucleus/library/tests_crypto/test_old_school_rsa_crypto.cpp @@ -0,0 +1,208 @@ +/* +* Name : test RSA public key encryption +* Author : Chris Koeritz +* Purpose: +* Exercises the RSA encryption functions from the crypto library. +** +* Copyright (c) 2005-$now By Author. This program is free software; you can * +* redistribute it and/or modify it under the terms of the GNU General Public * +* License as published by the Free Software Foundation; either version 2 of * +* the License or (at your option) any later version. This is online at: * +* http://www.fsf.org/copyleft/gpl.html * +* Please send any updates to: fred@gruntose.com * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace application; +using namespace basis; +using namespace crypto; +using namespace filesystem; +using namespace loggers; +using namespace mathematics; +using namespace processes; +using namespace structures; +using namespace textual; +using namespace timely; +using namespace unit_test; + +//#define DEBUG_RSA_CRYPTO + // uncomment for noisy run. + +#define LOG(to_print) EMERGENCY_LOG(program_wide_logger::get(), to_print) + +const int KEY_SIZE = 1024; + // the size of the RSA key that we'll create. + +const int MAX_STRING = 4000; + // the largest chunk that we'll try to encrypt. + +const int THREAD_COUNT = 5; // number of threads testing rsa at once. + +const int ITERATIONS = 6; // number of test runs in our testing threads. + +////////////// + +class test_rsa; // forward. + +class rsa_thread : public ethread +{ +public: + rsa_thread(test_rsa &parent) : ethread(), _parent(parent) {} + + void perform_activity(void *ptr); + // try out random rsa keys on randomly chosen chunks of the fodder. + +private: + test_rsa &_parent; +}; + +////////////// + +class test_rsa : public virtual unit_base, virtual public application_shell +{ +public: + test_rsa() + : _fodder(string_manipulation::make_random_name(MAX_STRING + 1, MAX_STRING + 1)) {} + virtual ~test_rsa() {} + DEFINE_CLASS_NAME("test_rsa"); + + const astring &fodder() const { return _fodder; } + + int execute(); + +private: + astring _fodder; // chunks taken from this are encrypted and decrypted. + time_stamp _program_start; // the time at which we started executing. + thread_cabinet _threads; // manages our testing threads. + friend class rsa_thread; // bad practice, but saves time in test app. +}; + +int test_rsa::execute() +{ + FUNCDEF("execute"); + int left = THREAD_COUNT; + while (left--) { + _threads.add_thread(new rsa_thread(*this), true, NULL_POINTER); + } + + while (_threads.threads()) { +#ifdef DEBUG_RSA_CRYPTO + LOG(astring("cleaning debris.")); +#endif + _threads.clean_debris(); +#ifdef DEBUG_RSA_CRYPTO + LOG(astring("after cleaning debris.")); +#endif + time_control::sleep_ms(1000); + } + +#ifdef DEBUG_RSA_CRYPTO + int duration = int(time_stamp().value() - _program_start.value()); + LOG(a_sprintf("duration for %d keys and encrypt/decrypt=%d ms,", + ITERATIONS * THREAD_COUNT, duration)); + LOG(a_sprintf("that comes to %d ms per cycle.", int(double(duration + / ITERATIONS / THREAD_COUNT)))); +#endif + + return final_report(); +} + +////////////// + +#undef UNIT_BASE_THIS_OBJECT +#define UNIT_BASE_THIS_OBJECT (*dynamic_cast(application_shell::single_instance())) + +void rsa_thread::perform_activity(void *) +{ + FUNCDEF("perform_activity"); + int left = ITERATIONS; + while (left--) { + time_stamp start; + + old_school_rsa_crypto rc_private_here(KEY_SIZE); + int key_durat = int(time_stamp().value() - start.value()); + + byte_array public_key; + rc_private_here.public_key(public_key); // get our public portion. + byte_array private_key; + rc_private_here.private_key(private_key); // get our private portion. + +//RSA_print_fp(stdout, private_key, 0); +//RSA_print_fp(stdout, public_key, 0); + + int string_start = _parent.randomizer().inclusive(0, MAX_STRING); + int string_end = _parent.randomizer().inclusive(0, MAX_STRING); + flip_increasing(string_start, string_end); + astring ranstring = _parent.fodder().substring(string_start, string_end); + byte_array target; + + // the first phase tests the outsiders sending back data that only we, + // with our private key, can decrypt. + + start.reset(); + old_school_rsa_crypto rc_pub(public_key); + bool worked = rc_pub.public_encrypt(byte_array(ranstring.length() + 1, + (abyte*)ranstring.s()), target); + int pub_enc_durat = int(time_stamp().value() - start.value()); + ASSERT_TRUE(worked, "phase 1 shouldn't fail to encrypt the string"); + + old_school_rsa_crypto rc_priv(private_key); + byte_array recovered; + start.reset(); + worked = rc_priv.private_decrypt(target, recovered); + int priv_dec_durat = int(time_stamp().value() - start.value()); + ASSERT_TRUE(worked, "phase 1 should not fail to decrypt the string"); + + astring teddro = (char *)recovered.observe(); + + ASSERT_EQUAL(teddro, ranstring, "should not fail to get back the data"); + + // the second phase tests us using our private key to encrypt data which + // anyone with the public key can decode. + + start.reset(); + worked = rc_priv.private_encrypt(byte_array(ranstring.length() + 1, + (abyte*)ranstring.s()), target); + int priv_enc_durat = int(time_stamp().value() - start.value()); + ASSERT_TRUE(worked, "phase 2 should not fail to encrypt the string"); + + start.reset(); + worked = rc_pub.public_decrypt(target, recovered); + int pub_dec_durat = int(time_stamp().value() - start.value()); + ASSERT_TRUE(worked, "phase 2 should not fail to decrypt the string"); + + teddro = (char *)recovered.observe(); + + ASSERT_EQUAL(teddro, ranstring, "should not fail to get back the data here either"); + +#ifdef DEBUG_RSA_CRYPTO + LOG(a_sprintf("key generation: %d ms, public encrypt: %d ms, private " + "decrypt: %d ms", key_durat, pub_enc_durat, priv_dec_durat)); + LOG(a_sprintf("data size: %d bytes, private encrypt: %d ms, public " + "decrypt: %d ms", + string_end - string_start + 1, priv_enc_durat, pub_dec_durat)); +#endif + + time_control::sleep_ms(0); // take a rest. + } +} + +HOOPLE_MAIN(test_rsa, ) + diff --git a/nucleus/library/tests_crypto/test_rsa_crypto.cpp b/nucleus/library/tests_crypto/test_rsa_crypto.cpp deleted file mode 100644 index adc85d5a..00000000 --- a/nucleus/library/tests_crypto/test_rsa_crypto.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* -* Name : test RSA public key encryption -* Author : Chris Koeritz -* Purpose: -* Exercises the RSA encryption functions from the crypto library. -** -* Copyright (c) 2005-$now By Author. This program is free software; you can * -* redistribute it and/or modify it under the terms of the GNU General Public * -* License as published by the Free Software Foundation; either version 2 of * -* the License or (at your option) any later version. This is online at: * -* http://www.fsf.org/copyleft/gpl.html * -* Please send any updates to: fred@gruntose.com * -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -using namespace application; -using namespace basis; -using namespace crypto; -using namespace filesystem; -using namespace loggers; -using namespace mathematics; -using namespace processes; -using namespace structures; -using namespace textual; -using namespace timely; -using namespace unit_test; - -//#define DEBUG_RSA_CRYPTO - // uncomment for noisy run. - -#define LOG(to_print) EMERGENCY_LOG(program_wide_logger::get(), to_print) - -const int KEY_SIZE = 1024; - // the size of the RSA key that we'll create. - -const int MAX_STRING = 4000; - // the largest chunk that we'll try to encrypt. - -const int THREAD_COUNT = 5; // number of threads testing rsa at once. - -const int ITERATIONS = 6; // number of test runs in our testing threads. - -////////////// - -class test_rsa; // forward. - -class rsa_thread : public ethread -{ -public: - rsa_thread(test_rsa &parent) : ethread(), _parent(parent) {} - - void perform_activity(void *ptr); - // try out random rsa keys on randomly chosen chunks of the fodder. - -private: - test_rsa &_parent; -}; - -////////////// - -class test_rsa : public virtual unit_base, virtual public application_shell -{ -public: - test_rsa() - : _fodder(string_manipulation::make_random_name(MAX_STRING + 1, MAX_STRING + 1)) {} - virtual ~test_rsa() {} - DEFINE_CLASS_NAME("test_rsa"); - - const astring &fodder() const { return _fodder; } - - int execute(); - -private: - astring _fodder; // chunks taken from this are encrypted and decrypted. - time_stamp _program_start; // the time at which we started executing. - thread_cabinet _threads; // manages our testing threads. - friend class rsa_thread; // bad practice, but saves time in test app. -}; - -int test_rsa::execute() -{ - FUNCDEF("execute"); - int left = THREAD_COUNT; - while (left--) { - _threads.add_thread(new rsa_thread(*this), true, NULL_POINTER); - } - - while (_threads.threads()) { -#ifdef DEBUG_RSA_CRYPTO - LOG(astring("cleaning debris.")); -#endif - _threads.clean_debris(); -#ifdef DEBUG_RSA_CRYPTO - LOG(astring("after cleaning debris.")); -#endif - time_control::sleep_ms(1000); - } - -#ifdef DEBUG_RSA_CRYPTO - int duration = int(time_stamp().value() - _program_start.value()); - LOG(a_sprintf("duration for %d keys and encrypt/decrypt=%d ms,", - ITERATIONS * THREAD_COUNT, duration)); - LOG(a_sprintf("that comes to %d ms per cycle.", int(double(duration - / ITERATIONS / THREAD_COUNT)))); -#endif - - return final_report(); -} - -////////////// - -#undef UNIT_BASE_THIS_OBJECT -#define UNIT_BASE_THIS_OBJECT (*dynamic_cast(application_shell::single_instance())) - -void rsa_thread::perform_activity(void *) -{ - FUNCDEF("perform_activity"); - int left = ITERATIONS; - while (left--) { - time_stamp start; - - rsa_crypto rc_private_here(KEY_SIZE); - int key_durat = int(time_stamp().value() - start.value()); - - byte_array public_key; - rc_private_here.public_key(public_key); // get our public portion. - byte_array private_key; - rc_private_here.private_key(private_key); // get our private portion. - -//RSA_print_fp(stdout, private_key, 0); -//RSA_print_fp(stdout, public_key, 0); - - int string_start = _parent.randomizer().inclusive(0, MAX_STRING); - int string_end = _parent.randomizer().inclusive(0, MAX_STRING); - flip_increasing(string_start, string_end); - astring ranstring = _parent.fodder().substring(string_start, string_end); - byte_array target; - - // the first phase tests the outsiders sending back data that only we, - // with our private key, can decrypt. - - start.reset(); - rsa_crypto rc_pub(public_key); - bool worked = rc_pub.public_encrypt(byte_array(ranstring.length() + 1, - (abyte*)ranstring.s()), target); - int pub_enc_durat = int(time_stamp().value() - start.value()); - ASSERT_TRUE(worked, "phase 1 shouldn't fail to encrypt the string"); - - rsa_crypto rc_priv(private_key); - byte_array recovered; - start.reset(); - worked = rc_priv.private_decrypt(target, recovered); - int priv_dec_durat = int(time_stamp().value() - start.value()); - ASSERT_TRUE(worked, "phase 1 should not fail to decrypt the string"); - - astring teddro = (char *)recovered.observe(); - - ASSERT_EQUAL(teddro, ranstring, "should not fail to get back the data"); - - // the second phase tests us using our private key to encrypt data which - // anyone with the public key can decode. - - start.reset(); - worked = rc_priv.private_encrypt(byte_array(ranstring.length() + 1, - (abyte*)ranstring.s()), target); - int priv_enc_durat = int(time_stamp().value() - start.value()); - ASSERT_TRUE(worked, "phase 2 should not fail to encrypt the string"); - - start.reset(); - worked = rc_pub.public_decrypt(target, recovered); - int pub_dec_durat = int(time_stamp().value() - start.value()); - ASSERT_TRUE(worked, "phase 2 should not fail to decrypt the string"); - - teddro = (char *)recovered.observe(); - - ASSERT_EQUAL(teddro, ranstring, "should not fail to get back the data here either"); - -#ifdef DEBUG_RSA_CRYPTO - LOG(a_sprintf("key generation: %d ms, public encrypt: %d ms, private " - "decrypt: %d ms", key_durat, pub_enc_durat, priv_dec_durat)); - LOG(a_sprintf("data size: %d bytes, private encrypt: %d ms, public " - "decrypt: %d ms", - string_end - string_start + 1, priv_enc_durat, pub_dec_durat)); -#endif - - time_control::sleep_ms(0); // take a rest. - } -} - -HOOPLE_MAIN(test_rsa, ) - diff --git a/octopi/library/cromp/cromp_client.cpp b/octopi/library/cromp/cromp_client.cpp index 141bda78..1c58b010 100644 --- a/octopi/library/cromp/cromp_client.cpp +++ b/octopi/library/cromp/cromp_client.cpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/octopi/library/cromp/cromp_common.cpp b/octopi/library/cromp/cromp_common.cpp index 3a05e9ec..f732ac62 100644 --- a/octopi/library/cromp/cromp_common.cpp +++ b/octopi/library/cromp/cromp_common.cpp @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include #include @@ -104,9 +104,9 @@ const int cromp_common::HOSTCHOP = 6; double cromp_common::_bytes_sent_total = 0.0; double cromp_common::_bytes_received_total = 0.0; - SAFE_STATIC_CONST(rsa_crypto, _hidden_localhost_only_key, + SAFE_STATIC_CONST(old_school_rsa_crypto, _hidden_localhost_only_key, (encryption_infoton::RSA_KEY_SIZE)) - const rsa_crypto &cromp_common::localhost_only_key() { + const old_school_rsa_crypto &cromp_common::localhost_only_key() { #ifdef DEBUG_CROMP_COMMON FUNCDEF("localhost_only_key"); #endif @@ -119,7 +119,7 @@ double cromp_common::_bytes_received_total = 0.0; if (!was_initted) LOG("started creating localhost RSA key."); #endif - const rsa_crypto &to_return = _hidden_localhost_only_key(); + const old_school_rsa_crypto &to_return = _hidden_localhost_only_key(); #ifdef DEBUG_CROMP_COMMON if (!was_initted) LOG("done creating localhost RSA key."); diff --git a/octopi/library/cromp/cromp_common.h b/octopi/library/cromp/cromp_common.h index 2f5b20c1..8ac3a0fa 100644 --- a/octopi/library/cromp/cromp_common.h +++ b/octopi/library/cromp/cromp_common.h @@ -13,7 +13,7 @@ * Please send any updates to: fred@gruntose.com * \*****************************************************************************/ -#include +#include #include #include #include @@ -177,7 +177,7 @@ public: // returns our octopus support object. this should always exist when this // object is constructed properly. - static const crypto::rsa_crypto &localhost_only_key(); + static const crypto::old_school_rsa_crypto &localhost_only_key(); // this key should *only* be used for speeding up encryption on the local // host. it is generated when the first caller needs it but then is // a constant key during the program's runtime. this object can be used diff --git a/octopi/library/tentacles/encryption_infoton.cpp b/octopi/library/tentacles/encryption_infoton.cpp index b6250755..36f06985 100644 --- a/octopi/library/tentacles/encryption_infoton.cpp +++ b/octopi/library/tentacles/encryption_infoton.cpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -113,7 +113,7 @@ outcome encryption_infoton::prepare_blowfish_key(blowfish_crypto &new_key) return _success; } - rsa_crypto pub(_public_key); // suck in the provided key. + old_school_rsa_crypto pub(_public_key); // suck in the provided key. blowfish_crypto agreed_key(BLOWFISH_KEY_SIZE); // random blowfish key. new_key = agreed_key; @@ -125,22 +125,22 @@ outcome encryption_infoton::prepare_blowfish_key(blowfish_crypto &new_key) return _success; } -outcome encryption_infoton::prepare_both_keys(rsa_crypto &private_key) +outcome encryption_infoton::prepare_both_keys(old_school_rsa_crypto &private_key) { - rsa_crypto priv(RSA_KEY_SIZE); // generate random key. + old_school_rsa_crypto priv(RSA_KEY_SIZE); // generate random key. outcome to_return = prepare_public_key(priv); if (to_return == tentacle::OKAY) private_key = priv; return to_return; } -outcome encryption_infoton::prepare_public_key(const rsa_crypto &private_key) +outcome encryption_infoton::prepare_public_key(const old_school_rsa_crypto &private_key) { bool worked = private_key.public_key(_public_key); if (!worked) return tentacle::DISALLOWED; // why would that ever fail? return tentacle::OKAY; } -outcome encryption_infoton::extract_response(const rsa_crypto &private_key, +outcome encryption_infoton::extract_response(const old_school_rsa_crypto &private_key, blowfish_crypto &new_key) const { FUNCDEF("extract_response"); diff --git a/octopi/library/tentacles/encryption_infoton.h b/octopi/library/tentacles/encryption_infoton.h index c9a67c2c..9f02b217 100644 --- a/octopi/library/tentacles/encryption_infoton.h +++ b/octopi/library/tentacles/encryption_infoton.h @@ -16,7 +16,7 @@ \*****************************************************************************/ #include -#include +#include #include #include @@ -68,14 +68,14 @@ public: "new_key" will always be used to communicate with the client after this. */ - basis::outcome prepare_public_key(const crypto::rsa_crypto &private_key); + basis::outcome prepare_public_key(const crypto::old_school_rsa_crypto &private_key); //!< prepares the request side for a client. /*!< the rsa public key will be generated from the "private_key". */ - basis::outcome prepare_both_keys(crypto::rsa_crypto &private_key); + basis::outcome prepare_both_keys(crypto::old_school_rsa_crypto &private_key); //!< sets up both keys by randomly generating the "private_key". - basis::outcome extract_response(const crypto::rsa_crypto &private_key, + basis::outcome extract_response(const crypto::old_school_rsa_crypto &private_key, crypto::blowfish_crypto &new_key) const; //!< used by the client to extract the shared blowfish key from the server. /*!< using the private key, the server's response is decrypted and stored diff --git a/octopi/library/tentacles/encryption_tentacle.cpp b/octopi/library/tentacles/encryption_tentacle.cpp index 73789b73..7cfe5046 100644 --- a/octopi/library/tentacles/encryption_tentacle.cpp +++ b/octopi/library/tentacles/encryption_tentacle.cpp @@ -17,7 +17,7 @@ #include "key_repository.h" #include -#include +#include #include #include #include @@ -52,7 +52,7 @@ encryption_tentacle::encryption_tentacle(const byte_array &private_key) (encryption_infoton::encryption_classifier(), false), _server_side(false), _keys(new key_repository), - _rsa_private(new rsa_crypto(private_key)) + _rsa_private(new old_school_rsa_crypto(private_key)) { } @@ -61,7 +61,7 @@ encryption_tentacle::encryption_tentacle(int key_size) (encryption_infoton::encryption_classifier(), false), _server_side(false), _keys(new key_repository), - _rsa_private(new rsa_crypto(key_size)) + _rsa_private(new old_school_rsa_crypto(key_size)) { } @@ -73,7 +73,7 @@ encryption_tentacle::~encryption_tentacle() key_repository &encryption_tentacle::keys() const { return *_keys; } -const rsa_crypto &encryption_tentacle::private_key() const +const old_school_rsa_crypto &encryption_tentacle::private_key() const { return *_rsa_private; } outcome encryption_tentacle::reconstitute(const string_array &classifier, diff --git a/octopi/library/tentacles/encryption_tentacle.h b/octopi/library/tentacles/encryption_tentacle.h index 362da6e8..398e2543 100644 --- a/octopi/library/tentacles/encryption_tentacle.h +++ b/octopi/library/tentacles/encryption_tentacle.h @@ -84,14 +84,14 @@ public: /*!< this is very private info, but it's needed for encrypting items going back to the client. */ - const crypto::rsa_crypto &private_key() const; + const crypto::old_school_rsa_crypto &private_key() const; //!< provides access to the key held here. /*!< this is an important object; do not expose it externally. */ private: bool _server_side; //!< true if we're acting as a server. key_repository *_keys; //!< our table of keys that we've agreed on. - crypto::rsa_crypto *_rsa_private; //!< the private key for a client side. + crypto::old_school_rsa_crypto *_rsa_private; //!< the private key for a client side. }; } //namespace. diff --git a/scripts/buildor/upgrade_hoople_to_feistymeow.sh b/scripts/buildor/upgrade_hoople_to_feistymeow.sh index 12d31222..886f1a6c 100644 --- a/scripts/buildor/upgrade_hoople_to_feistymeow.sh +++ b/scripts/buildor/upgrade_hoople_to_feistymeow.sh @@ -142,7 +142,7 @@ standards and usages." | sed -e 's/class encryption_tentacle;/#include /g' \ | sed -e 's/class login_tentacle;/#include /g' \ | sed -e 's/class thread_cabinet;/#include /g' \ - | sed -e 's/RSA_crypto/rsa_crypto/g' \ + | sed -e 's/RSA_crypto/old_school_rsa_crypto/g' \ | sed -e 's/float_plus/double_plus/g' \ | sed -e 's/basis::obscure_/structures::obscure_/g' \ | sed -e 's/program_wide_logger()/program_wide_logger::get()/g' \