]> feistymeow.org Git - feisty_meow.git/commitdiff
breaking changes, not finished
authorFred T. Hamster <fred@feistymeow.org>
Sat, 14 Mar 2026 00:05:29 +0000 (20:05 -0400)
committerFred T. Hamster <fred@feistymeow.org>
Sat, 14 Mar 2026 00:05:29 +0000 (20:05 -0400)
will not build quite yet, but nearly there...

21 files changed:
nucleus/library/crypto/blowfish_crypto.cpp
nucleus/library/crypto/blowfish_crypto.h
nucleus/library/crypto/cryptical_envelopment.cpp [new file with mode: 0644]
nucleus/library/crypto/cryptical_envelopment.h [new file with mode: 0644]
nucleus/library/crypto/makefile
nucleus/library/crypto/old_school_rsa_crypto.cpp [new file with mode: 0644]
nucleus/library/crypto/old_school_rsa_crypto.h [new file with mode: 0644]
nucleus/library/crypto/rsa_crypto.cpp [deleted file]
nucleus/library/crypto/rsa_crypto.h [deleted file]
nucleus/library/tests_crypto/makefile
nucleus/library/tests_crypto/test_blowfish_crypto.cpp
nucleus/library/tests_crypto/test_old_school_rsa_crypto.cpp [new file with mode: 0644]
nucleus/library/tests_crypto/test_rsa_crypto.cpp [deleted file]
octopi/library/cromp/cromp_client.cpp
octopi/library/cromp/cromp_common.cpp
octopi/library/cromp/cromp_common.h
octopi/library/tentacles/encryption_infoton.cpp
octopi/library/tentacles/encryption_infoton.h
octopi/library/tentacles/encryption_tentacle.cpp
octopi/library/tentacles/encryption_tentacle.h
scripts/buildor/upgrade_hoople_to_feistymeow.sh

index b68c7d45328de7c8a57b59ad2229d71add720f4a..3c0596d6df75cf66c12178313ae0ea685536bef7 100644 (file)
@@ -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("<<decrypt<<");
   return to_return;
 }
+*/
 
 } //namespace.
 
index 42a6250335d1e9db286bcc7c18a04fc9cbfb2de7..f69923f126581bd032c452f3ed89ec265d501a72 100644 (file)
 #include <basis/byte_array.h>
 #include <basis/contracts.h>
 
+#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 (file)
index 0000000..e717d1b
--- /dev/null
@@ -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 <basis/astring.h>
+#include <basis/functions.h>
+#include <basis/mutex.h>
+#include <loggers/critical_events.h>
+#include <loggers/program_wide_logger.h>
+#include <mathematics/chaos.h>
+#include <structures/static_memory_gremlin.h>
+
+///#include <openssl/blowfish.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
+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("<<encrypt<<");
+  return to_return;
+}
+
+bool cryptical_envelopment::decrypt(const byte_array &source,
+    byte_array &target) const
+{
+  FUNCDEF("decrypt");
+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("<<decrypt<<");
+  return to_return;
+}
+
+} //namespace.
+
+
diff --git a/nucleus/library/crypto/cryptical_envelopment.h b/nucleus/library/crypto/cryptical_envelopment.h
new file mode 100644 (file)
index 0000000..9b07a44
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef CRYPTICAL_ENVELOPMENT_CLASS
+#define CRYPTICAL_ENVELOPMENT_CLASS
+
+/*
+*  Name   : cryptical_envelopment
+*  Author : Chris Koeritz
+*
+*  Purpose: Implements the majority of encryption processing using the
+*  OpenSSL EVP methods, aka the digital envelope routines.
+*****
+* 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 <basis/byte_array.h>
+#include <basis/contracts.h>
+
+// 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
+
index 97c7376a06a42988dbcff9ec79d0e76eb4f48c2f..06b612c4439385a4b25c2fce4f3b72fe69b64b42 100644 (file)
@@ -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 (file)
index 0000000..43a7017
--- /dev/null
@@ -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 <basis/functions.h>
+#include <loggers/critical_events.h>
+#include <loggers/program_wide_logger.h>
+#include <mathematics/chaos.h>
+#include <structures/object_packers.h>
+#include <structures/static_memory_gremlin.h>
+
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/rsa.h>
+
+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 (file)
index 0000000..524fb39
--- /dev/null
@@ -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 <basis/byte_array.h>
+#include <basis/contracts.h>
+
+// 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 (file)
index b96b3cd..0000000
+++ /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 <basis/functions.h>
-#include <loggers/critical_events.h>
-#include <loggers/program_wide_logger.h>
-#include <mathematics/chaos.h>
-#include <structures/object_packers.h>
-#include <structures/static_memory_gremlin.h>
-
-#include <openssl/bn.h>
-#include <openssl/err.h>
-#include <openssl/rsa.h>
-
-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 (file)
index b241930..0000000
+++ /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 <basis/byte_array.h>
-#include <basis/contracts.h>
-
-// 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
-
index d7d3f49e508b3c313f2858d7d1934adb1a5f9ea4..e0854cbbacc87bfe9045d0e4bd1ba8afb6c0dcd3 100644 (file)
@@ -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
index abf9f7d870cd43e2df410f7332675e46e1cb4733..23f622c0f837a3ca25710d15f659128ceb52085e 100644 (file)
@@ -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 (file)
index 0000000..c0dacda
--- /dev/null
@@ -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 <application/hoople_main.h>
+#include <basis/byte_array.h>
+#include <basis/astring.h>
+#include <crypto/old_school_rsa_crypto.h>
+#include <mathematics/chaos.h>
+#include <processes/ethread.h>
+#include <processes/thread_cabinet.h>
+#include <structures/static_memory_gremlin.h>
+#include <structures/unique_id.h>
+#include <textual/byte_formatter.h>
+#include <textual/string_manipulation.h>
+#include <timely/time_control.h>
+#include <timely/time_stamp.h>
+#include <unit_test/unit_base.h>
+
+#include <stdio.h>
+#include <string.h>
+
+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<unit_base *>(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 (file)
index adc85d5..0000000
+++ /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 <application/hoople_main.h>
-#include <basis/byte_array.h>
-#include <basis/astring.h>
-#include <crypto/rsa_crypto.h>
-#include <mathematics/chaos.h>
-#include <processes/ethread.h>
-#include <processes/thread_cabinet.h>
-#include <structures/static_memory_gremlin.h>
-#include <structures/unique_id.h>
-#include <textual/byte_formatter.h>
-#include <textual/string_manipulation.h>
-#include <timely/time_control.h>
-#include <timely/time_stamp.h>
-#include <unit_test/unit_base.h>
-
-#include <stdio.h>
-#include <string.h>
-
-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<unit_base *>(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, )
-
index 141bda783d922960f2dcfa686c166345cd7a16a8..1c58b010d2c38c0805c67d065f0a6af97714a963 100644 (file)
@@ -20,7 +20,7 @@
 #include <basis/functions.h>
 #include <basis/mutex.h>
 #include <configuration/application_configuration.h>
-#include <crypto/rsa_crypto.h>
+#include <crypto/old_school_rsa_crypto.h>
 #include <loggers/program_wide_logger.h>
 #include <mathematics/chaos.h>
 #include <octopus/entity_defs.h>
index 3a05e9ec3cfd6eca5a7f061c22b13bf74398aadf..f732ac622526e1fca6371f7e14e1269f1f2d94be 100644 (file)
@@ -35,7 +35,7 @@
 #include <basis/functions.h>
 #include <basis/astring.h>
 #include <basis/mutex.h>
-#include <crypto/rsa_crypto.h>
+#include <crypto/old_school_rsa_crypto.h>
 #include <loggers/program_wide_logger.h>
 #include <octopus/entity_data_bin.h>
 #include <octopus/entity_defs.h>
@@ -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.");
index 2f5b20c180bdf59f6c8a012908d13e6b7439e4b5..8ac3a0fa163ba31c3f3268f3093dd0460b1809f5 100644 (file)
@@ -13,7 +13,7 @@
 * Please send any updates to: fred@gruntose.com                               *
 \*****************************************************************************/
 
-#include <crypto/rsa_crypto.h>
+#include <crypto/old_school_rsa_crypto.h>
 #include <octopus/octopus.h>
 #include <octopus/entity_defs.h>
 #include <octopus/entity_data_bin.h>
@@ -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
index b62507557e06ff5bda42701f977df6d689d0ad7f..36f069854df997cdbfa4b6d7a39c1db442f5b163 100644 (file)
@@ -19,7 +19,7 @@
 #include <basis/mutex.h>
 #include <basis/functions.h>
 #include <crypto/blowfish_crypto.h>
-#include <crypto/rsa_crypto.h>
+#include <crypto/old_school_rsa_crypto.h>
 #include <octopus/tentacle.h>
 #include <structures/static_memory_gremlin.h>
 #include <textual/byte_formatter.h>
@@ -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");
index c9a67c2cfed1c4f7bc0fb66f8d29b4a4713214e8..9f02b2172451f54447b10890908b1144b93268e1 100644 (file)
@@ -16,7 +16,7 @@
 \*****************************************************************************/
 
 #include <crypto/blowfish_crypto.h>
-#include <crypto/rsa_crypto.h>
+#include <crypto/old_school_rsa_crypto.h>
 #include <octopus/entity_defs.h>
 #include <octopus/infoton.h>
 
@@ -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
index 73789b7375e8a5b20fb02ab5a5a57d9924f2843a..7cfe50464883c729b52e62a06204757c4d1090e8 100644 (file)
@@ -17,7 +17,7 @@
 #include "key_repository.h"
 
 #include <crypto/blowfish_crypto.h>
-#include <crypto/rsa_crypto.h>
+#include <crypto/old_school_rsa_crypto.h>
 #include <loggers/program_wide_logger.h>
 #include <structures/symbol_table.h>
 #include <textual/byte_formatter.h>
@@ -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,
index 362da6e80ab824a89d395c265ccfc72ed1d4163c..398e254351f5989912479981cc638e2ecc50adc9 100644 (file)
@@ -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.
index 12d31222c3051c20fac2cce4043a65059fe658eb..886f1a6ca2a090e2d2c7407cffb6b25d5209b8fc 100644 (file)
@@ -142,7 +142,7 @@ standards and usages."
     | sed -e 's/class encryption_tentacle;/#include <tentacles\/encryption_tentacle.h>/g' \
     | sed -e 's/class login_tentacle;/#include <tentacles\/login_tentacle.h>/g' \
     | sed -e 's/class thread_cabinet;/#include <processes\/thread_cabinet.h>/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>/double_plus/g' \
     | sed -e 's/basis::obscure_/structures::obscure_/g' \
     | sed -e 's/program_wide_logger()/program_wide_logger::get()/g' \