t_rsa_crypto.cpp

Go to the documentation of this file.
00001 /*****************************************************************************\
00002 *                                                                             *
00003 *  Name   : test RSA public key encryption                                    *
00004 *  Author : Chris Koeritz                                                     *
00005 *                                                                             *
00006 *  Purpose:                                                                   *
00007 *                                                                             *
00008 *    Exercises the RSA encryption functions from the crypto library.          *
00009 *                                                                             *
00010 *******************************************************************************
00011 * Copyright (c) 2005-$now By Author.  This program is free software; you can  *
00012 * redistribute it and/or modify it under the terms of the GNU General Public  *
00013 * License as published by the Free Software Foundation; either version 2 of   *
00014 * the License or (at your option) any later version.  This is online at:      *
00015 *     http://www.fsf.org/copyleft/gpl.html                                    *
00016 * Please send any updates to: fred@gruntose.com                               *
00017 \*****************************************************************************/
00018 
00019 #include <basis/byte_array.h>
00020 #include <basis/chaos.h>
00021 #include <basis/istring.h>
00022 #include <crypto/rsa_crypto.h>
00023 #include <data_struct/unique_id.h>
00024 #include <mechanisms/ithread.h>
00025 #include <mechanisms/time_stamp.h>
00026 #include <mechanisms/thread_cabinet.h>
00027 #include <opsystem/application_shell.h>
00028 #include <data_struct/static_memory_gremlin.h>
00029 #include <textual/byte_format.h>
00030 #include <textual/string_manipulation.h>
00031 
00032 #include <stdio.h>
00033 #include <string.h>
00034 
00035 const int KEY_SIZE = 1024;
00036   // the size of the RSA key that we'll create.
00037 
00039   // the number of cycles of testing.
00040 
00042 
00043 const int MAX_STRING = 100000;
00044   // the largest chunk that we'll try to encrypt.
00045 
00046 const int THREAD_COUNT = 10;  // number of threads testing rsa at once.
00047 
00048 const int ITERATIONS = 32;  // number of test runs in our testing threads.
00049 
00051 
00052 class test_rsa;  // forward.
00053 
00054 class rsa_thread : public ithread
00055 {
00056 public:
00057   rsa_thread(test_rsa &parent) : ithread(), _parent(parent) {}
00058 
00059   void perform_activity(void *ptr);
00060     // try out random rsa keys on randomly chosen chunks of the fodder.
00061 
00062 private:
00063   test_rsa &_parent;
00064 };
00065 
00067 
00068 class test_rsa : public application_shell
00069 {
00070 public:
00071   test_rsa()
00072       : application_shell(static_class_name()),
00073        _fodder(string_manipulation::make_random_name
00074             (MAX_STRING + 1, MAX_STRING + 1)) {}
00075   virtual ~test_rsa() {}
00076   IMPLEMENT_CLASS_NAME("test_rsa");
00077 
00078   const istring &fodder() const { return _fodder; }
00079 
00080   int execute();
00081 
00082 private:
00083   istring _fodder;  // chunks taken from this are encrypted and decrypted.
00084   time_stamp _program_start;  // the time at which we started executing.
00085   thread_cabinet _threads;  // manages our testing threads.
00086   friend class rsa_thread;  // bad practice, but saves time in test app.
00087 };
00088 
00089 int test_rsa::execute()
00090 {
00091   FUNCDEF("execute");
00092   int left = THREAD_COUNT;
00093   while (left--) {
00094     _threads.add_thread(new rsa_thread(*this), true, NIL);
00095   }
00096 
00097   while (_threads.threads()) {
00098 printf("cleaning debris.\n");
00099     _threads.clean_debris();
00100     portable::sleep_ms(1000);
00101   }
00102 
00103   int duration = int(time_stamp().value() - _program_start.value());
00104   printf("duration for %d keys and encrypt/decrypt=%d ms,\n",
00105       ITERATIONS * THREAD_COUNT, duration);
00106   printf("that comes to %d ms per cycle.\n", int(double(duration
00107       / ITERATIONS / THREAD_COUNT)));
00108 
00109   return 0;
00110 }
00111 
00113 
00114 void rsa_thread::perform_activity(void *)
00115 {
00116   FUNCDEF("perform_activity");
00117   int left = ITERATIONS;
00118   while (left--) {
00119     time_stamp start;
00120 
00121     RSA_crypto rc_private_here(KEY_SIZE);
00122     int key_durat = int(time_stamp().value() - start.value());
00123 
00124     byte_array public_key;
00125     rc_private_here.public_key(public_key);  // get our public portion.
00126     byte_array private_key;
00127     rc_private_here.private_key(private_key);  // get our private portion.
00128 
00129 //RSA_print_fp(stdout, private_key, 0);
00130 //RSA_print_fp(stdout, public_key, 0);
00131 
00132     int string_start = _parent.randomizer().inclusive(0, MAX_STRING);
00133     int string_end = _parent.randomizer().inclusive(0, MAX_STRING);
00134     flip_increasing(string_start, string_end);
00135     istring ranstring = _parent.fodder().substring(string_start, string_end);
00136     byte_array target;
00137 
00138     // the first phase tests the outsiders sending back data that only we,
00139     // with our private key, can decrypt.
00140 
00141     start.reset();
00142     RSA_crypto rc_pub(public_key);
00143     bool worked = rc_pub.public_encrypt(byte_array(ranstring.length() + 1,
00144         (byte*)ranstring.s()), target);
00145     int pub_enc_durat = int(time_stamp().value() - start.value());
00146     if (!worked)
00147       deadly_error("rsa_test", "phase 1", "failed to encrypt the string!\n");
00148 
00149     RSA_crypto rc_priv(private_key);
00150     byte_array recovered;
00151     start.reset();
00152     worked = rc_priv.private_decrypt(target, recovered);
00153     int priv_dec_durat = int(time_stamp().value() - start.value());
00154     if (!worked)
00155       deadly_error("rsa_test", "phase 1", "failed to decrypt the string!\n");
00156 
00157     istring teddro = (char *)recovered.observe();
00158 
00159     if (teddro != ranstring)
00160       printf("failed to get back the data!\n");
00161 
00162     // the second phase tests us using our private key to encrypt data which
00163     // anyone with the public key can decode.
00164 
00165     start.reset();
00166     worked = rc_priv.private_encrypt(byte_array(ranstring.length() + 1,
00167         (byte*)ranstring.s()), target);
00168     int priv_enc_durat = int(time_stamp().value() - start.value());
00169     if (!worked)
00170       deadly_error("rsa_test", "phase 2", "failed to encrypt the string!\n");
00171 
00172     start.reset();
00173     worked = rc_pub.public_decrypt(target, recovered);
00174     int pub_dec_durat = int(time_stamp().value() - start.value());
00175     if (!worked)
00176       deadly_error("rsa_test", "phase 2", "failed to decrypt the string!\n");
00177 
00178     teddro = (char *)recovered.observe();
00179 
00180     if (teddro != ranstring)
00181       printf("failed to get back the data!\n");
00182 
00183     printf("key generation: %d ms, public encrypt: %d ms, private "
00184         "decrypt: %d ms\n", key_durat, pub_enc_durat, priv_dec_durat);
00185     printf("data size: %d bytes, private encrypt: %d ms, public "
00186         "decrypt: %d ms\n",
00187         string_end - string_start + 1, priv_enc_durat, pub_dec_durat);
00188     printf("\n");
00189 
00190     portable::sleep_ms(0);  // take a rest.
00191   }
00192 }
00193 
00194 HOOPLE_MAIN(test_rsa, )
00195 

Generated on Fri Nov 28 04:29:36 2008 for HOOPLE Libraries by  doxygen 1.5.1