aboutsummaryrefslogtreecommitdiffstats
path: root/doc/examples/rng_test.cpp
diff options
context:
space:
mode:
authorlloyd <lloyd@randombit.net>2008-09-18 01:03:19 +0000
committerlloyd <lloyd@randombit.net>2008-09-18 01:03:19 +0000
commit57789ce48e65ed83244130b077aa35a6696feab9 (patch)
tree5e0a26887f1d26a031100a17e8a953024b9b10e9 /doc/examples/rng_test.cpp
parentf07f1e4779c8721e7623188a770614bea6dd8877 (diff)
Add a program that checks the X9.31 PRNG against a set of NIST test vectors
Diffstat (limited to 'doc/examples/rng_test.cpp')
-rw-r--r--doc/examples/rng_test.cpp134
1 files changed, 134 insertions, 0 deletions
diff --git a/doc/examples/rng_test.cpp b/doc/examples/rng_test.cpp
new file mode 100644
index 000000000..0a245ca9e
--- /dev/null
+++ b/doc/examples/rng_test.cpp
@@ -0,0 +1,134 @@
+#include <botan/botan.h>
+#include <botan/x931_rng.h>
+#include <botan/filters.h>
+
+#include <iostream>
+#include <fstream>
+#include <boost/algorithm/string.hpp>
+#include <stdexcept>
+
+using namespace Botan;
+
+std::vector<std::pair<std::string, std::string> > read_file(const std::string&);
+
+SecureVector<byte> decode_hex(const std::string& in)
+ {
+ SecureVector<byte> result;
+
+ try {
+ Botan::Pipe pipe(new Botan::Hex_Decoder);
+ pipe.process_msg(in);
+ result = pipe.read_all();
+ }
+ catch(std::exception& e)
+ {
+ result.destroy();
+ }
+ return result;
+ }
+
+std::string hex_encode(const byte in[], u32bit len)
+ {
+ Botan::Pipe pipe(new Botan::Hex_Encoder);
+ pipe.process_msg(in, len);
+ return pipe.read_all_as_string();
+ }
+
+class Fixed_Output_RNG : public RandomNumberGenerator
+ {
+ public:
+ bool is_seeded() const { return !buf.empty(); }
+
+ byte random()
+ {
+ if(buf.empty())
+ throw std::runtime_error("Out of bytes");
+
+ byte out = buf.front();
+ buf.pop_front();
+ return out;
+ }
+
+ void randomize(byte out[], u32bit len) throw()
+ {
+ for(u32bit j = 0; j != len; j++)
+ out[j] = random();
+ }
+
+ std::string name() const { return "Fixed_Output_RNG"; }
+
+ void clear() throw() {}
+
+ void add_randomness(const byte in[], u32bit len) throw()
+ {
+ buf.insert(buf.end(), in, in + len);
+ }
+
+ Fixed_Output_RNG() {}
+ private:
+ std::deque<byte> buf;
+ };
+
+void x931_tests(std::vector<std::pair<std::string, std::string> > vecs,
+ const std::string& cipher)
+ {
+ for(size_t j = 0; j != vecs.size(); ++j)
+ {
+ const std::string result = vecs[j].first;
+ const std::string input = vecs[j].second;
+
+ ANSI_X931_RNG prng(cipher, new Fixed_Output_RNG);
+
+ SecureVector<byte> x = decode_hex(input);
+ prng.add_entropy(x.begin(), x.size());
+
+ SecureVector<byte> output(result.size() / 2);
+ prng.randomize(output, output.size());
+
+ if(decode_hex(result) != output)
+ std::cout << "FAIL";
+ else
+ std::cout << "PASS";
+
+ std::cout << " Seed " << input << " "
+ << "Got " << hex_encode(output, output.size()) << " "
+ << "Exp " << result << "\n";
+ }
+
+ }
+
+int main()
+ {
+ x931_tests(read_file("ANSI931_AES128VST.txt.vst"), "AES-128");
+ x931_tests(read_file("ANSI931_AES192VST.txt.vst"), "AES-192");
+ x931_tests(read_file("ANSI931_AES256VST.txt.vst"), "AES-256");
+ x931_tests(read_file("ANSI931_TDES2VST.txt.vst"), "TripleDES");
+ x931_tests(read_file("ANSI931_TDES3VST.txt.vst"), "TripleDES");
+ }
+
+
+std::vector<std::pair<std::string, std::string> > read_file(const std::string& fsname)
+ {
+ std::ifstream in(fsname.c_str());
+
+ std::vector<std::pair<std::string, std::string> > out;
+
+ while(in.good())
+ {
+ std::string line;
+ std::getline(in, line);
+
+ if(line == "")
+ break;
+
+ std::vector<std::string> l;
+ boost::split(l, line, boost::is_any_of(":"));
+
+ if(l.size() != 2)
+ throw std::runtime_error("Bad line " + line);
+
+ out.push_back(std::make_pair(l[0], l[1]));
+ }
+
+ return out;
+ }