diff options
author | lloyd <lloyd@randombit.net> | 2008-09-18 01:03:19 +0000 |
---|---|---|
committer | lloyd <lloyd@randombit.net> | 2008-09-18 01:03:19 +0000 |
commit | 57789ce48e65ed83244130b077aa35a6696feab9 (patch) | |
tree | 5e0a26887f1d26a031100a17e8a953024b9b10e9 /doc/examples/rng_test.cpp | |
parent | f07f1e4779c8721e7623188a770614bea6dd8877 (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.cpp | 134 |
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; + } |