diff options
Diffstat (limited to 'doc/examples/eax_test.cpp')
-rw-r--r-- | doc/examples/eax_test.cpp | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/doc/examples/eax_test.cpp b/doc/examples/eax_test.cpp new file mode 100644 index 000000000..32311800d --- /dev/null +++ b/doc/examples/eax_test.cpp @@ -0,0 +1,251 @@ +/* +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <fstream> +#include <iostream> +#include <sstream> +#include <boost/regex.hpp> + +#include <botan/botan.h> +#include <botan/eax.h> + +using namespace Botan; + +namespace { + +unsigned from_string(const std::string& s) + { + std::istringstream stream(s); + unsigned n; + stream >> n; + return n; + } + +std::string seq(unsigned n) + { + std::string s; + + for(unsigned i = 0; i != n; ++i) + { + unsigned char b = (i & 0xFF); + + const char bin2hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + s += bin2hex[(b >> 4)]; + s += bin2hex[(b & 0x0f)]; + } + + return s; + } + +void eax_test(const std::string& algo, + const std::string& key_str, + const std::string& nonce_str, + const std::string& header_str, + const std::string& tag_str, + const std::string& plaintext_str, + const std::string& ciphertext) + { + /* + printf("EAX(algo=%s key=%s nonce=%s header=%s tag=%s pt=%s ct=%s)\n", + algo.c_str(), key_str.c_str(), nonce_str.c_str(), header_str.c_str(), tag_str.c_str(), + plaintext_str.c_str(), ciphertext.c_str()); + */ + + SymmetricKey key(key_str); + InitializationVector iv(nonce_str); + + EAX_Encryption* enc; + + Pipe pipe(new Hex_Decoder, + enc = new EAX_Encryption(get_block_cipher(algo)), + new Hex_Encoder); + + enc->set_key(key); + enc->set_iv(iv); + + OctetString header(header_str); + + enc->set_header(header.begin(), header.length()); + + pipe.start_msg(); + pipe.write(plaintext_str); + pipe.end_msg(); + + std::string out = pipe.read_all_as_string(); + + if(out != ciphertext + tag_str) + { + printf("BAD enc %s '%s' != '%s%s'\n", algo.c_str(), + out.c_str(), ciphertext.c_str(), tag_str.c_str()); + } + else + printf("OK enc %s\n", algo.c_str()); + + try + { + EAX_Decryption* dec; + Pipe pipe2(new Hex_Decoder, + dec = new EAX_Decryption(get_block_cipher(algo)), + new Hex_Encoder); + + dec->set_key(key); + dec->set_iv(iv); + + dec->set_header(header.begin(), header.length()); + + pipe2.start_msg(); + pipe2.write(ciphertext); + pipe2.write(tag_str); + pipe2.end_msg(); + + std::string out2 = pipe2.read_all_as_string(); + + if(out2 != plaintext_str) + { + printf("BAD decrypt %s '%s'\n", algo.c_str(), out2.c_str()); + } + else + printf("OK decrypt %s\n", algo.c_str()); + } + catch(std::exception& e) + { + printf("%s\n", e.what()); + } + + } + +std::pair<std::string, int> translate_algo(const std::string& in) + { + if(in == "aes (16 byte key)") + return std::make_pair("AES-128", 16); + + if(in == "blowfish (8 byte key)") + return std::make_pair("Blowfish", 8); + + if(in == "rc2 (8 byte key)") + return std::make_pair("RC2", 8); + + if(in == "rc5 (8 byte key)") + return std::make_pair("RC5", 8); + + if(in == "rc6 (16 byte key)") + return std::make_pair("RC6", 16); + + if(in == "safer-sk128 (16 byte key)") + return std::make_pair("SAFER-SK(10)", 16); + + if(in == "twofish (16 byte key)") + return std::make_pair("Twofish", 16); + + if(in == "des (8 byte key)") + return std::make_pair("DES", 8); + + if(in == "3des (24 byte key)") + return std::make_pair("TripleDES", 24); + + // These 3 are disabled due to differences in base algorithm. + +#if 0 + // XTEA: LTC uses little endian, Botan (and Crypto++) use big-endian + // I swapped to LE in XTEA and the vectors did match + if(in == "xtea (16 byte key)") + return std::make_pair("XTEA", 16); + + // Skipjack: LTC uses big-endian, Botan (and Crypto++) use + // little-endian I am not sure if that was the full difference + // though, was unable to replicate LTC's EAX vectors with Skipjack + if(in == "skipjack (10 byte key)") + return std::make_pair("Skipjack", 10); + + // Noekeon: unknown cause, though LTC's lone test vector does not + // match Botan + + if(in == "noekeon (16 byte key)") + return std::make_pair("Noekeon", 16); + +#endif + + return std::make_pair("", 0); + } + +std::string rep(const std::string& s_in, unsigned n) + { + std::string s_out; + + for(unsigned i = 0; i != n; ++i) + s_out += s_in[i % s_in.size()]; + + return s_out; + } + +void run_tests(std::istream& in) + { + std::string algo; + std::string key; + + while(in.good()) + { + std::string line; + + std::getline(in, line); + + if(line == "") + continue; + + if(line.size() > 5 && line.substr(0, 4) == "EAX-") + { + std::pair<std::string, int> name_and_keylen = + translate_algo(line.substr(4)); + + algo = name_and_keylen.first; + key = seq(name_and_keylen.second); + } + else if(algo != "") + { + boost::regex vec_regex("^([ 0-9]{3}): (.*), (.*)$"); + + boost::smatch what; + + if(boost::regex_match(line, what, vec_regex, boost::match_extra)) + { + unsigned n = from_string(what[1]); + std::string ciphertext = what[2]; + std::string tag = what[3]; + + std::string plaintext = seq(n); + std::string header = seq(n); + std::string nonce = seq(n); + + eax_test(algo, key, nonce, header, tag, + plaintext, ciphertext); + + key = rep(tag, key.size()); // repeat as needed + } + } + } + + + } + +} + +int main() + { + std::ifstream in("eax_tv.txt"); + + Botan::LibraryInitializer init; + + if(!in) + { + std::cerr << "Couldn't read input file\n"; + return 1; + } + + run_tests(in); + + } |