feisty meow concerns codebase 2.140
test_twofish_crypto.cpp
Go to the documentation of this file.
1/*
2* Name : test twofish 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>
18#include <mathematics/chaos.h>
19#include <processes/ethread.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
32using namespace application;
33using namespace basis;
34using namespace crypto;
35using namespace filesystem;
36using namespace loggers;
37using namespace mathematics;
38using namespace processes;
39using namespace structures;
40using namespace textual;
41using namespace timely;
42using namespace unit_test;
43
44#define LOG(to_print) EMERGENCY_LOG(program_wide_logger::get(), astring(to_print))
45
46#define DEBUG_TWOFISH
47 // uncomment for noisier run.
48
49const int TEST_RUNS_PER_KEY = 42; // encryption test cycles done on each key.
50
51const int THREAD_COUNT = 10; // number of threads testing twofish at once.
52
53const int ITERATIONS = 64; // number of test runs in our testing threads.
54
55const int MAX_STRING = 64 * KILOBYTE; // largest chunk that we'll try to encrypt.
56
58
59class test_twofish; // forward.
60
61class twofish_thread : public ethread
62{
63public:
64 twofish_thread(test_twofish &parent) : ethread(), _parent(parent) {}
65
66 void perform_activity(void *ptr);
67 // try out random twofish keys on randomly chosen chunks of the fodder.
68
69private:
70 test_twofish &_parent;
71};
72
74
75class test_twofish : virtual public unit_base, virtual public application_shell
76{
77public:
78 test_twofish()
79 : _fodder(string_manipulation::make_random_name(MAX_STRING + 1, MAX_STRING + 1)) {}
80 DEFINE_CLASS_NAME("test_twofish");
81
82 int execute();
83
84private:
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 twofish_thread; // bad practice, but saves time in test app.
89};
90
91int test_twofish::execute()
92{
93 FUNCDEF("execute");
94#ifdef DEBUG_TWOFISH
95 LOG("starting twofish test...");
96#endif
97 int left = THREAD_COUNT;
98 while (left--) {
99#ifdef DEBUG_TWOFISH
100 LOG(a_sprintf("twofish thread %d starting...", left));
101#endif
102 _threads.add_thread(new twofish_thread(*this), true, NULL_POINTER);
103 }
104
105#ifdef DEBUG_TWOFISH
106 LOG("started all threads...");
107#endif
108
109 while (_threads.threads()) {
110#ifdef DEBUG_TWOFISH
111 LOG("periodic debris cleaning.");
112#endif
113 _threads.clean_debris();
115 }
116
117 int duration = int(time_stamp().value() - _program_start.value());
118 LOG(a_sprintf("duration for %d keys and encrypt/decrypt=%d ms,",
120 LOG(a_sprintf("that comes to %d ms per cycle.", int(double(duration
122
123 return final_report();
124}
125
127
128#undef UNIT_BASE_THIS_OBJECT
129#define UNIT_BASE_THIS_OBJECT (*dynamic_cast<unit_base *>(application_shell::single_instance()))
130
131void twofish_thread::perform_activity(void *)
132{
133 FUNCDEF("perform_activity");
134 int left = ITERATIONS;
135 while (left--) {
136 time_stamp key_start;
138#ifdef DEBUG_TWOFISH
139 LOG(a_sprintf("%d bit key has:", tc.key_size()));
140 astring dumped_key = byte_formatter::text_dump(tc.get_key());
141 LOG(a_sprintf("%s", dumped_key.s()));
142#endif
143 int key_dur = int(time_stamp().value() - key_start.value());
144#ifdef DEBUG_TWOFISH
145 LOG(a_sprintf(" key generation took %d ms", key_dur));
146#endif
147
148 for (int i = 0; i < TEST_RUNS_PER_KEY; i++) {
151LOG(a_sprintf("test run %d on this key.", i+1));
152 int string_start = _parent.randomizer().inclusive(0, MAX_STRING - 1);
153 int string_end = _parent.randomizer().inclusive(0, MAX_STRING - 1);
154 flip_increasing(string_start, string_end);
155 astring ranstring = _parent._fodder.substring(string_start, string_end);
156#ifdef DEBUG_TWOFISH
157// LOG(a_sprintf("encoding %s", ranstring.s()));
158// LOG(a_sprintf("string length encoded: %d", ranstring.length()));
159#endif
160
161 byte_array target;
162 time_stamp test_start;
163 bool worked = tc.encrypt(byte_array(ranstring.length() + 1, (abyte*)ranstring.s()), target);
164 int enc_durat = int(time_stamp().value() - test_start.value());
165 ASSERT_TRUE(worked, "phase 1 should not fail to encrypt the string");
166
167 byte_array recovered;
168 test_start.reset();
169 worked = tc.decrypt(target, recovered);
170 int dec_durat = int(time_stamp().value() - test_start.value());
171 ASSERT_TRUE(worked, "phase 1 should not fail to decrypt the string");
172#ifdef DEBUG_TWOFISH
173 astring jammer_piece = a_sprintf("--\noriginal has %d chars, recovered has %d chars",
174 ranstring.length(), recovered.length() - 1);
175#endif
176
177 astring teddro = (char *)recovered.observe();
178#ifdef DEBUG_TWOFISH
179// LOG(a_sprintf("decoded %s", teddro.s()));
180#endif
181
182#ifdef DEBUG_TWOFISH
183 if (teddro != ranstring) {
184 LOG(a_sprintf("error!\toriginal has %d chars, recovered has %d chars",
185 ranstring.length(), recovered.length() - 1));
186 LOG(a_sprintf("\tencoded %s", ranstring.s()));
187 LOG(a_sprintf("\tdecoded %s", teddro.s()));
188 }
189#endif
190 ASSERT_EQUAL(teddro, ranstring, "should not fail to regenerate the original string");
191
192#ifdef DEBUG_TWOFISH
193 LOG(a_sprintf("%s\nencrypt %d ms, decrypt %d ms, data %d bytes",
194 jammer_piece.s(), enc_durat, dec_durat, string_end - string_start + 1));
195#endif
196 time_control::sleep_ms(0); // take a rest.
197 }
198 time_control::sleep_ms(0); // take a rest.
199 }
200}
201
202HOOPLE_MAIN(test_twofish, )
203
204
The application_shell is a base object for console programs.
virtual int execute()=0
< retrieves the command line from the /proc hierarchy on linux.
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:868
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
bool encrypt(const basis::byte_array &source, basis::byte_array &target) const
encrypts the "source" array into the "target" array.
bool decrypt(const basis::byte_array &source, basis::byte_array &target) const
decrypts the "target" array from the encrypted "source" array.
const basis::byte_array & get_key() const
returns our current key.
static int static_maximum_key_size_in_bits()
static int static_minimum_key_size_in_bits()
Provides a platform-independent object for adding threads to a program.
Definition ethread.h:36
virtual void perform_activity(void *thread_data)=0
< invoked just after after start(), when the OS thread is created.
Manages a collection of threads.
static void text_dump(basis::astring &output, const basis::abyte *location, basis::un_int length, basis::un_int label=0, const char *eol="\n")
prints out a block of memory in a human readable form.
Provides various functions for massaging strings.
static void sleep_ms(basis::un_int msec)
a system independent name for a forced snooze measured in milliseconds.
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.
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:42
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
Definition enhance_cpp.h:54
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
const int KILOBYTE
Number of bytes in a kilobyte.
A platform independent way to obtain the timestamp of a file.
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>
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