/* $Id: TestAPI.cpp $ * Last updated: * $Date: 2021-09-25 08:37:00 $ * $Version: 6.20.0 $ */ /******************************* LICENSE *********************************** * Copyright (C) 2021 David Ireland, DI Management Services Pty Limited. * All rights reserved. <www.di-mgt.com.au> <www.cryptosys.net> * The code in this module is licensed under the terms of the MIT license. * For a copy, see <http://opensource.org/licenses/MIT> **************************************************************************** */ #include <iostream> #include <assert.h> #include <fstream> #include <sstream> #include "crsysapi.hpp" #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include <windows.h> // For ``SetConsoleOutputCP(CP_UTF8);`` #endif using std::cout; using std::endl; /** Read in a file to a string in one go. */ std::string read_text_file(const std::string& path) { std::ifstream in(path); auto ss = std::ostringstream{}; ss << in.rdbuf(); return ss.str(); } /** Read in a binary file. */ crsysapi::bvec_t read_binary_file(const std::string& path) { std::ifstream stream(path, std::ios::in | std::ios::binary); crsysapi::bvec_t bv((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>()); return bv; } /** Write string to a text file */ void write_text_file(const std::string& path, const std::string& s) { std::ofstream f(path); f << s; f.close(); } static void test_Cnv() { crsysapi::bvec_t bv; cout << "\nTESTING Cnv..." << endl; cout << crsysapi::Cnv::ToHex("abc") << endl; cout << crsysapi::Cnv::ToHex(crsysapi::Cnv::FromHex("616263")) << endl; cout << crsysapi::Cnv::ToHex(crsysapi::Cnv::FromBase64("/ty6mHZUMhA=")) << endl; cout << crsysapi::Cnv::ToBase64(crsysapi::Cnv::FromBase64("/ty6mHZUMhA=")) << endl; cout << crsysapi::Cnv::ToBase64("abc") << endl; // Punct and spaces are ignored bv = crsysapi::Cnv::FromHex(" 61 : 62 :63 "); cout << "bv.size=" << bv.size() << endl; cout << "Expecting errors..." << endl; try { bv = crsysapi::Cnv::FromHex("BADHEXXX"); cout << "bv.size=" << bv.size() << endl; } catch (std::exception& e) { cout << e.what() << endl; } try { bv = crsysapi::Cnv::FromBase64("BADBASE64%#@"); cout << "bv.size=" << bv.size() << endl; } catch (std::exception& e) { cout << e.what() << endl; } } void test_Hash() { cout << "\nTESTING Hash..." << endl; std::string hashstr; crsysapi::bvec_t hashbv; crsysapi::Hash::Alg hashAlg; hashstr = crsysapi::Hash::HexFromHex("616263"); cout << "'" << hashstr << "'" << endl; hashstr = crsysapi::Hash::HexFromHex("616263", crsysapi::Hash::Alg::Sha224); cout << "'" << hashstr << "'" << endl; hashbv = crsysapi::Hash::BytesFromBytes(crsysapi::Cnv::FromHex("616263")); cout << crsysapi::Cnv::ToHex(hashbv) << endl; hashbv = crsysapi::Hash::BytesFromBytes(crsysapi::Cnv::FromHex("616263"), crsysapi::Hash::Alg::Sha224); cout << crsysapi::Cnv::ToHex(hashbv) << endl; hashbv = crsysapi::Hash::BytesFromBytes(crsysapi::Cnv::FromHex("616263"), crsysapi::Hash::Alg::Sha256); cout << crsysapi::Cnv::ToHex(hashbv) << endl; crsysapi::Hash::Alg myhashalg; myhashalg = crsysapi::Hash::Alg::Sha256; hashbv = crsysapi::Hash::BytesFromBytes(crsysapi::Cnv::FromHex("616263"), myhashalg); cout << crsysapi::Cnv::ToHex(hashbv) << endl; hashstr = crsysapi::Hash::HexFromString("abc"); cout << "'" << hashstr << "'" << endl; hashstr = crsysapi::Hash::HexFromBytes(crsysapi::Cnv::FromHex("616263")); cout << "'" << hashstr << "'" << endl; hashstr = crsysapi::Hash::HexFromString("abc", myhashalg); cout << "'" << hashstr << "'" << endl; hashstr = crsysapi::Hash::HexFromBytes(crsysapi::Cnv::FromHex("616263"), myhashalg); cout << "'" << hashstr << "'" << endl; myhashalg = crsysapi::Hash::Alg::Sha3_256; cout << "SHA-3-256:" << endl; hashstr = crsysapi::Hash::HexFromString("abc", myhashalg); cout << "'" << hashstr << "'" << endl; hashstr = crsysapi::Hash::HexFromBytes(crsysapi::Cnv::FromHex("616263"), myhashalg); cout << "'" << hashstr << "'" << endl; cout << "EXPECTING ERROR: FILE IS MISSING..." << endl; try { hashbv = crsysapi::Hash::BytesFromFile("missing.file", myhashalg); cout << crsysapi::Cnv::ToHex(hashbv) << endl; } catch (std::exception& e) { cout << e.what() << endl; } // Hash the empty string cout << "SHA-1 hash the empty string..." << endl; hashstr = crsysapi::Hash::HexFromString(""); cout << "'" << hashstr << "'" << endl; hashbv = crsysapi::Hash::BytesFromBytes(crsysapi::bvec_t()); cout << crsysapi::Cnv::ToHex(hashbv) << endl; hashstr = crsysapi::Hash::HexFromHex(""); cout << "'" << hashstr << "'" << endl; hashbv = crsysapi::Hash::BytesFromFile("empty.txt"); cout << crsysapi::Cnv::ToHex(hashbv) << endl; hashstr = crsysapi::Hash::HexFromFile("empty.txt"); cout << "'" << hashstr << "'" << endl; cout << "SHA-3-384 hash the empty string..." << endl; hashstr = crsysapi::Hash::HexFromString("", crsysapi::Hash::Alg::Sha3_384); cout << "'" << hashstr << "'" << endl; // Hash a text file: test files have different line endings (Windows CR-LF vs Unix LF) // but should give same result when using HexFromTextFile cout << "Hash a text file..." << endl; cout << "Contents = \"hello\\n\" in Windows (CRLF) and Unix (LF) forms" << endl; hashstr = crsysapi::Hash::HexFromFile("hello-crlf.txt"); cout << "Binary CRLF: '" << hashstr << "'" << endl; hashstr = crsysapi::Hash::HexFromFile("hello-unix.txt"); cout << "Binary UNIX: '" << hashstr << "'" << endl; hashstr = crsysapi::Hash::HexFromTextFile("hello-crlf.txt"); cout << "Text CRLF: '" << hashstr << "'" << endl; assert(hashstr == "22596363b3de40b06f981fb85d82312e8c0ed511"); hashstr = crsysapi::Hash::HexFromTextFile("hello-unix.txt"); cout << "Text UNIX: '" << hashstr << "'" << endl; cout << "Hash bit strings of length 9 and 22 bits using SHA-1 and SHA-3-256 respectively..." << endl; cout << crsysapi::Hash::HexFromBits(crsysapi::Cnv::FromHex("5180"), 9) << endl; assert(0 == crsysapi::Hash::HexFromBits(crsysapi::Cnv::FromHex("5180"), 9).compare("0f582fa68b71ecdf1dcfc4946019cf5a18225bd2")); // SHAVS-SHA3 CAVS 19.0 "SHA3-256 ShortMsg" hashstr = crsysapi::Hash::HexFromBits(crsysapi::Cnv::FromHex("2590A0"), 22, crsysapi::Hash::Alg::Sha3_256); cout << hashstr << endl; assert(hashstr == "d5863d4b1ff41551c92a9e08c52177e32376c9bd100c611c607db840096eb22f"); cout << "EXPECTING ERRORS..." << endl; try { crsysapi::Hash::HexFromBits(crsysapi::Cnv::FromHex("5180"), 666); // Too many bits for byte array } catch (std::exception& e) { cout << e.what() << endl; } try { crsysapi::Hash::HexFromBits(crsysapi::Cnv::FromHex("5180"), 9, crsysapi::Hash::Alg::Rmd160); // Unsupported algorithm } catch (std::exception& e) { cout << e.what() << endl; } cout << "...END OF EXPECTED ERRORS." << endl; // Demonstrate lookups for hash algorithm names and digest length cout << "Length(" << crsysapi::Hash::AlgName(crsysapi::Hash::Alg::Sha1) << ")=" << crsysapi::Hash::LengthInBytes(crsysapi::Hash::Alg::Sha1) << " "; cout << "Length(" << crsysapi::Hash::AlgName(crsysapi::Hash::Alg::Sha256) << ")=" << crsysapi::Hash::LengthInBytes(crsysapi::Hash::Alg::Sha256) << " "; hashAlg = crsysapi::Hash::Alg::Md5; cout << "Length(" << crsysapi::Hash::AlgName(hashAlg) << ")=" << crsysapi::Hash::LengthInBytes(hashAlg) << " "; hashAlg = crsysapi::Hash::Alg::Sha3_384; cout << "Length(" << crsysapi::Hash::AlgName(hashAlg) << ")=" << crsysapi::Hash::LengthInBytes(hashAlg) << " "; hashAlg = crsysapi::Hash::Alg::Rmd160; cout << "Length(" << crsysapi::Hash::AlgName(hashAlg) << ")=" << crsysapi::Hash::LengthInBytes(hashAlg) << " "; cout << endl; } void test_Hash_Obj() { cout << "\nTESTING Hash object..." << endl; crsysapi::bvec_t hashbv; bool isok; crsysapi::Hash oHash; isok = oHash.Init(crsysapi::Hash::Alg::Sha256); assert(isok); oHash.AddData("a"); oHash.AddData("bc"); hashbv = oHash.Final(); cout << "SHA256('abc')=" << crsysapi::Cnv::ToHex(hashbv) << endl; assert(crsysapi::Cnv::ToHex(hashbv) == "BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD"); // One million repetitions of the character "a" (0x61) // Ref: https://www.di-mgt.com.au/sha_testvectors.html isok = oHash.Init(crsysapi::Hash::Alg::Sha3_512); assert(isok); crsysapi::bvec_t a1000(1000, 0x61); for (int i = 0; i < 1000; i++) { oHash.AddData(a1000); } hashbv = oHash.Final(); cout << "SHA-3-512(1m x 'a')=" << crsysapi::Cnv::ToHex(hashbv) << endl; assert(crsysapi::Cnv::ToHex(hashbv) == "3C3A876DA14034AB60627C077BB98F7E120A2A5370212DFFB3385A18D4F38859ED311D0A9D5141CE9CC5C66EE689B266A8AA18ACE8282A0E0DB596C90B0A7B87"); cout << "\nEXPECTED ERROR: unsupported algorithm" << endl; try { isok = oHash.Init(crsysapi::Hash::Alg::Rmd160); assert(isok); } catch (std::exception& e) { cout << e.what() << endl; } cout << "-----END EXPECTED ERROR" << endl; } void test_Mac() { cout << "\nTESTING Mac..." << endl; std::string macstr, keyHex, msgHex; crsysapi::bvec_t macbv, bv, data, key; //crsysapi::Mac::Alg macAlg; cout << "Test case 1 from RFC 2202 and RFC 4231" << endl; // HEX('Hi There') = 4869205468657265 macstr = crsysapi::Mac::HexFromHex("4869205468657265", "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"); cout << "HMAC-SHA-1='" << macstr << "'" << endl; assert(macstr == "b617318655057264e28bc0b6fb378c8ef146be00"); macstr = crsysapi::Mac::HexFromHex("4869205468657265", "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", crsysapi::Mac::Alg::HmacSha256); cout << "HMAC-SHA-256='" << macstr << "'" << endl; assert(macstr == "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"); cout << "Test case 4 from RFC 2202 and RFC 4231" << endl; key = crsysapi::Cnv::FromHex("0102030405060708090a0b0c0d0e0f10111213141516171819"); cout << "key=" << crsysapi::Cnv::ToHex(key) << endl; // data = 0xcd repeated 50 times data.clear(); data.insert(data.begin(), 50, (unsigned char)0xcd); cout << "data=" << crsysapi::Cnv::ToHex(data) << endl; bv = crsysapi::Mac::BytesFromBytes(data, key); cout << "HMAC-SHA-1=" << crsysapi::Cnv::ToHex(bv) << endl; assert(bv == crsysapi::Cnv::FromHex("4c9007f4026250c6bc8414f9bf50c86c2d7235da")); bv = crsysapi::Mac::BytesFromBytes(data, key, crsysapi::Mac::Alg::HmacMd5); cout << "HMAC-MD5=" << crsysapi::Cnv::ToHex(bv) << endl; assert(bv == crsysapi::Cnv::FromHex("697eaf0aca3a3aea3a75164746ffaa79")); bv = crsysapi::Mac::BytesFromBytes(data, key, crsysapi::Mac::Alg::HmacSha256); cout << "HMAC-SHA-256=" << crsysapi::Cnv::ToHex(bv) << endl; assert(bv == crsysapi::Cnv::FromHex("82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b")); macstr = crsysapi::Mac::HexFromBytes(data, key, crsysapi::Mac::Alg::HmacSha384); cout << "HMAC-SHA-384='" << macstr << "'" << endl; assert(macstr == "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e6801dd23c4a7d679ccf8a386c674cffb"); macstr = crsysapi::Mac::HexFromBytes(data, key, crsysapi::Mac::Alg::HmacSha224); cout << "HMAC-SHA-224='" << macstr << "'" << endl; assert(macstr == "6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a"); macstr = crsysapi::Mac::HexFromBytes(data, key, crsysapi::Mac::Alg::HmacSha512); cout << "HMAC-SHA-512='" << macstr << "'" << endl; assert(macstr == "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd"); // Compute HMAC-RIPEMD-160 then check against known test vector (RFC2286) macstr = crsysapi::Mac::HexFromBytes(data, key, crsysapi::Mac::Alg::HmacRipemd160); cout << "HMAC-RIPEMD-160='" << macstr << "'" << endl; assert(macstr == "d5ca862f4d21d5e610e18b4cf1beb97a4365ecf4"); cout << "Test case 7 from RFC 4231" << endl; data = crsysapi::str2bvec("This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."); // key 0xaa repeated 131 times key.clear(); key.insert(key.begin(), 131, (unsigned char)0xAA); bv = crsysapi::Mac::BytesFromBytes(data, key, crsysapi::Mac::Alg::HmacSha224); cout << "HMAC-SHA-224=" << crsysapi::Cnv::ToHex(bv) << endl; assert(bv == crsysapi::Cnv::FromHex("3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1")); // HMAC-SHA3-256 cout << "HMAC-SHA3..." << endl; // Text is "Sample message for keylen<blocklen" msgHex = "53616D706C65206D65737361676520666F72206B65796C656E3C626C6F636B6C656E"; keyHex = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"; macstr = crsysapi::Mac::HexFromHex(msgHex, keyHex, crsysapi::Mac::Alg::HmacSha3_256); cout << "HMAC-SHA3-256='" << macstr << "'" << endl; assert(macstr == "4fe8e202c4f058e8dddc23d8c34e467343e23555e24fc2f025d598f558f67205"); cout << "CMAC tests from SP800-38B..." << endl; keyHex = "2b7e151628aed2a6abf7158809cf4f3c"; // CMAC-AES-128 on the empty string msgHex = ""; macstr = crsysapi::Mac::HexFromHex(msgHex, keyHex, crsysapi::Mac::Alg::CmacAes128); cout << "CMAC-AES-128(K128, '')='" << macstr << "'" << endl; assert(macstr == "bb1d6929e95937287fa37d129b756746"); /* CMAC_AES-256 on Example 12: Mlen = 512 */ keyHex = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"; msgHex = "6bc1bee22e409f96e93d7e117393172a" "ae2d8a571e03ac9c9eb76fac45af8e51" "30c81c46a35ce411e5fbc1191a0a52ef" "f69f2445df4f9b17ad2b417be66c3710"; macstr = crsysapi::Mac::HexFromHex(msgHex, keyHex, crsysapi::Mac::Alg::CmacAes256); cout << "CMAC-AES-256(K256, M512)='" << macstr << "'" << endl; assert(macstr == "e1992190549f6ed5696a2c056c315410"); // POLY1305 AUTHENTICATION ALGORITHM // Ref: Test vector from `draft-irtf-cfrg-chacha20-poly1305-06.txt` keyHex = "85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b"; msgHex = crsysapi::Cnv::ToHex("Cryptographic Forum Research Group"); macstr = crsysapi::Mac::HexFromHex(msgHex, keyHex, crsysapi::Mac::Alg::Poly1305); cout << "POLY1305='" << macstr << "'" << endl; assert(macstr == "a8061dc1305136c6c22b8baf0c0127a9"); // KMAC // Ref: `KMAC_samples.pdf` "Secure Hashing - KMAC-Samples" 2017-02-27 // Sample #1 keyHex = "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F"; msgHex = "00010203"; macstr = crsysapi::Mac::HexFromHex(msgHex, keyHex, crsysapi::Mac::Alg::Kmac128); cout << "KMAC128='" << macstr << "'" << endl; assert(macstr == "e5780b0d3ea6f7d3a429c5706aa43a00fadbd7d49628839e3187243f456ee14e"); } void test_Mac_Obj() { cout << "\nTESTING Mac object..." << endl; crsysapi::bvec_t bv, key, data10; bool isok; key = crsysapi::Cnv::FromHex("0102030405060708090a0b0c0d0e0f10111213141516171819"); cout << "key=" << crsysapi::Cnv::ToHex(key) << endl; // data = 0xcd repeated 50 times data10.clear(); // make block of 10 data10.insert(data10.begin(), 10, (unsigned char)0xcd); cout << "data10=" << crsysapi::Cnv::ToHex(data10) << endl; crsysapi::Mac oMac; isok = oMac.Init(key, crsysapi::Mac::Alg::HmacSha256); assert(isok); for (int i = 0; i < 5; i++) { oMac.AddData(data10); } bv = oMac.Final(); cout << crsysapi::Cnv::ToHex(bv) << endl; assert(crsysapi::Cnv::ToHex(bv) == "82558A389A443C0EA4CC819899F2083A85F0FAA3E578F8077A2E3FF46729665B"); cout << "EXPECTED ERROR: unsupported algorithm" << endl; try { isok = oMac.Init(key, crsysapi::Mac::Alg::CmacAes256); assert(isok); } catch (std::exception& e) { cout << e.what() << endl; } } void test_Rng() { crsysapi::bvec_t bv; cout << "\nTESTING Rng..." << endl; cout << "Rng::Hex:" << endl; for (int i = 0; i < 4; i++) { std::string s = crsysapi::Rng::Hex(32); cout << s << endl; } cout << "Rng::Number(-5,+5):" << endl; for (int i = 0; i < 20; i++) { cout << crsysapi::Rng::Number(-5, 5) << " "; } cout << endl; cout << "Rng::Octet:" << endl; for (int i = 0; i < 20; i++) { cout << crsysapi::Rng::Octet() << " "; } cout << endl; cout << "Rng::Bytes:" << endl; for (int i = 0; i < 4; i++) { bv = crsysapi::Rng::Bytes(24); cout << crsysapi::Cnv::ToHex(bv) << endl; } std::string seedfile = "mycppseedfile.dat"; crsysapi::Rng::Initialize(seedfile); // Show contents of seed file bv = read_binary_file(seedfile); cout << "Seed file:\n" << crsysapi::Cnv::ToHex(bv) << endl; crsysapi::Rng::UpdateSeedFile(seedfile); bv = read_binary_file(seedfile); cout << "New Seed file:\n" << crsysapi::Cnv::ToHex(bv) << endl; } void test_Cipher() { //std::string s; crsysapi::bvec_t bv; crsysapi::bvec_t pt, ct, dt, key, iv, data; std::string algstr; cout << "\nTESTING Cipher..." << endl; algstr = "Aes128/CBC/pkcs5"; cout << algstr << endl; key = crsysapi::Cnv::FromHex("0123456789ABCDEFF0E1D2C3B4A59687"); iv = crsysapi::Cnv::FromHex("FEDCBA9876543210FEDCBA9876543210"); pt = crsysapi::str2bvec("Now is the time for all good men to"); ct = crsysapi::Cipher::Encrypt(pt, key, iv, algstr); cout << "ct=" << crsysapi::Cnv::ToHex(ct) << endl; assert(0 == crsysapi::Cnv::ToHex(ct).compare("C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E17753C7E8DF5975A36677355F5C6584228B")); dt = crsysapi::Cipher::Decrypt(ct, key, iv, algstr); cout << "dt='" << crsysapi::bvec2str(dt) << "'" << endl; assert(dt.size() > 0); ct = crsysapi::Cipher::Encrypt(pt, key, iv, algstr, crsysapi::Cipher::Opts::PrefixIV); cout << "ct(PrefixIV)=" << crsysapi::Cnv::ToHex(ct) << endl; //assert(0 == crsysapi::Cnv::ToHex(ct).compare("C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E17753C7E8DF5975A36677355F5C6584228B")); dt = crsysapi::Cipher::Decrypt(ct, key, iv, algstr, crsysapi::Cipher::Opts::PrefixIV); cout << "dt='" << crsysapi::bvec2str(dt) << "'" << endl; assert(dt.size() > 0); cout << "bvec2str(empty)='" << crsysapi::bvec2str(crsysapi::bvec_t()) << "'" << endl; // Same input, different mode and padding, ECB mode so pass an empty IV algstr = "Aes128/ECB/OneAndZeroes"; cout << algstr << endl; ct = crsysapi::Cipher::Encrypt(pt, key, crsysapi::bvec_t(), algstr); cout << "ct=" << crsysapi::Cnv::ToHex(ct) << endl; assert(0 == crsysapi::Cnv::ToHex(ct).compare("F0D1AD6F901FFFAE5572A6928DAB52B064B25C79F876730321E36DC01011ACCED7E53F5E5CB18233FE486CD4FFA79FE9")); dt = crsysapi::Cipher::Decrypt(ct, key, iv, algstr); cout << "dt='" << crsysapi::bvec2str(dt) << "'" << endl; assert(dt.size() > 0); // Again, using Alg/Mode/Pad params instead of alg string ct = crsysapi::Cipher::Encrypt(pt, key, iv, crsysapi::Cipher::Alg::Aes128, crsysapi::Cipher::Mode::CBC, crsysapi::Cipher::Pad::Default); cout << "ct=" << crsysapi::Cnv::ToHex(ct) << endl; assert(0 == crsysapi::Cnv::ToHex(ct).compare("C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E17753C7E8DF5975A36677355F5C6584228B")); dt = crsysapi::Cipher::Decrypt(ct, key, iv, crsysapi::Cipher::Alg::Aes128, crsysapi::Cipher::Mode::CBC, crsysapi::Cipher::Pad::Default); cout << "dt='" << crsysapi::bvec2str(dt) << "'" << endl; assert(dt.size() > 0); ct = crsysapi::Cipher::Encrypt(pt, key, crsysapi::bvec_t(), crsysapi::Cipher::Alg::Aes128, crsysapi::Cipher::Mode::ECB, crsysapi::Cipher::Pad::OneAndZeroes); cout << "ct=" << crsysapi::Cnv::ToHex(ct) << endl; assert(0 == crsysapi::Cnv::ToHex(ct).compare("F0D1AD6F901FFFAE5572A6928DAB52B064B25C79F876730321E36DC01011ACCED7E53F5E5CB18233FE486CD4FFA79FE9")); dt = crsysapi::Cipher::Decrypt(ct, key, crsysapi::bvec_t(), crsysapi::Cipher::Alg::Aes128, crsysapi::Cipher::Mode::ECB, crsysapi::Cipher::Pad::OneAndZeroes); cout << "dt='" << crsysapi::bvec2str(dt) << "'" << endl; assert(dt.size() > 0); cout << "TEST CIPHER FUNCTIONS WITH EXACT BLOCK LENGTHS..." << endl; key = crsysapi::Cnv::FromHex("0123456789ABCDEFF0E1D2C3B4A59687"); iv = crsysapi::Cnv::FromHex("FEDCBA9876543210FEDCBA9876543210"); pt = crsysapi::str2bvec("Now is the time for all good men"); // Exactly 32 bytes, a multiple of 16 ct = crsysapi::Cipher::EncryptBlock(pt, key, iv, crsysapi::Cipher::Alg::Aes128, crsysapi::Cipher::Mode::CBC); cout << "ct=" << crsysapi::Cnv::ToHex(ct) << endl; assert(0 == crsysapi::Cnv::ToHex(ct).compare("C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E177")); dt = crsysapi::Cipher::DecryptBlock(ct, key, iv, crsysapi::Cipher::Alg::Aes128, crsysapi::Cipher::Mode::CBC); cout << "dt=" << crsysapi::Cnv::ToHex(dt) << endl; cout << "dt='" << crsysapi::bvec2str(dt) << "'" << endl; assert(dt.size() > 0); // Use defaults and a random key crsysapi::Cipher::Alg myalg = crsysapi::Cipher::Alg::Aes256; // Cipher::Alg _must_ be specified cout << "Cipher::Alg = " << crsysapi::Cipher::AlgName(myalg) << endl; key = crsysapi::Rng::Bytes(crsysapi::Cipher::KeyBytes(myalg)); cout << "Random key: " << crsysapi::Cnv::ToHex(key) << endl; ct = crsysapi::Cipher::EncryptBlock(pt, key, iv, myalg); cout << "ct=" << crsysapi::Cnv::ToHex(ct) << endl; dt = crsysapi::Cipher::DecryptBlock(ct, key, iv, myalg); cout << "dt=" << crsysapi::Cnv::ToHex(dt) << endl; cout << "dt='" << crsysapi::bvec2str(dt) << "'" << endl; assert(dt.size() > 0); // Invalid decryption cout << "Expecting an error (passing the wrong key to decrypt)..." << endl; key = crsysapi::Cnv::FromHex("FF0123456789ABCDEFF0E1D2C3B4A596"); // Wrong key iv = crsysapi::Cnv::FromHex("FEDCBA9876543210FEDCBA9876543210"); ct = crsysapi::Cnv::FromHex("C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E17753C7E8DF5975A36677355F5C6584228B"); try { dt = crsysapi::Cipher::Decrypt(ct, key, iv, crsysapi::Cipher::Alg::Aes128, crsysapi::Cipher::Mode::CBC); cout << "dt=" << crsysapi::Cnv::ToHex(dt) << endl; } catch (std::exception& e) { cout << e.what() << endl; } cout << "Passing an invalid IV..." << endl; try { dt = crsysapi::Cipher::EncryptBlock(ct, key, crsysapi::bvec_t(), crsysapi::Cipher::Alg::Aes128, crsysapi::Cipher::Mode::CBC); cout << "dt=" << crsysapi::Cnv::ToHex(dt) << endl; } catch (std::exception& e) { cout << e.what() << endl; } cout << "Triple DES Known Answer tests..." << endl; key = crsysapi::Cnv::FromHex("385D7189A5C3D485E1370AA5D408082B5CCCCB5E19F2D90E"); iv = crsysapi::Cnv::FromHex("C141B5FCCD28DC8A"); pt = crsysapi::Cnv::FromHex("6E1BD7C6120947A464A6AAB293A0F89A563D8D40D3461B68"); crsysapi::Cipher::Alg alg = crsysapi::Cipher::Alg::Tdea; crsysapi::Cipher::Mode mode; //char sCorrectECB[] = "64EAAD4ACBB9CEAD6C7615E7C7E4792FE587D91F20C7D2F4"; //char sCorrectCBC[] = "6235A461AFD312973E3B4F7AA7D23E34E03371F8E8C376C9"; //char sCorrectCFB[] = "E26BA806A59B0330DE40CA38E77A3E494BE2B212F6DD624B"; //char sCorrectOFB[] = "E26BA806A59B03307DE2BCC25A08BA40A8BA335F5D604C62"; //char sCorrectCTR[] = "E26BA806A59B03303C62C2EFF32D3ACDD5D5F35EBCC53371"; mode = crsysapi::Cipher::Mode::ECB; cout << crsysapi::Cipher::AlgName(alg) << "/" << crsysapi::Cipher::ModeName(mode) << endl; cout << "pt=" << crsysapi::Cnv::ToHex(pt) << endl; ct = crsysapi::Cipher::EncryptBlock(pt, key, iv, alg, mode); cout << "ct=" << crsysapi::Cnv::ToHex(ct) << endl; assert(0 == crsysapi::Cnv::ToHex(ct).compare("64EAAD4ACBB9CEAD6C7615E7C7E4792FE587D91F20C7D2F4")); dt = crsysapi::Cipher::DecryptBlock(ct, key, iv, alg, mode); cout << "dt=" << crsysapi::Cnv::ToHex(dt) << endl; assert(0 == crsysapi::Cnv::ToHex(dt).compare("6E1BD7C6120947A464A6AAB293A0F89A563D8D40D3461B68")); mode = crsysapi::Cipher::Mode::CBC; cout << crsysapi::Cipher::AlgName(alg) << "/" << crsysapi::Cipher::ModeName(mode) << endl; cout << "pt=" << crsysapi::Cnv::ToHex(pt) << endl; ct = crsysapi::Cipher::EncryptBlock(pt, key, iv, alg, mode); cout << "ct=" << crsysapi::Cnv::ToHex(ct) << endl; assert(0 == crsysapi::Cnv::ToHex(ct).compare("6235A461AFD312973E3B4F7AA7D23E34E03371F8E8C376C9")); dt = crsysapi::Cipher::DecryptBlock(ct, key, iv, alg, mode); cout << "dt=" << crsysapi::Cnv::ToHex(dt) << endl; assert(0 == crsysapi::Cnv::ToHex(dt).compare("6E1BD7C6120947A464A6AAB293A0F89A563D8D40D3461B68")); mode = crsysapi::Cipher::Mode::CFB; cout << crsysapi::Cipher::AlgName(alg) << "/" << crsysapi::Cipher::ModeName(mode) << endl; cout << "pt=" << crsysapi::Cnv::ToHex(pt) << endl; ct = crsysapi::Cipher::EncryptBlock(pt, key, iv, alg, mode); cout << "ct=" << crsysapi::Cnv::ToHex(ct) << endl; assert(0 == crsysapi::Cnv::ToHex(ct).compare("E26BA806A59B0330DE40CA38E77A3E494BE2B212F6DD624B")); dt = crsysapi::Cipher::DecryptBlock(ct, key, iv, alg, mode); cout << "dt=" << crsysapi::Cnv::ToHex(dt) << endl; assert(0 == crsysapi::Cnv::ToHex(dt).compare("6E1BD7C6120947A464A6AAB293A0F89A563D8D40D3461B68")); mode = crsysapi::Cipher::Mode::OFB; cout << crsysapi::Cipher::AlgName(alg) << "/" << crsysapi::Cipher::ModeName(mode) << endl; cout << "pt=" << crsysapi::Cnv::ToHex(pt) << endl; ct = crsysapi::Cipher::EncryptBlock(pt, key, iv, alg, mode); cout << "ct=" << crsysapi::Cnv::ToHex(ct) << endl; assert(0 == crsysapi::Cnv::ToHex(ct).compare("E26BA806A59B03307DE2BCC25A08BA40A8BA335F5D604C62")); dt = crsysapi::Cipher::DecryptBlock(ct, key, iv, alg, mode); cout << "dt=" << crsysapi::Cnv::ToHex(dt) << endl; assert(0 == crsysapi::Cnv::ToHex(dt).compare("6E1BD7C6120947A464A6AAB293A0F89A563D8D40D3461B68")); mode = crsysapi::Cipher::Mode::CTR; cout << crsysapi::Cipher::AlgName(alg) << "/" << crsysapi::Cipher::ModeName(mode) << endl; cout << "pt=" << crsysapi::Cnv::ToHex(pt) << endl; ct = crsysapi::Cipher::EncryptBlock(pt, key, iv, alg, mode); cout << "ct=" << crsysapi::Cnv::ToHex(ct) << endl; assert(0 == crsysapi::Cnv::ToHex(ct).compare("E26BA806A59B03303C62C2EFF32D3ACDD5D5F35EBCC53371")); dt = crsysapi::Cipher::DecryptBlock(ct, key, iv, alg, mode); cout << "dt=" << crsysapi::Cnv::ToHex(dt) << endl; assert(0 == crsysapi::Cnv::ToHex(dt).compare("6E1BD7C6120947A464A6AAB293A0F89A563D8D40D3461B68")); } void test_Cipher_Obj() { cout << "\nTESTING Cipher object..." << endl; crsysapi::bvec_t pt, ct; crsysapi::bvec_t key, iv; crsysapi::Cipher::Alg alg = crsysapi::Cipher::Alg::Aes128; crsysapi::Cipher::Mode mode; bool isok; key = crsysapi::Cnv::FromHex("0123456789ABCDEFF0E1D2C3B4A59687"); iv = crsysapi::Cnv::FromHex("FEDCBA9876543210FEDCBA9876543210"); crsysapi::Cipher oCipher; // AES-128 CBC mode mode = crsysapi::Cipher::Mode::CBC; isok = oCipher.InitEncrypt(key, iv, alg, mode); assert(isok); cout << crsysapi::Cipher::AlgName(alg) << "/" << crsysapi::Cipher::ModeName(mode) << endl; // Pass data in chunks of 16 bytes (or multiples of) // Part 1... pt = crsysapi::str2bvec("Now is the time for all good men"); cout << "PT=" << crsysapi::Cnv::ToHex(pt) << endl; ct = oCipher.Update(pt); cout << "CT=" << crsysapi::Cnv::ToHex(ct) << endl; // Part 2... pt = crsysapi::str2bvec(" to come to the aid of the party"); cout << "PT=" << crsysapi::Cnv::ToHex(pt) << endl; ct = oCipher.Update(pt); cout << "CT=" << crsysapi::Cnv::ToHex(ct) << endl; // We are done isok = oCipher.Final(); assert(isok); // AES-128 counter (CTR) mode mode = crsysapi::Cipher::Mode::CTR; isok = oCipher.InitEncrypt(key, iv, alg, mode); assert(isok); cout << crsysapi::Cipher::AlgName(alg) << "/" << crsysapi::Cipher::ModeName(mode) << endl; // Pass data in chunks of 16 bytes (or multiples of) // Part 1... pt = crsysapi::str2bvec("Now is the time for all good men"); cout << "PT=" << crsysapi::Cnv::ToHex(pt) << endl; ct = oCipher.Update(pt); cout << "CT=" << crsysapi::Cnv::ToHex(ct) << endl; // Part 2... // In CTR mode (and OFB and CFB) the last block need not be a multiple pt = crsysapi::str2bvec(" to come to the aid of"); cout << "PT=" << crsysapi::Cnv::ToHex(pt) << endl; ct = oCipher.Update(pt); cout << "CT=" << crsysapi::Cnv::ToHex(ct) << endl; // We are done isok = oCipher.Final(); assert(isok); // Now decrypt... cout << "Decrypting..." << endl; mode = crsysapi::Cipher::Mode::ECB; isok = oCipher.InitDecrypt(key, iv, alg, mode); assert(isok); cout << crsysapi::Cipher::AlgName(alg) << "/" << crsysapi::Cipher::ModeName(mode) << endl; ct = crsysapi::Cnv::FromHex("F0D1AD6F901FFFAE5572A6928DAB52B064B25C79F876730321E36DC01011ACCE"); cout << "CT=" << crsysapi::Cnv::ToHex(ct) << endl; pt = oCipher.Update(ct); cout << "PT=" << crsysapi::bvec2str(pt) << endl; ct = crsysapi::Cnv::FromHex("02D6F240643271217758C44862BB1B6862CD10757387256BC678A1708483862A"); cout << "CT=" << crsysapi::Cnv::ToHex(ct) << endl; pt = oCipher.Update(ct); cout << "PT=" << crsysapi::bvec2str(pt) << endl; } void test_CipherStream() { crsysapi::bvec_t bv; crsysapi::bvec_t pt, ct, dt, key, iv, data; std::string fileIn, fileOut; int r; cout << "\nTESTING CipherStream..." << endl; cout << "Arcfour (RC4) test vector" << endl; key = crsysapi::Cnv::FromHex("0123456789abcdef"); pt = crsysapi::Cnv::FromHex("0123456789abcdef"); cout << "KY=" << crsysapi::Cnv::ToHex(key) << endl; cout << "PT=" << crsysapi::Cnv::ToHex(pt) << endl; ct = crsysapi::CipherStream::Bytes(pt, key, crsysapi::bvec_t(), crsysapi::CipherStream::Alg::Arcfour); cout << "CT=" << crsysapi::Cnv::ToHex(ct) << endl; assert(0 == crsysapi::Cnv::ToHex(ct).compare("75B7878099E0C596")); cout << "ChaCha20 test vector from \"ChaCha20 and Poly1305 for IETF protocols\"" << endl; key = crsysapi::Cnv::FromHex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"); iv = crsysapi::Cnv::FromHex("000000000000004a00000000"); cout << "KY=" << crsysapi::Cnv::ToHex(key) << endl; cout << "IV=" << crsysapi::Cnv::ToHex(iv) << endl; pt = crsysapi::str2bvec("Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."); cout << "PT=" << crsysapi::Cnv::ToHex(pt) << endl; ct = crsysapi::CipherStream::Bytes(pt, key, iv, crsysapi::CipherStream::Alg::Chacha20, 1); cout << "CT=" << crsysapi::Cnv::ToHex(ct) << endl; assert(0 == crsysapi::Cnv::ToHex(ct).compare("6E2E359A2568F98041BA0728DD0D6981E97E7AEC1D4360C20A27AFCCFD9FAE0BF91B65C5524733AB8F593DABCD62B3571639D624E65152AB8F530C359F0861D807CA0DBF500D6A6156A38E088A22B65E52BC514D16CCF806818CE91AB77937365AF90BBF74A35BE6B40B8EEDF2785E42874D")); cout << "Salsa20 test vector" << endl; key = crsysapi::Cnv::FromHex("80000000000000000000000000000000"); iv = crsysapi::Cnv::FromHex("0000000000000000"); cout << "KY=" << crsysapi::Cnv::ToHex(key) << endl; cout << "IV=" << crsysapi::Cnv::ToHex(iv) << endl; pt = crsysapi::bvec_t(64); // 64 zero bytes std::fill(pt.begin(), pt.end(), 0); cout << "PT=" << crsysapi::Cnv::ToHex(pt) << endl; ct = crsysapi::CipherStream::Bytes(pt, key, iv, crsysapi::CipherStream::Alg::Salsa20); cout << "CT=" << crsysapi::Cnv::ToHex(ct) << endl; assert(0 == crsysapi::Cnv::ToHex(ct).compare("4DFA5E481DA23EA09A31022050859936DA52FCEE218005164F267CB65F5CFD7F2B4F97E0FF16924A52DF269515110A07F9E460BC65EF95DA58F740B7D1DBB0AA")); cout << "ChaCha20 test vector using files" << endl; key = crsysapi::Cnv::FromHex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"); iv = crsysapi::Cnv::FromHex("000000000000004a00000000"); cout << "KY=" << crsysapi::Cnv::ToHex(key) << endl; cout << "IV=" << crsysapi::Cnv::ToHex(iv) << endl; fileIn = "sunscreen.txt"; fileOut = "sunscreen.chacha.dat"; r = crsysapi::CipherStream::File(fileOut, fileIn, key, iv, crsysapi::CipherStream::Alg::Chacha20, 1); cout << "CipherStream::File returns " << r << " (expecting 0)" << endl; assert(0 == r); // Check file contents ct = read_binary_file(fileOut); cout << "File(CT)=" << crsysapi::Cnv::ToHex(ct) << endl; cout << "OK =6E2E359A2568F98041BA0728DD0D6981E97E7AEC1D4360C20A27AFCCFD9FAE0BF91B65C5524733AB8F593DABCD62B3571639D624E65152AB8F530C359F0861D807CA0DBF500D6A6156A38E088A22B65E52BC514D16CCF806818CE91AB77937365AF90BBF74A35BE6B40B8EEDF2785E42874D" << endl; } void test_Aead() { crsysapi::bvec_t bv; crsysapi::bvec_t pt, ct, dt, key, nonce, data, aad; std::string okhex; cout << "\nTESTING Aead..." << endl; cout << "Ref: IEEE P802.1 MACsec 2.4.1 54-byte Packet Encryption Using GCM-AES-128:" << endl; key = crsysapi::Cnv::FromHex("071b113b 0ca743fe cccf3d05 1f737382"); nonce = crsysapi::Cnv::FromHex("f0761e8d cd3d0001 76d457ed"); aad = crsysapi::Cnv::FromHex("e20106d7 cd0df076 1e8dcd3d 88e54c2a 76d457ed"); pt = crsysapi::Cnv::FromHex("08000f10 11121314 15161718 191a1b1c 1d1e1f20 21222324 25262728 292a2b2c 2d2e2f30 31323334 0004"); okhex = "F0761E8DCD3D000176D457ED13B4C72B389DC5018E72A171DD85A5D3752274D3A019FBCAED09A425CD9B2E1C9B72EEE7C9DE7D52B3F3D6A5284F4A6D3FE22A5D6C2B960494C3"; cout << "K: " << crsysapi::Cnv::ToHex(key) << endl; cout << "N: " << crsysapi::Cnv::ToHex(nonce) << endl; cout << "A: " << crsysapi::Cnv::ToHex(aad) << endl; cout << "P: " << crsysapi::Cnv::ToHex(pt) << endl; ct = crsysapi::Aead::EncryptWithTag(pt, key, nonce, aad, crsysapi::Aead::Alg::Aes_128_Gcm, crsysapi::Aead::Opts::PrefixIV); cout << "Output prefixed with IV and with tag appended..." << endl; cout << "C: " << crsysapi::Cnv::ToHex(ct) << endl; cout << "OK " << okhex << endl; assert(0 == crsysapi::Cnv::ToHex(ct).compare(okhex)); // Now decrypt okhex = crsysapi::Cnv::ToHex(pt); dt = crsysapi::Aead::DecryptWithTag(ct, key, nonce, aad, crsysapi::Aead::Alg::Aes_128_Gcm, crsysapi::Aead::Opts::PrefixIV); cout << "P: " << crsysapi::Cnv::ToHex(dt) << endl; cout << "OK " << okhex << endl; assert(0 == crsysapi::Cnv::ToHex(dt).compare(okhex)); cout << "Ref: RFC7739 ChaCha20_Poly1305 Appendix A.5:" << endl; key = crsysapi::Cnv::FromHex("1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0"); nonce = crsysapi::Cnv::FromHex("000000000102030405060708"); aad = crsysapi::Cnv::FromHex("f33388860000000000004e91"); pt = crsysapi::Cnv::FromHex("496e7465726e65742d4472616674732061726520647261667420646f63756d656e74732076616c696420666f722061206d6178696d756d206f6620736978206d6f6e74687320616e64206d617920626520757064617465642c207265706c616365642c206f72206f62736f6c65746564206279206f7468657220646f63756d656e747320617420616e792074696d652e20497420697320696e617070726f70726961746520746f2075736520496e7465726e65742d447261667473206173207265666572656e6365206d6174657269616c206f7220746f2063697465207468656d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67726573732e2fe2809d"); // Expected output is ciphertext + 16-byte tag okhex = "64A0861575861AF460F062C79BE643BD5E805CFD345CF389F108670AC76C8CB24C6CFC18755D43EEA09EE94E382D26B0BDB7B73C321B0100D4F03B7F355894CF332F830E710B97CE98C8A84ABD0B948114AD176E008D33BD60F982B1FF37C8559797A06EF4F0EF61C186324E2B3506383606907B6A7C02B0F9F6157B53C867E4B9166C767B804D46A59B5216CDE7A4E99040C5A40433225EE282A1B0A06C523EAF4534D7F83FA1155B0047718CBC546A0D072B04B3564EEA1B422273F548271A0BB2316053FA76991955EBD63159434ECEBB4E466DAE5A1073A6727627097A1049E617D91D361094FA68F0FF77987130305BEABA2EDA04DF997B714D6C6F2C29A6AD5CB4022B02709B" "EEAD9D67890CBB22392336FEA1851F38"; cout << "K: " << crsysapi::Cnv::ToHex(key) << endl; cout << "N: " << crsysapi::Cnv::ToHex(nonce) << endl; cout << "A: " << crsysapi::Cnv::ToHex(aad) << endl; cout << "P: " << crsysapi::Cnv::ToHex(pt) << endl; ct = crsysapi::Aead::EncryptWithTag(pt, key, nonce, aad, crsysapi::Aead::Alg::Chacha20_Poly1305); cout << "C: " << crsysapi::Cnv::ToHex(ct) << endl; cout << "OK " << okhex << endl; assert(0 == crsysapi::Cnv::ToHex(ct).compare(okhex)); // Now decrypt okhex = crsysapi::Cnv::ToHex(pt); dt = crsysapi::Aead::DecryptWithTag(ct, key, nonce, aad, crsysapi::Aead::Alg::Chacha20_Poly1305); cout << "P: " << crsysapi::Cnv::ToHex(dt) << endl; cout << "OK " << okhex << endl; assert(0 == crsysapi::Cnv::ToHex(dt).compare(okhex)); cout << crsysapi::bvec2str(dt) << endl; } void test_Wipe() { crsysapi::bvec_t bv; std::string s; cout << "\nTESTING Wipe..." << endl; bv = crsysapi::str2bvec("Some secret data"); crsysapi::Wipe::Data(bv); cout << "After Wipe::Data='" << crsysapi::Cnv::ToHex(bv) << "'" << endl; s = "More secret data"; crsysapi::Wipe::String(s); cout << "After Wipe::String='" << s << "'" << endl; std::string fname = "todelete.txt"; write_text_file(fname, "Even more secret stuff\n"); cout << "FILE: " << fname << endl; cout << "[" << read_text_file(fname) << "]" << endl; crsysapi::Wipe::File(fname); cout << "After Wipe::File=" << "[" << read_text_file(fname) << "]" << endl; } void test_Pbe() { cout << "\nTESTING PASSWORD-BASED ENCRYPTION (PBE)..." << endl; std::string password = "password"; crsysapi::bvec_t salt = crsysapi::Cnv::FromHex("78 57 8E 5A 5D 63 CB 06"); int count = 2048; crsysapi::bvec_t dk; dk = crsysapi::Pbe::Kdf2(24, password, salt, count); cout << "dk=" << crsysapi::Cnv::ToHex(dk) << endl; assert(dk == crsysapi::Cnv::FromHex("BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643")); // Same params but derive longer key (CAUTION: never use same salt in practice) dk = crsysapi::Pbe::Kdf2(64, password, salt, count); cout << "dk=" << crsysapi::Cnv::ToHex(dk) << endl; assert(dk == crsysapi::Cnv::FromHex("BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643C4B150DEF77511224479994567F2E9B4E3BD0DF7AEDA3022B1F26051D81505C794F8940C04DF1144")); // Use different HMAC algorithm dk = crsysapi::Pbe::Kdf2(24, password, salt, count, crsysapi::Pbe::PrfAlg::Hmac_Sha256); cout << "dk=" << crsysapi::Cnv::ToHex(dk) << endl; assert(dk == crsysapi::Cnv::FromHex("97B5A91D35AF542324881315C4F849E327C4707D1BC9D322")); } void test_Crc() { cout << "\nTESTING CRC..." << endl; int n; std::string s = "123456789"; n = crsysapi::Crc::String(s); std::cout << std::hex << n << std::dec << std::endl; assert(n = 0xCBF43926); crsysapi::bvec_t bv = crsysapi::str2bvec("123456789"); n = crsysapi::Crc::Bytes(bv); std::cout << std::hex << n << std::dec << std::endl; assert(n = 0xCBF43926); n = crsysapi::Crc::File("1-9.txt"); std::cout << std::hex << n << std::dec << std::endl; assert(n = 0xCBF43926); cout << "EXPECTING ERROR: Missing file..." << endl; try { n = crsysapi::Crc::File("missing.file"); std::cout << std::hex << n << std::dec << std::endl; } catch (std::exception& e) { cout << e.what() << endl; } } void test_Xof() { cout << "\nTESTING XOF..." << endl; crsysapi::bvec_t bv; crsysapi::bvec_t msg = crsysapi::Cnv::FromHex("6ae23f058f0f2264a18cd609acc26dd4dbc00f5c3ee9e13ecaea2bb5a2f0bb6b"); // Output 2000 bits bv = crsysapi::Xof::Bytes(2000 / 8, msg, crsysapi::Xof::XofAlg::Shake256); cout << "OUT=" << crsysapi::Cnv::ToHex(bv) << endl; assert(crsysapi::Cnv::ToHex(bv) == "B9B92544FB25CFE4EC6FE437D8DA2BBE00F7BDAFACE3DE97B8775A44D753C3ADCA3F7C6F183CC8647E229070439AA9539AE1F8F13470C9D3527FFFDEEF6C94F9F0520FF0C1BA8B16E16014E1AF43AC6D94CB7929188CCE9D7B02F81A2746F52BA16988E5F6D93298D778DFE05EA0EF256AE3728643CE3E29C794A0370E9CA6A8BF3E7A41E86770676AC106F7AE79E67027CE7B7B38EFE27D253A52B5CB54D6EB4367A87736ED48CB45EF27F42683DA140ED3295DFC575D3EA38CFC2A3697CC92864305407369B4ABAC054E497378DD9FD0C4B352EA3185CE1178B3DC1599DF69DB29259D4735320C8E7D33E8226620C9A1D22761F1D35BDFF79A"); } void test_Prf() { cout << "\nTESTING PRF..." << endl; crsysapi::bvec_t bv; crsysapi::bvec_t key = crsysapi::Cnv::FromHex("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F"); crsysapi::bvec_t msg = crsysapi::Cnv::FromHex("00010203"); bv = crsysapi::Prf::Bytes(256 / 8, msg, key, crsysapi::Prf::PrfAlg::Kmac128, "My Tagged Application"); cout << "OUT=" << crsysapi::Cnv::ToHex(bv) << endl; assert(crsysapi::Cnv::ToHex(bv) == "3B1FBA963CD8B0B59E8C1A6D71888B7143651AF8BA0A7070C0979E2811324AA5"); } void test_Err() { cout << "\nTESTING ERR..." << endl; for (int i = 0; i < 7; i++) { // Print message for every third error code, just to demonstrate int errCode = i * 3; cout << "ErrorLookup(" << errCode << ")=" << crsysapi::Err::ErrorLookup(errCode) << endl; } cout << crsysapi::Err::FormatErrorMessage(1) << endl; } void do_all() { test_Cnv(); test_Rng(); test_Hash(); test_Hash_Obj(); test_Mac(); test_Mac_Obj(); test_Cipher(); test_Cipher_Obj(); test_CipherStream(); test_Aead(); test_Wipe(); test_Pbe(); test_Crc(); test_Xof(); test_Prf(); test_Err(); } int main(int argc, char *argv[]) { #ifdef _WIN32 // Set Windows console display page to UTF-8 SetConsoleOutputCP(CP_UTF8); #endif cout << "Compiled: " __DATE__ " " __TIME__ << endl; cout << "__cplusplus=" << __cplusplus << endl; cout << "Gen::Version=" << crsysapi::Gen::Version() << endl; cout << "Gen::CompileTime=" << crsysapi::Gen::CompileTime() << endl; cout << "Gen::ModuleName=" << crsysapi::Gen::ModuleName() << endl; cout << "Gen::Platform=" << crsysapi::Gen::Platform() << endl; if (argc > 1 && strcmp(argv[1], "all") == 0) { cout << "DOING ALL..." << endl; do_all(); } else { cout << "DOING SOME..." << endl; //test_Cnv(); //test_Rng(); //test_Hash(); test_Hash_Obj(); //test_Mac(); //test_Mac_Obj(); //test_Cipher(); //test_Cipher_Obj(); //test_CipherStream(); //test_Aead(); //test_Wipe(); //test_Pbe(); //test_Crc(); //test_Xof(); //test_Prf(); //test_Err(); } // ****************************************** // FINALLY, DISPLAY QUICK INFO ABOUT THE CORE DLL cout << "\nFINALLY, DETAILS OF CORE NATIVE DLL..." << endl; cout << "DLL Version=" << crsysapi::Gen::Version() << " [" << crsysapi::Gen::Platform() << "] Lic={" << crsysapi::Gen::LicenceType() << "} Compiled=[" << crsysapi::Gen::CompileTime() << "] " << endl; cout << "[" << crsysapi::Gen::ModuleName() << "]" << endl; cout << endl << "ALL DONE." << endl; }