+++ /dev/null
-/*
-* 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.
-
-
+++ /dev/null
-#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
-
--- /dev/null
+/*
+* 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.
+
--- /dev/null
+#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
+
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
#include <mathematics/chaos.h>
#include <structures/static_memory_gremlin.h>
-//#include <openssl/twofish.h>
#include <openssl/err.h>
#include <openssl/evp.h>
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.
#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.
-
#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".
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.
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
#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>
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;
//////////////
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());
#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.