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/crypto.h>
00028 #include <openssl/err.h>
00029 #include <openssl/rand.h>
00030
00031 #include <openssl/rsa.h>
00032
00033 #include <stdio.h>
00034 #include <string.h>
00035
00036 HOOPLE_STARTUP_CODE;
00037
00038 const int KEY_SIZE = 1024;
00039
00040
00041 const int TEST_RUNS = 100;
00042
00043
00044 const int SEED_SIZE = 100;
00045
00046
00047 const int MAX_STRING = 100000;
00048
00049
00050 chaos rando;
00051
00052 RSA *generate_key()
00053 {
00054 RSA *to_return = RSA_generate_key(512, 65537, NIL, NIL);
00055 if (!to_return) {
00056 printf("failed to generate a key\n");
00057 return NIL;
00058 }
00059
00060 int check = RSA_check_key(to_return);
00061 if (check != 1) {
00062 printf("failed to check the key\n");
00063 return NIL;
00064 }
00065 return to_return;
00066 }
00067
00068 const byte_array &random_seed()
00069 {
00070 static byte_array seed;
00071 static bool initted = false;
00072 if (!initted) {
00073 for (int i = 0; i < SEED_SIZE; i++) {
00074 seed += byte(rando.inclusive(0, 255));
00075 }
00076 initted = true;
00077 }
00078 return seed;
00079 }
00080
00081
00082
00083
00085
00086
00087
00088
00089
00090 bool rsa_public_encryption(RSA *key, const byte_array &source,
00091 byte_array &target)
00092 {
00093 target.reset();
00094 const int max_chunk = RSA_size(key) - 12;
00095
00096
00097 byte_array cipher(RSA_size(key));
00098 for (int i = 0; i < source.length(); i += max_chunk) {
00099 int edge = i + max_chunk - 1;
00100 if (edge > source.last())
00101 edge = source.last();
00102
00103 int next_chunk = edge - i + 1;
00104 RSA_public_encrypt(next_chunk, &source[i],
00105 cipher.access(), key, RSA_PKCS1_PADDING);
00106 target += cipher;
00107 }
00108 return true;
00109 }
00110
00111 bool rsa_private_decryption(RSA *key, const byte_array &source,
00112 byte_array &target)
00113 {
00114 target.reset();
00115 const int max_chunk = RSA_size(key);
00116
00117
00118 byte_array uncipher(max_chunk);
00119 for (int i = 0; i < source.length(); i += max_chunk) {
00120 int edge = i + max_chunk - 1;
00121 if (edge > source.last())
00122 edge = source.last();
00123 int next_chunk = edge - i + 1;
00124
00125 int dec_size = RSA_private_decrypt(next_chunk, &source[i],
00126 uncipher.access(), key, RSA_PKCS1_PADDING);
00127
00128 if (dec_size < 0) return false;
00129 uncipher.zap(dec_size, uncipher.last());
00130 target += uncipher;
00131 uncipher.reset(max_chunk);
00132 }
00133 return true;
00134 }
00135
00137
00138
00139
00140
00141
00142 bool rsa_private_encryption(RSA *key, const byte_array &source,
00143 byte_array &target)
00144 {
00145 target.reset();
00146 const int max_chunk = RSA_size(key) - 12;
00147
00148
00149 byte_array cipher(RSA_size(key));
00150 for (int i = 0; i < source.length(); i += max_chunk) {
00151 int edge = i + max_chunk - 1;
00152 if (edge > source.last())
00153 edge = source.last();
00154
00155 int next_chunk = edge - i + 1;
00156 RSA_private_encrypt(next_chunk, &source[i],
00157 cipher.access(), key, RSA_PKCS1_PADDING);
00158 target += cipher;
00159 }
00160 return true;
00161 }
00162
00163 bool rsa_public_decryption(RSA *key, const byte_array &source,
00164 byte_array &target)
00165 {
00166 target.reset();
00167 const int max_chunk = RSA_size(key);
00168
00169
00170 byte_array uncipher(max_chunk);
00171 for (int i = 0; i < source.length(); i += max_chunk) {
00172 int edge = i + max_chunk - 1;
00173 if (edge > source.last())
00174 edge = source.last();
00175 int next_chunk = edge - i + 1;
00176
00177 int dec_size = RSA_public_decrypt(next_chunk, &source[i],
00178 uncipher.access(), key, RSA_PKCS1_PADDING);
00179
00180 if (dec_size < 0) return false;
00181 uncipher.zap(dec_size, uncipher.last());
00182 target += uncipher;
00183 uncipher.reset(max_chunk);
00184 }
00185 return true;
00186 }
00187
00189
00190 int main(int formal(argc), char *formal(argv)[])
00191 {
00192 CRYPTO_malloc_debug_init();
00193
00194 CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);
00195
00196 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
00197
00198 RAND_seed(random_seed().observe(), SEED_SIZE);
00199
00200 time_stamp start;
00201
00202 istring fodder = string_manipulation::make_random_name(MAX_STRING + 1,
00203 MAX_STRING + 1);
00204
00205 for (int i = 0; i < TEST_RUNS; i++) {
00206 time_stamp start;
00207 RSA *private_key = generate_key();
00208 int key_durat = int(time_stamp().value() - start.value());
00209
00210 RSA *public_key = RSAPublicKey_dup(private_key);
00211
00212
00213
00214
00215
00216 int string_start = rando.inclusive(0, MAX_STRING);
00217 int string_end = rando.inclusive(0, MAX_STRING);
00218 flip_increasing(string_start, string_end);
00219 istring ranstring = fodder.substring(string_start, string_end);
00220 byte_array target;
00221
00222
00223
00224
00225 start.reset();
00226 bool worked = rsa_public_encryption(public_key,
00227 byte_array(ranstring.length() + 1, (byte*)ranstring.s()), target);
00228 int pub_enc_durat = int(time_stamp().value() - start.value());
00229 if (!worked)
00230 deadly_error("rsa_test", "phase 1", "failed to encrypt the string!\n");
00231
00232 byte_array recovered;
00233 start.reset();
00234 worked = rsa_private_decryption(private_key, target, recovered);
00235 int priv_dec_durat = int(time_stamp().value() - start.value());
00236 if (!worked)
00237 deadly_error("rsa_test", "phase 1", "failed to decrypt the string!\n");
00238
00239 istring teddro = (char *)recovered.observe();
00240
00241 if (teddro != ranstring)
00242 printf("failed to get back the data!\n");
00243
00244
00245
00246
00247 start.reset();
00248 worked = rsa_private_encryption(private_key,
00249 byte_array(ranstring.length() + 1, (byte*)ranstring.s()), target);
00250 int priv_enc_durat = int(time_stamp().value() - start.value());
00251 if (!worked)
00252 deadly_error("rsa_test", "phase 2", "failed to encrypt the string!\n");
00253
00254 start.reset();
00255 worked = rsa_public_decryption(public_key, target, recovered);
00256 int pub_dec_durat = int(time_stamp().value() - start.value());
00257 if (!worked)
00258 deadly_error("rsa_test", "phase 2", "failed to decrypt the string!\n");
00259
00260 teddro = (char *)recovered.observe();
00261
00262 if (teddro != ranstring)
00263 printf("failed to get back the data!\n");
00264
00265 printf("key generation: %d ms, public encrypt: %d ms, private "
00266 "decrypt: %d ms\n", key_durat, pub_enc_durat, priv_dec_durat);
00267 printf("data size: %d bytes, private encrypt: %d ms, public "
00268 "decrypt: %d ms\n",
00269 string_end - string_start + 1, priv_enc_durat, pub_dec_durat);
00270 printf("\n");
00271
00272 RSA_free(public_key);
00273 RSA_free(private_key);
00274 }
00275
00276 int duration = int(time_stamp().value() - start.value());
00277 printf("duration for %d keys and encrypt/decrypt=%d ms,\n",
00278 TEST_RUNS, duration);
00279 printf("that comes to %d ms per cycle.\n", duration / TEST_RUNS);
00280
00281 CRYPTO_cleanup_all_ex_data();
00282 ERR_remove_state(0);
00283
00284 CRYPTO_mem_leaks_fp(stderr);
00285
00286 return 0;
00287 }
00288