feisty meow concerns codebase  2.140
test_blowfish_crypto.cpp
Go to the documentation of this file.
1 /*
2 * Name : test blowfish encryption
3 * Author : Chris Koeritz
4 * Purpose: Exercises the BlowFish encryption methods in the crypto library.
5 **
6 * Copyright (c) 2005-$now By Author. This program is free software; you can *
7 * redistribute it and/or modify it under the terms of the GNU General Public *
8 * License as published by the Free Software Foundation; either version 2 of *
9 * the License or (at your option) any later version. This is online at: *
10 * http://www.fsf.org/copyleft/gpl.html *
11 * Please send any updates to: fred@gruntose.com *
12 */
13 
15 #include <basis/byte_array.h>
16 #include <basis/astring.h>
17 #include <crypto/blowfish_crypto.h>
18 #include <mathematics/chaos.h>
19 #include <processes/ethread.h>
22 #include <structures/unique_id.h>
23 #include <textual/byte_formatter.h>
25 #include <timely/time_control.h>
26 #include <timely/time_stamp.h>
27 #include <unit_test/unit_base.h>
28 
29 #include <stdio.h>
30 #include <string.h>
31 
32 using namespace application;
33 using namespace basis;
34 using namespace crypto;
35 using namespace filesystem;
36 using namespace loggers;
37 using namespace mathematics;
38 using namespace processes;
39 using namespace structures;
40 using namespace textual;
41 using namespace timely;
42 using namespace unit_test;
43 
44 #define LOG(to_print) EMERGENCY_LOG(program_wide_logger::get(), to_print)
45 
46 #define DEBUG_BLOWFISH
47  // uncomment for noisier run.
48 
49 const int TEST_RUNS_PER_KEY = 5; // encryption test cycles done on each key.
50 
51 const int THREAD_COUNT = 10; // number of threads testing blowfish at once.
52 
53 const int ITERATIONS = 4; // number of test runs in our testing threads.
54 
55 const int MAX_STRING = 20000; // largest chunk that we'll try to encrypt.
56 
58 
59 class test_blowfish; // forward.
60 
61 class blowfish_thread : public ethread
62 {
63 public:
64  blowfish_thread(test_blowfish &parent) : ethread(), _parent(parent) {}
65 
66  void perform_activity(void *ptr);
67  // try out random blowfish keys on randomly chosen chunks of the fodder.
68 
69 private:
70  test_blowfish &_parent;
71 };
72 
74 
75 class test_blowfish : virtual public unit_base, virtual public application_shell
76 {
77 public:
78  test_blowfish()
79  : _fodder(string_manipulation::make_random_name(MAX_STRING + 1, MAX_STRING + 1)) {}
80  DEFINE_CLASS_NAME("test_blowfish");
81 
82  int execute();
83 
84 private:
85  astring _fodder; // chunks taken from this are encrypted and decrypted.
86  time_stamp _program_start; // the time at which we started executing.
87  thread_cabinet _threads; // manages our testing threads.
88  friend class blowfish_thread; // bad practice, but saves time in test app.
89 };
90 
91 int test_blowfish::execute()
92 {
93  FUNCDEF("execute");
94 #ifdef DEBUG_BLOWFISH
95  LOG(astring("starting blowfish test..."));
96 #endif
97  int left = THREAD_COUNT;
98  while (left--) {
99 #ifdef DEBUG_BLOWFISH
100  LOG(a_sprintf("blowfish thread %d starting...", left));
101 #endif
102  _threads.add_thread(new blowfish_thread(*this), true, NULL_POINTER);
103  }
104 
105 #ifdef DEBUG_BLOWFISH
106  LOG(astring("started all threads..."));
107 #endif
108 
109  while (_threads.threads()) {
110 #ifdef DEBUG_BLOWFISH
111  LOG(astring("cleaning debris."));
112 #endif
113  _threads.clean_debris();
114  time_control::sleep_ms(1000);
115  }
116 
117 #ifdef DEBUG_BLOWFISH
118  int duration = int(time_stamp().value() - _program_start.value());
119  LOG(a_sprintf("duration for %d keys and encrypt/decrypt=%d ms,",
120  ITERATIONS * TEST_RUNS_PER_KEY * THREAD_COUNT, duration));
121  LOG(a_sprintf("that comes to %d ms per cycle.\n", int(double(duration
123 #endif
124 
125  return final_report();
126 }
127 
129 
130 #undef UNIT_BASE_THIS_OBJECT
131 #define UNIT_BASE_THIS_OBJECT (*dynamic_cast<unit_base *>(application_shell::single_instance()))
132 
133 void blowfish_thread::perform_activity(void *)
134 {
135  FUNCDEF("perform_activity");
136  int left = ITERATIONS;
137  while (left--) {
138  time_stamp key_start;
139  blowfish_crypto bc(_parent.randomizer().inclusive
140  (blowfish_crypto::minimum_key_size(),
141  blowfish_crypto::maximum_key_size()));
142 #ifdef DEBUG_BLOWFISH
143  LOG(a_sprintf("%d bit key has:", bc.key_size()));
144  astring dumped_key = byte_formatter::text_dump(bc.get_key());
145  LOG(a_sprintf("%s", dumped_key.s()));
146 #endif
147  int key_dur = int(time_stamp().value() - key_start.value());
148 
149 #ifdef DEBUG_BLOWFISH
150  LOG(a_sprintf(" key generation took %d ms", key_dur));
151 #endif
152 
153  for (int i = 0; i < TEST_RUNS_PER_KEY; i++) {
154  byte_array key;
155  byte_array iv;
156 
157  int string_start = _parent.randomizer().inclusive(0, MAX_STRING - 1);
158  int string_end = _parent.randomizer().inclusive(0, MAX_STRING - 1);
159  flip_increasing(string_start, string_end);
160  astring ranstring = _parent._fodder.substring(string_start, string_end);
161 //LOG(a_sprintf("encoding %s\n", ranstring.s());
162 //LOG(a_sprintf("string length encoded: %d\n", ranstring.length());
163 
164  byte_array target;
165 
166  time_stamp test_start;
167  bool worked = bc.encrypt(byte_array(ranstring.length() + 1,
168  (abyte*)ranstring.s()), target);
169  int enc_durat = int(time_stamp().value() - test_start.value());
170  ASSERT_TRUE(worked, "phase 1 should not fail to encrypt the string");
171 
172  byte_array recovered;
173  test_start.reset();
174  worked = bc.decrypt(target, recovered);
175  int dec_durat = int(time_stamp().value() - test_start.value());
176  ASSERT_TRUE(worked, "phase 1 should not fail to decrypt the string");
177 // LOG(a_sprintf("original has %d chars, recovered has %d chars\n",
178 // ranstring.length(), recovered.length() - 1));
179 
180  astring teddro = (char *)recovered.observe();
181 //LOG(a_sprintf("decoded %s\n", teddro.s()));
182 
183 #ifdef DEBUG_BLOWFISH
184  if (teddro != ranstring) {
185  LOG(a_sprintf("error!\toriginal has %d chars, recovered has %d chars\n",
186  ranstring.length(), recovered.length() - 1));
187  LOG(a_sprintf("\tencoded %s\n", ranstring.s()));
188  LOG(a_sprintf("\tdecoded %s\n", teddro.s()));
189  }
190 #endif
191  ASSERT_EQUAL(teddro, ranstring, "should not fail to regenerate the original string");
192 
193 #ifdef DEBUG_BLOWFISH
194  LOG(a_sprintf(" encrypt %d ms, decrypt %d ms, data %d bytes\n",
195  enc_durat, dec_durat, string_end - string_start + 1));
196 #endif
197  time_control::sleep_ms(0); // take a rest.
198  }
199  time_control::sleep_ms(0); // take a rest.
200  }
201 }
202 
203 HOOPLE_MAIN(test_blowfish, )
204 
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
int length() const
Returns the current reported length of the allocated C array.
Definition: array.h:115
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
Provides BlowFish encryption on byte_arrays using the OpenSSL package.
bool decrypt(const basis::byte_array &source, basis::byte_array &target) const
decrypts the "target" array from the encrypted "source" array.
bool encrypt(const basis::byte_array &source, basis::byte_array &target) const
encrypts the "source" array into the "target" array.
const basis::byte_array & get_key() const
returns our current key.
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
const int TEST_RUNS_PER_KEY
#define LOG(to_print)
#define ASSERT_EQUAL(a, b, test_name)
Definition: unit_base.h:38
#define ASSERT_TRUE(a, test_name)
Definition: unit_base.h:46