00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <basis/byte_array.h>
00020 #include <basis/chaos.h>
00021 #include <basis/function.h>
00022 #include <basis/istring.h>
00023 #include <mechanisms/time_stamp.h>
00024 #include <data_struct/static_memory_gremlin.h>
00025 #include <textual/string_manipulation.h>
00026
00027 #include <openssl/blowfish.h>
00028 #include <openssl/crypto.h>
00029 #include <openssl/err.h>
00030 #include <openssl/evp.h>
00031 #include <openssl/rand.h>
00032
00033 #include <stdio.h>
00034 #include <string.h>
00035
00036 HOOPLE_STARTUP_CODE;
00037
00038 const int KEY_SIZE = 402;
00039
00040
00041 const int TEST_RUNS = 100;
00042
00043
00044 const int SEED_SIZE = 100;
00045
00046
00047 const int MAX_STRING = 1000000;
00048
00049
00050 const int MAX_CHUNK = 1024;
00051
00052
00053 chaos rando;
00054
00055 #define static_class_name() "blowfish_test"
00056
00057 void provide_init_vect(byte_array &new_iv)
00058 {
00059 new_iv.reset(EVP_MAX_IV_LENGTH);
00060 for (int i = 0; i < EVP_MAX_IV_LENGTH; i++) new_iv[i] = 214 - i;
00061 }
00062
00063 void generate_key(int size, byte_array &new_key)
00064 {
00065 new_key.reset(size);
00066 for (int i = 0; i < size; i++) new_key[i] = rando.inclusive(0, 255);
00067 }
00068
00069 const byte_array &random_seed()
00070 {
00071 static byte_array seed;
00072 static bool initted = false;
00073 if (!initted) {
00074 for (int i = 0; i < SEED_SIZE; i++) {
00075 seed += byte(rando.inclusive(0, 255));
00076 }
00077 initted = true;
00078 }
00079 return seed;
00080 }
00081
00083
00084 bool blowfish_encryption(const byte_array &key, const byte_array &init_vect,
00085 const byte_array &source, byte_array &target)
00086 {
00087 FUNCDEF("blowfish_encryption");
00088 target.reset();
00089 bool to_return = true;
00090
00091
00092 EVP_CIPHER_CTX session;
00093 EVP_CIPHER_CTX_init(&session);
00094 EVP_EncryptInit(&session, EVP_bf_cbc(), key.observe(), init_vect.observe());
00095 EVP_CIPHER_CTX_set_key_length(&session, key.length());
00096
00097 byte_array cipher(MAX_CHUNK + 100);
00098 for (int i = 0; i < source.length(); i += MAX_CHUNK) {
00099
00100 int edge = i + MAX_CHUNK - 1;
00101 if (edge > source.last())
00102 edge = source.last();
00103 int next_chunk = edge - i + 1;
00104 int cipher_len = 0;
00105
00106 int enc_ret = EVP_EncryptUpdate(&session, cipher.access(), &cipher_len,
00107 &source[i], next_chunk);
00108 if (enc_ret != 1) {
00109 continuable_error(static_class_name(), func, "encryption failed.");
00110 to_return = false;
00111 break;
00112 }
00113
00114
00115 cipher.zap(cipher_len, cipher.last());
00116 target += cipher;
00117 cipher.reset(MAX_CHUNK + 100);
00118 }
00119
00120
00121 int pad_len = 0;
00122 int enc_ret = EVP_EncryptFinal(&session, cipher.access(), &pad_len);
00123 if (enc_ret != 1) {
00124 continuable_error(static_class_name(), func, "finalizing encryption failed.");
00125 to_return = false;
00126 } else {
00127
00128 cipher.zap(pad_len, cipher.last());
00129 target += cipher;
00130 }
00131
00132 EVP_CIPHER_CTX_cleanup(&session);
00133 return to_return;
00134 }
00135
00136 bool blowfish_decryption(const byte_array &key, const byte_array &init_vect,
00137 const byte_array &source, byte_array &target)
00138 {
00139 FUNCDEF("blowfish_decryption");
00140 target.reset();
00141 bool to_return = true;
00142 EVP_CIPHER_CTX session;
00143 EVP_CIPHER_CTX_init(&session);
00144 EVP_DecryptInit(&session, EVP_bf_cbc(), key.observe(), init_vect.observe());
00145 EVP_CIPHER_CTX_set_key_length(&session, key.length());
00146
00147 byte_array uncipher(MAX_CHUNK + 100);
00148 for (int i = 0; i < source.length(); i += MAX_CHUNK) {
00149 int edge = i + MAX_CHUNK - 1;
00150 if (edge > source.last())
00151 edge = source.last();
00152 int next_chunk = edge - i + 1;
00153
00154 int uncipher_len = 0;
00155 int dec_ret = EVP_DecryptUpdate(&session, uncipher.access(), &uncipher_len,
00156 &source[i], next_chunk);
00157 if (dec_ret != 1) {
00158 continuable_error(static_class_name(), func, "decryption failed.");
00159 to_return = false;
00160 break;
00161 }
00162
00163 uncipher.zap(uncipher_len, uncipher.last());
00164 target += uncipher;
00165 uncipher.reset(MAX_CHUNK + 100);
00166 }
00167
00168 int pad_len = 0;
00169 int dec_ret = EVP_DecryptFinal(&session, uncipher.access(), &pad_len);
00170
00171 if (dec_ret != 1) {
00172 continuable_error(static_class_name(), func, "finalizing decryption failed.");
00173 to_return = false;
00174 } else {
00175 int dec_size = pad_len;
00176 uncipher.zap(dec_size, uncipher.last());
00177 target += uncipher;
00178 }
00179
00180 EVP_CIPHER_CTX_cleanup(&session);
00181 return to_return;
00182 }
00183
00185
00186 int main(int formal(argc), char *formal(argv)[])
00187 {
00188 FUNCDEF("main");
00189 CRYPTO_malloc_debug_init();
00190
00191 CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);
00192
00193 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
00194
00195 RAND_seed(random_seed().observe(), SEED_SIZE);
00196
00197 istring fodder = string_manipulation::make_random_name(MAX_STRING + 1,
00198 MAX_STRING + 1);
00199
00200 time_stamp start;
00201
00202 for (int i = 0; i < TEST_RUNS; i++) {
00203 time_stamp start;
00204 byte_array key;
00205 byte_array iv;
00206 provide_init_vect(iv);
00207 generate_key(KEY_SIZE, key);
00208 int key_durat = int(time_stamp().value() - start.value());
00209
00210 int string_start = rando.inclusive(0, MAX_STRING);
00211 int string_end = rando.inclusive(0, MAX_STRING);
00212 flip_increasing(string_start, string_end);
00213 istring ranstring = fodder.substring(string_start, string_end);
00214
00215
00216 byte_array target;
00217
00218 start.reset();
00219 bool worked = blowfish_encryption(key, iv,
00220 byte_array(ranstring.length() + 1, (byte*)ranstring.s()), target);
00221 int enc_durat = int(time_stamp().value() - start.value());
00222 if (!worked)
00223 deadly_error("blowfish_test", "phase 1", "failed to encrypt the string!");
00224
00225 byte_array recovered;
00226 start.reset();
00227 worked = blowfish_decryption(key, iv, target, recovered);
00228 int dec_durat = int(time_stamp().value() - start.value());
00229 if (!worked)
00230 deadly_error("blowfish_test", "phase 1", "failed to decrypt the string!");
00231
00232
00233
00234 istring teddro = (char *)recovered.observe();
00235
00236
00237 if (teddro != ranstring)
00238 deadly_error(static_class_name(), func, "failed to regenerate the original string!");
00239
00240 printf("key generation: %d ms, encrypt: %d ms, decrypt: %d ms\n",
00241 key_durat, enc_durat, dec_durat);
00242 printf("data size: %d bytes\n", string_end - string_start + 1);
00243 printf("\n");
00244 }
00245
00246 int duration = int(time_stamp().value() - start.value());
00247 printf("duration for %d keys and encrypt/decrypt=%d ms,\n",
00248 TEST_RUNS, duration);
00249 printf("that comes to %d ms per cycle.\n", duration / TEST_RUNS);
00250
00251 CRYPTO_cleanup_all_ex_data();
00252 ERR_remove_state(0);
00253
00254 CRYPTO_mem_leaks_fp(stderr);
00255
00256 return 0;
00257 }
00258
00259 #undef static_class_name
00260