]> feistymeow.org Git - feisty_meow.git/commitdiff
super achey breaky change -- switching to twofish
authorFred T. Hamster <fred@feistymeow.org>
Mon, 16 Mar 2026 19:07:20 +0000 (15:07 -0400)
committerFred T. Hamster <fred@feistymeow.org>
Mon, 16 Mar 2026 19:07:20 +0000 (15:07 -0400)
we've renamed blowfish crypto in honor of openssl breaking it for us,
seemingly.  and we're going to just drop in a replacement of twofish.
however, right now, that's still in progress, so this code will not build yet.

nucleus/library/crypto/blowfish_crypto.cpp [deleted file]
nucleus/library/crypto/blowfish_crypto.h [deleted file]
nucleus/library/crypto/borked_blowfish_crypto.cpp [new file with mode: 0644]
nucleus/library/crypto/borked_blowfish_crypto.h [new file with mode: 0644]
nucleus/library/crypto/makefile
nucleus/library/crypto/twofish_crypto.cpp
nucleus/library/crypto/twofish_crypto.h
nucleus/library/tests_crypto/makefile
nucleus/library/tests_crypto/test_blowfish_crypto.cpp
nucleus/library/tests_crypto/test_twofish_crypto.cpp

diff --git a/nucleus/library/crypto/blowfish_crypto.cpp b/nucleus/library/crypto/blowfish_crypto.cpp
deleted file mode 100644 (file)
index 02ce500..0000000
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
-*  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"
-
-#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/err.h>
-#include <openssl/evp.h>
-
-using namespace basis;
-using namespace loggers;
-using namespace mathematics;
-using namespace structures;
-
-namespace crypto {
-
-////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.
-
-//#undef set_key
-  // get rid of a macro we don't want.
-
-//#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
-  #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_BLOWFISH
-  // 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
-*/
-
-blowfish_crypto::blowfish_crypto(int key_size)
-: cryptical_envelopment(EVP_bf_cbc())
-///_key_size(key_size),
-///  _key(new byte_array)
-{
-  set_key(key_size);
-/*
-  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");
-*/
-}
-
-blowfish_crypto::blowfish_crypto(const byte_array &key, int key_size)
-: cryptical_envelopment(EVP_bf_cbc())
-//: _key_size(key_size),
-//  _key(new byte_array(key))
-{
-  set_key(key, key_size);
-/*
-  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");
-*/
-}
-
-blowfish_crypto::blowfish_crypto(const blowfish_crypto &to_copy)
-: root_object(),
-  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");
-}
-
-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; }
-
-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;
-  *((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");
-  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 blowfish_crypto::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);
-}
-
-SAFE_STATIC(mutex, __vector_init_lock, )
-
-const byte_array &blowfish_crypto::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 doing init");
-    for (int i = 0; i < to_return.length(); i++)
-      to_return[i] = abyte(214 - i);
-    initted = true;
-    LOG("finished init process");
-  }
-  return to_return;
-}
-
-bool blowfish_crypto::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, EVP_bf_cbc(), NULL_POINTER, NULL_POINTER, NULL_POINTER);
-  if (!initret) {
-    // zero means a failure of the initialization.
-    ALWAYS_LOG(a_sprintf("failure in calling EVP_EncryptInit_ex, with error %s", GET_SSL_ERROR()));
-    exit(1);
-  }
-  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.
-    ALWAYS_LOG(a_sprintf("second phase failure in calling EVP_EncryptInit_ex, with error %s", GET_SSL_ERROR()));
-    exit(1);
-  }
-
-  // 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("  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 blowfish_crypto::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));
-///NOOOOOOO BITS_PER_BYTE * _key->length()));
-  int initret = EVP_DecryptInit_ex(session, EVP_bf_cbc(), NULL_POINTER, NULL_POINTER, NULL_POINTER);
-  if (!initret) {
-    // zero means a failure of the initialization.
-//hmmm: below approach is called a deadly error.  use that instead, throughout.
-    ALWAYS_LOG(a_sprintf("failure in calling EVP_DecryptInit_ex, with error %s", GET_SSL_ERROR()));
-    exit(1);
-  }
-  // 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.
-    ALWAYS_LOG(a_sprintf("second phase failure in calling EVP_DecryptInit_ex, with error %s", GET_SSL_ERROR()));
-    exit(1);
-  }
-
-  // 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("  padding added %d bytes.", 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/blowfish_crypto.h b/nucleus/library/crypto/blowfish_crypto.h
deleted file mode 100644 (file)
index 8cedb32..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-#ifndef BLOWFISH_CRYPTO_CLASS
-#define BLOWFISH_CRYPTO_CLASS
-
-/*****************************************************************************\
-*                                                                             *
-*  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 <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 cryptical_envelopment
-//: public virtual basis::root_object
-{
-public:
-  blowfish_crypto(int key_size);
-    //!< this will create a new random key of the "key_size", in bits.
-    /*!< the valid sizes are from 64 bits to 448 bits (we are forcing a
-    higher minimum than the published algorithm because we have found smaller
-    keys to be unreliable during decryption.  keys of 168 bits and larger
-    should be very secure.  it is said that if a billion computers each tried
-    a billion keys a second, then a 168 bit key would take 10 * 10^24 years
-    to break (using brute force).  this is essentially unbreakable since the
-    age of the universe is only 10 * 10^9 years so far. */
-
-  blowfish_crypto(const basis::byte_array &key, int key_size);
-    //!< uses a pre-existing "key".
-
-  blowfish_crypto(const blowfish_crypto &to_copy);  //!< copy constructor.
-
-  virtual ~blowfish_crypto();
-
-  blowfish_crypto &operator = (const blowfish_crypto &to_copy);
-
-  DEFINE_CLASS_NAME("blowfish_crypto");
-
-  // blowfish relevant values for appropriate key sizes.
-  virtual int minimum_key_size() const { return 32; }
-  virtual int maximum_key_size() const { return 448; }
-
-///  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".
-
-///  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 blowfish_crypto.cpp). */
-
-private:
-///  int _key_size;  //!< number of bits in the key.
-///  basis::byte_array *_key;  //!< our secret key.
-};
-
-} //namespace.
-
-#endif
-
diff --git a/nucleus/library/crypto/borked_blowfish_crypto.cpp b/nucleus/library/crypto/borked_blowfish_crypto.cpp
new file mode 100644 (file)
index 0000000..f912d84
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+*  Name   : borked_blowfish_crypto
+*  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 "borked_blowfish_crypto.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/err.h>
+#include <openssl/evp.h>
+
+using namespace basis;
+using namespace loggers;
+using namespace mathematics;
+using namespace structures;
+
+namespace crypto {
+
+//#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
+  #undef LOG
+  #define LOG(t) CLASS_EMERGENCY_LOG(program_wide_logger::get(), t)
+#else
+  #undef LOG
+  #define LOG(t) 
+#endif
+
+borked_blowfish_crypto::borked_blowfish_crypto(int key_size)
+: cryptical_envelopment(EVP_bf_cbc())
+{
+  set_key(key_size);
+}
+
+borked_blowfish_crypto::borked_blowfish_crypto(const byte_array &key, int key_size)
+: cryptical_envelopment(EVP_bf_cbc())
+{
+  set_key(key, key_size);
+}
+
+borked_blowfish_crypto::borked_blowfish_crypto(const borked_blowfish_crypto &to_copy)
+: root_object(),
+  cryptical_envelopment(*this)
+{
+}
+
+borked_blowfish_crypto::~borked_blowfish_crypto()
+{
+}
+
+borked_blowfish_crypto &borked_blowfish_crypto::operator = (const borked_blowfish_crypto &to_copy)
+{
+  if (this == &to_copy) return *this;
+  *((cryptical_envelopment *)this) = *((cryptical_envelopment *)&to_copy);
+//hmmm: is that the best way to do this?
+  return *this;
+}
+
+} //namespace.
+
diff --git a/nucleus/library/crypto/borked_blowfish_crypto.h b/nucleus/library/crypto/borked_blowfish_crypto.h
new file mode 100644 (file)
index 0000000..dfe0709
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef BLOWFISH_CRYPTO_CLASS
+#define BLOWFISH_CRYPTO_CLASS
+
+/*
+*  Name   : borked_blowfish_crypto
+*  Author : Chris Koeritz
+*  Purpose: provides BlowFish encryption on byte_arrays using the OpenSSL package.
+****
+* 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:
+ * this class is currently failing with bad decrypt, which we actually blame the openssl
+ * libraries for.  we have the same exact underlying usage of cryptical_envelopment class
+ * to drive the EVP functions for our twofish implementation, and it never has that issue.
+ * our blowfish implementation *used* to work fine, until openssl 3 or so.
+ */
+
+#include <basis/byte_array.h>
+#include <basis/contracts.h>
+
+#include "cryptical_envelopment.h"
+
+namespace crypto {
+
+class borked_blowfish_crypto : public cryptical_envelopment
+{
+public:
+  borked_blowfish_crypto(int key_size);
+    //!< this will create a new random key of the "key_size", in bits.
+    /*!< the valid sizes are from 64 bits to 448 bits (we are forcing a
+    higher minimum than the published algorithm because we have found smaller
+    keys to be unreliable during decryption.  keys of 168 bits and larger
+    should be very secure.  it is said that if a billion computers each tried
+    a billion keys a second, then a 168 bit key would take 10 * 10^24 years
+    to break (using brute force).  this is essentially unbreakable since the
+    age of the universe is only 10 * 10^9 years so far. */
+
+  borked_blowfish_crypto(const basis::byte_array &key, int key_size);
+    //!< uses a pre-existing "key".
+
+  borked_blowfish_crypto(const borked_blowfish_crypto &to_copy);  //!< copy constructor.
+
+  virtual ~borked_blowfish_crypto();
+
+  borked_blowfish_crypto &operator = (const borked_blowfish_crypto &to_copy);
+
+  DEFINE_CLASS_NAME("borked_blowfish_crypto");
+
+  // blowfish relevant values for appropriate key sizes.
+  virtual int minimum_key_size() const { return 64; }  // officially, this is 32.
+  virtual int maximum_key_size() const { return 448; }
+};
+
+} //namespace.
+
+#endif
+
index 4ba15f86d038392dad0577019d8f7433d463a0e2..ec80a34ffb09dbf79360ba509a838dcdba8902a5 100644 (file)
@@ -4,7 +4,7 @@ include cpp/variables.def
 
 TYPE = library
 PROJECT = crypto
-SOURCE = blowfish_crypto.cpp cryptical_envelopment.cpp old_school_rsa_crypto.cpp ssl_init.cpp twofish_crypto.cpp 
+SOURCE = borked_blowfish_crypto.cpp cryptical_envelopment.cpp old_school_rsa_crypto.cpp ssl_init.cpp twofish_crypto.cpp 
 USE_SSL = t
 TARGETS = crypto.lib
 
index ea9ad79382b5bc6a8abb8a0d7e9d8af637907811..41bd802a927b2ce59224c8ff1d6d09c54c62e876 100644 (file)
@@ -21,7 +21,6 @@
 #include <mathematics/chaos.h>
 #include <structures/static_memory_gremlin.h>
 
-//#include <openssl/twofish.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
 
@@ -30,15 +29,16 @@ using namespace loggers;
 using namespace mathematics;
 using namespace structures;
 
-namespace crypto {
-
-////const int FUDGE = 128;
-  // extra space for the cipher's block size.  twofish is only 8 bytes for
-  // the cipher block size, but we ensure there will definitely be no
-  // problems.
+/*
+ Q: is twofish truly requiring 128/192/256 key sizes only?
+ A: no, schneier says any key size up to 256 bits.
+ Q: can twofish really support *any* key length up to 256?
+ A: well, not in openssl.  we are getting invalid key length complaints
+    with keys below 92 bits.  this was calculated by testing for quite
+    a while with only those size keys, and 92 seems reliable as a minimum.
+*/
 
-//#undef set_key
-  // get rid of a macro we don't want.
+namespace crypto {
 
 //#define DEBUG_TWOFISH
   // uncomment for noisier version.
@@ -52,321 +52,35 @@ namespace crypto {
   #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_TWOFISH
-  // 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
-*/
-
 twofish_crypto::twofish_crypto(int key_size)
 : cryptical_envelopment(EVP_aes_256_cbc())
-///_key_size(key_size),
-///  _key(new byte_array)
 {
   set_key(key_size);
-/*
-  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");
-*/
 }
 
 twofish_crypto::twofish_crypto(const byte_array &key, int key_size)
 : cryptical_envelopment(EVP_aes_256_cbc())
-//: _key_size(key_size),
-//  _key(new byte_array(key))
 {
   set_key(key, key_size);
-/*
-  FUNCDEF("ctor(byte_array,int)");
-  static_ssl_initializer();
-  // any problems with the key provided are horrid.  they will yield a
-  // non-working twofish 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");
-*/
 }
 
 twofish_crypto::twofish_crypto(const twofish_crypto &to_copy)
 : root_object(),
   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");
 }
 
 twofish_crypto::~twofish_crypto()
 {
-/*
-  FUNCDEF("destructor");
-  LOG("prior to key whack");
-  WHACK(_key);
-  LOG("after key whack");
-*/
 }
 
-/*
-int twofish_crypto::key_size() const { return _key_size; }
-
-const byte_array &twofish_crypto::get_key() const { return *_key; }
-
-int twofish_crypto::minimum_key_size() { return 64; }
-
-int twofish_crypto::maximum_key_size() { return 448; }
-*/
-
 twofish_crypto &twofish_crypto::operator = (const twofish_crypto &to_copy)
 {
   if (this == &to_copy) return *this;
   *((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 twofish_crypto::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 twofish_crypto::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);
-}
-
-SAFE_STATIC(mutex, __vector_init_lock, )
-
-const byte_array &twofish_crypto::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 doing init");
-    for (int i = 0; i < to_return.length(); i++)
-      to_return[i] = abyte(214 - i);
-    initted = true;
-    LOG("finished init process");
-  }
-  return to_return;
-}
-
-bool twofish_crypto::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, EVP_bf_cbc(), NULL_POINTER, NULL_POINTER, NULL_POINTER);
-  if (!initret) {
-    // zero means a failure of the initialization.
-    ALWAYS_LOG(a_sprintf("failure in calling EVP_EncryptInit_ex, with error %s", GET_SSL_ERROR()));
-    exit(1);
-  }
-  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.
-    ALWAYS_LOG(a_sprintf("second phase failure in calling EVP_EncryptInit_ex, with error %s", GET_SSL_ERROR()));
-    exit(1);
-  }
-
-  // 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("  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 twofish_crypto::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));
-///NOOOOOOO BITS_PER_BYTE * _key->length()));
-  int initret = EVP_DecryptInit_ex(session, EVP_bf_cbc(), NULL_POINTER, NULL_POINTER, NULL_POINTER);
-  if (!initret) {
-    // zero means a failure of the initialization.
-//hmmm: below approach is called a deadly error.  use that instead, throughout.
-    ALWAYS_LOG(a_sprintf("failure in calling EVP_DecryptInit_ex, with error %s", GET_SSL_ERROR()));
-    exit(1);
-  }
-  // 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.
-    ALWAYS_LOG(a_sprintf("second phase failure in calling EVP_DecryptInit_ex, with error %s", GET_SSL_ERROR()));
-    exit(1);
-  }
-
-  // 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("  padding added %d bytes.", 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.
 
-
index 381c8dd463bc10801f5f26c87d87c1c807f2e0aa..95e74297cfe23651f478b3eb9316171a8ef48a7d 100644 (file)
@@ -1,19 +1,18 @@
 #ifndef TWOFISH_CRYPTO_CLASS
 #define TWOFISH_CRYPTO_CLASS
 
-/*****************************************************************************\
-*                                                                             *
-*  Name   : twofish 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   : twofish_crypto
+* Author : Chris Koeritz
+* Purpose: provides twofish encryption using the openssl libraries.
+****
+* 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>
 
 namespace crypto {
 
-//! Provides TwoFish encryption on byte_arrays using the OpenSSL package.
-
 class twofish_crypto : public cryptical_envelopment
-//: public virtual basis::root_object
 {
 public:
   twofish_crypto(int key_size);
     //!< this will create a new random key of the "key_size", in bits.
-    /*!< the valid sizes are from 64 bits to 448 bits (we are forcing a
-    higher minimum than the published algorithm because we have found smaller
-    keys to be unreliable during decryption.  keys of 168 bits and larger
-    should be very secure.  it is said that if a billion computers each tried
-    a billion keys a second, then a 168 bit key would take 10 * 10^24 years
-    to break (using brute force).  this is essentially unbreakable since the
-    age of the universe is only 10 * 10^9 years so far. */
+    /*!< the valid sizes are from 128 bits to 256 bits.  AES apparently only
+    requires that 128, 192 and 256 actually work, but the intervening key
+    sizes should be fine also. */
 
   twofish_crypto(const basis::byte_array &key, int key_size);
     //!< uses a pre-existing "key".
@@ -59,43 +51,6 @@ public:
      not the kind of deterministic behavior we might expect.
     */
   virtual int maximum_key_size() const { return 256; }
-
-///  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".
-
-///  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 twofish_crypto.cpp). */
-
-private:
-///  int _key_size;  //!< number of bits in the key.
-///  basis::byte_array *_key;  //!< our secret key.
 };
 
 } //namespace.
index 58b9ff7c38d9fb449c39f92a26abc23b736aea37..58b484714bdd74d485f24385d5668d10517e0b27 100644 (file)
@@ -2,7 +2,9 @@ include cpp/variables.def
 
 PROJECT = tests_crypto
 TYPE = test
-TARGETS = test_blowfish_crypto.exe test_old_school_rsa_crypto.exe test_twofish_crypto.exe 
+TARGETS = test_blowfish_crypto.exe  test_old_school_rsa_crypto.exe test_twofish_crypto.exe 
+# test_blowfish_crypto.exe  --  currently blows up, which we think is an error in openssl, because the twofish crypto works perfectly using the same
+#   cryptical envelopment base.  this is annoying, but we could stop using the legacy provider entirely if we didn't do blowfish any more.  not yet.
 LOCAL_LIBS_USED = unit_test crypto application processes loggers configuration textual timely \
   filesystem structures basis 
 USE_SSL = t
index 3baff5d760c504e74f05666242d425c1b1357f11..4fa124ee0f7cf8ef81e34dc40bbcf34ae4b7117d 100644 (file)
@@ -14,7 +14,7 @@
 #include <application/hoople_main.h>
 #include <basis/byte_array.h>
 #include <basis/astring.h>
-#include <crypto/blowfish_crypto.h>
+#include <crypto/borked_blowfish_crypto.h>
 #include <mathematics/chaos.h>
 #include <processes/ethread.h>
 #include <processes/thread_cabinet.h>
@@ -57,9 +57,9 @@ 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 = 32;
-const int blowfish_crypto_maximum_key_size_in_bits = 448;
+// some constants snagged from older version of borked_blowfish_crypto class...
+const int borked_blowfish_crypto_minimum_key_size_in_bits = 32;
+const int borked_blowfish_crypto_maximum_key_size_in_bits = 448;
 
 //////////////
 
@@ -141,8 +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_in_bits,
-        blowfish_crypto_maximum_key_size_in_bits));
+    borked_blowfish_crypto bc(_parent.randomizer().inclusive(borked_blowfish_crypto_minimum_key_size_in_bits,
+        borked_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());
index 055eb65c5db70088e4a06135f85dfc52ad6013f6..565b7cc73f2bbffc02f574f34cc36aaf3b2f9b5e 100644 (file)
@@ -46,19 +46,17 @@ using namespace unit_test;
 #define DEBUG_TWOFISH
   // uncomment for noisier run.
 
-//const int TEST_RUNS_PER_KEY = 42;  // encryption test cycles done on each key.
-const int TEST_RUNS_PER_KEY = 420;  // encryption test cycles done on each key.
+const int TEST_RUNS_PER_KEY = 42;  // encryption test cycles done on each key.
 
 const int THREAD_COUNT = 10;  // number of threads testing twofish at once.
 
-//const int ITERATIONS = 64;  // number of test runs in our testing threads.
-const int ITERATIONS = 4200;  // number of test runs in our testing threads.
+const int ITERATIONS = 64;  // number of test runs in our testing threads.
 
 const int MAX_STRING = 64 * KILOBYTE;  // largest chunk that we'll try to encrypt.
 
 // some constants snagged from older version of twofish_crypto class...
-const int twofish_crypto_minimum_key_size_in_bits = 92;
-const int twofish_crypto_maximum_key_size_in_bits = 256;
+//const int twofish_crypto_minimum_key_size_in_bits = 92;
+//const int twofish_crypto_maximum_key_size_in_bits = 256;
 /*
  Q: is twofish truly requiring 128/192/256 key sizes only?
  A: no, schneier says any key size up to 256 bits.