feisty meow concerns codebase  2.140
test_rsa_crypto.cpp
Go to the documentation of this file.
1 /*
2 * Name : test RSA public key encryption
3 * Author : Chris Koeritz
4 * Purpose:
5 * Exercises the RSA encryption functions from the crypto library.
6 **
7 * Copyright (c) 2005-$now By Author. This program is free software; you can *
8 * redistribute it and/or modify it under the terms of the GNU General Public *
9 * License as published by the Free Software Foundation; either version 2 of *
10 * the License or (at your option) any later version. This is online at: *
11 * http://www.fsf.org/copyleft/gpl.html *
12 * Please send any updates to: fred@gruntose.com *
13 */
14 
16 #include <basis/byte_array.h>
17 #include <basis/astring.h>
18 #include <crypto/rsa_crypto.h>
19 #include <mathematics/chaos.h>
20 #include <processes/ethread.h>
23 #include <structures/unique_id.h>
24 #include <textual/byte_formatter.h>
26 #include <timely/time_control.h>
27 #include <timely/time_stamp.h>
28 #include <unit_test/unit_base.h>
29 
30 #include <stdio.h>
31 #include <string.h>
32 
33 using namespace application;
34 using namespace basis;
35 using namespace crypto;
36 using namespace filesystem;
37 using namespace loggers;
38 using namespace mathematics;
39 using namespace processes;
40 using namespace structures;
41 using namespace textual;
42 using namespace timely;
43 using namespace unit_test;
44 
45 //#define DEBUG_RSA_CRYPTO
46  // uncomment for noisy run.
47 
48 #define LOG(to_print) EMERGENCY_LOG(program_wide_logger::get(), to_print)
49 
50 const int KEY_SIZE = 1024;
51  // the size of the RSA key that we'll create.
52 
53 const int MAX_STRING = 4000;
54  // the largest chunk that we'll try to encrypt.
55 
56 const int THREAD_COUNT = 5; // number of threads testing rsa at once.
57 
58 const int ITERATIONS = 6; // number of test runs in our testing threads.
59 
61 
62 class test_rsa; // forward.
63 
64 class rsa_thread : public ethread
65 {
66 public:
67  rsa_thread(test_rsa &parent) : ethread(), _parent(parent) {}
68 
69  void perform_activity(void *ptr);
70  // try out random rsa keys on randomly chosen chunks of the fodder.
71 
72 private:
73  test_rsa &_parent;
74 };
75 
77 
78 class test_rsa : public virtual unit_base, virtual public application_shell
79 {
80 public:
81  test_rsa()
82  : _fodder(string_manipulation::make_random_name(MAX_STRING + 1, MAX_STRING + 1)) {}
83  virtual ~test_rsa() {}
84  DEFINE_CLASS_NAME("test_rsa");
85 
86  const astring &fodder() const { return _fodder; }
87 
88  int execute();
89 
90 private:
91  astring _fodder; // chunks taken from this are encrypted and decrypted.
92  time_stamp _program_start; // the time at which we started executing.
93  thread_cabinet _threads; // manages our testing threads.
94  friend class rsa_thread; // bad practice, but saves time in test app.
95 };
96 
97 int test_rsa::execute()
98 {
99  FUNCDEF("execute");
100  int left = THREAD_COUNT;
101  while (left--) {
102  _threads.add_thread(new rsa_thread(*this), true, NULL_POINTER);
103  }
104 
105  while (_threads.threads()) {
106 #ifdef DEBUG_RSA_CRYPTO
107  LOG(astring("cleaning debris."));
108 #endif
109  _threads.clean_debris();
110 #ifdef DEBUG_RSA_CRYPTO
111  LOG(astring("after cleaning debris."));
112 #endif
113  time_control::sleep_ms(1000);
114  }
115 
116 #ifdef DEBUG_RSA_CRYPTO
117  int duration = int(time_stamp().value() - _program_start.value());
118  LOG(a_sprintf("duration for %d keys and encrypt/decrypt=%d ms,",
119  ITERATIONS * THREAD_COUNT, duration));
120  LOG(a_sprintf("that comes to %d ms per cycle.", int(double(duration
121  / ITERATIONS / THREAD_COUNT))));
122 #endif
123 
124  return final_report();
125 }
126 
128 
129 #undef UNIT_BASE_THIS_OBJECT
130 #define UNIT_BASE_THIS_OBJECT (*dynamic_cast<unit_base *>(application_shell::single_instance()))
131 
132 void rsa_thread::perform_activity(void *)
133 {
134  FUNCDEF("perform_activity");
135  int left = ITERATIONS;
136  while (left--) {
137  time_stamp start;
138 
139  rsa_crypto rc_private_here(KEY_SIZE);
140  int key_durat = int(time_stamp().value() - start.value());
141 
142  byte_array public_key;
143  rc_private_here.public_key(public_key); // get our public portion.
144  byte_array private_key;
145  rc_private_here.private_key(private_key); // get our private portion.
146 
147 //RSA_print_fp(stdout, private_key, 0);
148 //RSA_print_fp(stdout, public_key, 0);
149 
150  int string_start = _parent.randomizer().inclusive(0, MAX_STRING);
151  int string_end = _parent.randomizer().inclusive(0, MAX_STRING);
152  flip_increasing(string_start, string_end);
153  astring ranstring = _parent.fodder().substring(string_start, string_end);
154  byte_array target;
155 
156  // the first phase tests the outsiders sending back data that only we,
157  // with our private key, can decrypt.
158 
159  start.reset();
160  rsa_crypto rc_pub(public_key);
161  bool worked = rc_pub.public_encrypt(byte_array(ranstring.length() + 1,
162  (abyte*)ranstring.s()), target);
163  int pub_enc_durat = int(time_stamp().value() - start.value());
164  ASSERT_TRUE(worked, "phase 1 shouldn't fail to encrypt the string");
165 
166  rsa_crypto rc_priv(private_key);
167  byte_array recovered;
168  start.reset();
169  worked = rc_priv.private_decrypt(target, recovered);
170  int priv_dec_durat = int(time_stamp().value() - start.value());
171  ASSERT_TRUE(worked, "phase 1 should not fail to decrypt the string");
172 
173  astring teddro = (char *)recovered.observe();
174 
175  ASSERT_EQUAL(teddro, ranstring, "should not fail to get back the data");
176 
177  // the second phase tests us using our private key to encrypt data which
178  // anyone with the public key can decode.
179 
180  start.reset();
181  worked = rc_priv.private_encrypt(byte_array(ranstring.length() + 1,
182  (abyte*)ranstring.s()), target);
183  int priv_enc_durat = int(time_stamp().value() - start.value());
184  ASSERT_TRUE(worked, "phase 2 should not fail to encrypt the string");
185 
186  start.reset();
187  worked = rc_pub.public_decrypt(target, recovered);
188  int pub_dec_durat = int(time_stamp().value() - start.value());
189  ASSERT_TRUE(worked, "phase 2 should not fail to decrypt the string");
190 
191  teddro = (char *)recovered.observe();
192 
193  ASSERT_EQUAL(teddro, ranstring, "should not fail to get back the data here either");
194 
195 #ifdef DEBUG_RSA_CRYPTO
196  LOG(a_sprintf("key generation: %d ms, public encrypt: %d ms, private "
197  "decrypt: %d ms", key_durat, pub_enc_durat, priv_dec_durat));
198  LOG(a_sprintf("data size: %d bytes, private encrypt: %d ms, public "
199  "decrypt: %d ms",
200  string_end - string_start + 1, priv_enc_durat, pub_dec_durat));
201 #endif
202 
203  time_control::sleep_ms(0); // take a rest.
204  }
205 }
206 
207 HOOPLE_MAIN(test_rsa, )
208 
The application_shell is a base object for console programs.
a_sprintf is a specialization of astring that provides printf style support.
Definition: astring.h:440
const contents * observe() const
Returns a pointer to the underlying C array of data.
Definition: array.h:172
Provides a dynamically resizable ASCII character string.
Definition: astring.h:35
const char * s() const
synonym for observe. the 's' stands for "string", if that helps.
Definition: astring.h:113
bool substring(astring &target, int start, int end) const
a version that stores the substring in an existing "target" string.
Definition: astring.cpp:865
int length() const
Returns the current length of the string.
Definition: astring.cpp:132
A very common template for a dynamic array of bytes.
Definition: byte_array.h:36
Supports public key encryption and decryption.
Definition: rsa_crypto.h:33
bool public_encrypt(const basis::byte_array &source, basis::byte_array &target) const
encrypts "source" using our public key and stores it in "target".
Definition: rsa_crypto.cpp:313
bool private_key(basis::byte_array &privkey) const
makes a copy of the private key held here.
Definition: rsa_crypto.cpp:269
bool private_decrypt(const basis::byte_array &source, basis::byte_array &target) const
decrypts "source" using our private key and stores it in "target".
Definition: rsa_crypto.cpp:336
bool public_decrypt(const basis::byte_array &source, basis::byte_array &target) const
decrypts "source" using our public key and stores it in "target".
Definition: rsa_crypto.cpp:385
bool private_encrypt(const basis::byte_array &source, basis::byte_array &target) const
encrypts "source" using our private key and stores it in "target".
Definition: rsa_crypto.cpp:362
bool public_key(basis::byte_array &pubkey) const
makes a copy of the public key held here.
Definition: rsa_crypto.cpp:245
Provides a platform-independent object for adding threads to a program.
Definition: ethread.h:36
Manages a collection of threads.
Provides various functions for massaging strings.
Represents a point in time relative to the operating system startup time.
Definition: time_stamp.h:38
void reset()
sets the stamp time back to now.
Definition: time_stamp.cpp:59
time_representation value() const
returns the time_stamp in terms of the lower level type.
Definition: time_stamp.h:61
#define NULL_POINTER
The value representing a pointer to nothing.
Definition: definitions.h:32
#define DEFINE_CLASS_NAME(objname)
Defines the name of a class by providing a couple standard methods.
Definition: enhance_cpp.h:45
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
Definition: enhance_cpp.h:57
Provides macros that implement the 'main' program of an application.
#define HOOPLE_MAIN(obj_name, obj_args)
options that should work for most unix and linux apps.
Definition: hoople_main.h:61
Implements an application lock to ensure only one is running at once.
The guards collection helps in testing preconditions and reporting errors.
Definition: array.h:30
unsigned char abyte
A fairly important unit which is seldom defined...
Definition: definitions.h:51
void flip_increasing(type &a, type &b)
Makes sure that two values are in increasing order (a < b).
Definition: functions.h:95
A platform independent way to obtain the timestamp of a file.
Definition: byte_filer.cpp:37
A logger that sends to the console screen using the standard output device.
An extension to floating point primitives providing approximate equality.
Definition: averager.h:21
A dynamic container class that holds any kind of object via pointers.
Definition: amorph.h:55
#include <time.h>
Definition: earth_time.cpp:37
Useful support functions for unit testing, especially within hoople.
Definition: unit_base.cpp:35
const int ITERATIONS
const int MAX_STRING
const int THREAD_COUNT
#define LOG(to_print)
const int KEY_SIZE
#define ASSERT_EQUAL(a, b, test_name)
Definition: unit_base.h:38
#define ASSERT_TRUE(a, test_name)
Definition: unit_base.h:46