|
17 | 17 |
|
18 | 18 | #include <boost/assign/list_of.hpp>
|
19 | 19 | #include <boost/test/unit_test.hpp>
|
| 20 | +#include <openssl/aes.h> |
| 21 | +#include <openssl/evp.h> |
20 | 22 |
|
21 | 23 | BOOST_FIXTURE_TEST_SUITE(crypto_tests, BasicTestingSetup)
|
22 | 24 |
|
@@ -103,6 +105,88 @@ void TestAES256(const std::string &hexkey, const std::string &hexin, const std::
|
103 | 105 | BOOST_CHECK(buf == in);
|
104 | 106 | }
|
105 | 107 |
|
| 108 | +void TestAES128CBC(const std::string &hexkey, const std::string &hexiv, bool pad, const std::string &hexin, const std::string &hexout) |
| 109 | +{ |
| 110 | + std::vector<unsigned char> key = ParseHex(hexkey); |
| 111 | + std::vector<unsigned char> iv = ParseHex(hexiv); |
| 112 | + std::vector<unsigned char> in = ParseHex(hexin); |
| 113 | + std::vector<unsigned char> correctout = ParseHex(hexout); |
| 114 | + std::vector<unsigned char> realout(in.size() + AES_BLOCKSIZE); |
| 115 | + |
| 116 | + // Encrypt the plaintext and verify that it equals the cipher |
| 117 | + AES128CBCEncrypt enc(&key[0], &iv[0], pad); |
| 118 | + int size = enc.Encrypt(&in[0], in.size(), &realout[0]); |
| 119 | + realout.resize(size); |
| 120 | + BOOST_CHECK(realout.size() == correctout.size()); |
| 121 | + BOOST_CHECK_MESSAGE(realout == correctout, HexStr(realout) + std::string(" != ") + hexout); |
| 122 | + |
| 123 | + // Decrypt the cipher and verify that it equals the plaintext |
| 124 | + std::vector<unsigned char> decrypted(correctout.size()); |
| 125 | + AES128CBCDecrypt dec(&key[0], &iv[0], pad); |
| 126 | + size = dec.Decrypt(&correctout[0], correctout.size(), &decrypted[0]); |
| 127 | + decrypted.resize(size); |
| 128 | + BOOST_CHECK(decrypted.size() == in.size()); |
| 129 | + BOOST_CHECK_MESSAGE(decrypted == in, HexStr(decrypted) + std::string(" != ") + hexin); |
| 130 | + |
| 131 | + // Encrypt and re-decrypt substrings of the plaintext and verify that they equal each-other |
| 132 | + for(std::vector<unsigned char>::iterator i(in.begin()); i != in.end(); ++i) |
| 133 | + { |
| 134 | + std::vector<unsigned char> sub(i, in.end()); |
| 135 | + std::vector<unsigned char> subout(sub.size() + AES_BLOCKSIZE); |
| 136 | + int size = enc.Encrypt(&sub[0], sub.size(), &subout[0]); |
| 137 | + if (size != 0) |
| 138 | + { |
| 139 | + subout.resize(size); |
| 140 | + std::vector<unsigned char> subdecrypted(subout.size()); |
| 141 | + size = dec.Decrypt(&subout[0], subout.size(), &subdecrypted[0]); |
| 142 | + subdecrypted.resize(size); |
| 143 | + BOOST_CHECK(decrypted.size() == in.size()); |
| 144 | + BOOST_CHECK_MESSAGE(subdecrypted == sub, HexStr(subdecrypted) + std::string(" != ") + HexStr(sub)); |
| 145 | + } |
| 146 | + } |
| 147 | +} |
| 148 | + |
| 149 | +void TestAES256CBC(const std::string &hexkey, const std::string &hexiv, bool pad, const std::string &hexin, const std::string &hexout) |
| 150 | +{ |
| 151 | + std::vector<unsigned char> key = ParseHex(hexkey); |
| 152 | + std::vector<unsigned char> iv = ParseHex(hexiv); |
| 153 | + std::vector<unsigned char> in = ParseHex(hexin); |
| 154 | + std::vector<unsigned char> correctout = ParseHex(hexout); |
| 155 | + std::vector<unsigned char> realout(in.size() + AES_BLOCKSIZE); |
| 156 | + |
| 157 | + // Encrypt the plaintext and verify that it equals the cipher |
| 158 | + AES256CBCEncrypt enc(&key[0], &iv[0], pad); |
| 159 | + int size = enc.Encrypt(&in[0], in.size(), &realout[0]); |
| 160 | + realout.resize(size); |
| 161 | + BOOST_CHECK(realout.size() == correctout.size()); |
| 162 | + BOOST_CHECK_MESSAGE(realout == correctout, HexStr(realout) + std::string(" != ") + hexout); |
| 163 | + |
| 164 | + // Decrypt the cipher and verify that it equals the plaintext |
| 165 | + std::vector<unsigned char> decrypted(correctout.size()); |
| 166 | + AES256CBCDecrypt dec(&key[0], &iv[0], pad); |
| 167 | + size = dec.Decrypt(&correctout[0], correctout.size(), &decrypted[0]); |
| 168 | + decrypted.resize(size); |
| 169 | + BOOST_CHECK(decrypted.size() == in.size()); |
| 170 | + BOOST_CHECK_MESSAGE(decrypted == in, HexStr(decrypted) + std::string(" != ") + hexin); |
| 171 | + |
| 172 | + // Encrypt and re-decrypt substrings of the plaintext and verify that they equal each-other |
| 173 | + for(std::vector<unsigned char>::iterator i(in.begin()); i != in.end(); ++i) |
| 174 | + { |
| 175 | + std::vector<unsigned char> sub(i, in.end()); |
| 176 | + std::vector<unsigned char> subout(sub.size() + AES_BLOCKSIZE); |
| 177 | + int size = enc.Encrypt(&sub[0], sub.size(), &subout[0]); |
| 178 | + if (size != 0) |
| 179 | + { |
| 180 | + subout.resize(size); |
| 181 | + std::vector<unsigned char> subdecrypted(subout.size()); |
| 182 | + size = dec.Decrypt(&subout[0], subout.size(), &subdecrypted[0]); |
| 183 | + subdecrypted.resize(size); |
| 184 | + BOOST_CHECK(decrypted.size() == in.size()); |
| 185 | + BOOST_CHECK_MESSAGE(subdecrypted == sub, HexStr(subdecrypted) + std::string(" != ") + HexStr(sub)); |
| 186 | + } |
| 187 | + } |
| 188 | +} |
| 189 | + |
106 | 190 | std::string LongTestString(void) {
|
107 | 191 | std::string ret;
|
108 | 192 | for (int i=0; i<200000; i++) {
|
@@ -304,4 +388,55 @@ BOOST_AUTO_TEST_CASE(aes_testvectors) {
|
304 | 388 | TestAES256("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "f69f2445df4f9b17ad2b417be66c3710", "23304b7a39f9f3ff067d8d8f9e24ecc7");
|
305 | 389 | }
|
306 | 390 |
|
| 391 | +BOOST_AUTO_TEST_CASE(aes_cbc_testvectors) { |
| 392 | + |
| 393 | + // NIST AES CBC 128-bit encryption test-vectors |
| 394 | + TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", false, \ |
| 395 | + "6bc1bee22e409f96e93d7e117393172a", "7649abac8119b246cee98e9b12e9197d"); |
| 396 | + TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "7649ABAC8119B246CEE98E9B12E9197D", false, \ |
| 397 | + "ae2d8a571e03ac9c9eb76fac45af8e51", "5086cb9b507219ee95db113a917678b2"); |
| 398 | + TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "5086cb9b507219ee95db113a917678b2", false, \ |
| 399 | + "30c81c46a35ce411e5fbc1191a0a52ef", "73bed6b8e3c1743b7116e69e22229516"); |
| 400 | + TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "73bed6b8e3c1743b7116e69e22229516", false, \ |
| 401 | + "f69f2445df4f9b17ad2b417be66c3710", "3ff1caa1681fac09120eca307586e1a7"); |
| 402 | + |
| 403 | + // The same vectors with padding enabled |
| 404 | + TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", true, \ |
| 405 | + "6bc1bee22e409f96e93d7e117393172a", "7649abac8119b246cee98e9b12e9197d8964e0b149c10b7b682e6e39aaeb731c"); |
| 406 | + TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "7649ABAC8119B246CEE98E9B12E9197D", true, \ |
| 407 | + "ae2d8a571e03ac9c9eb76fac45af8e51", "5086cb9b507219ee95db113a917678b255e21d7100b988ffec32feeafaf23538"); |
| 408 | + TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "5086cb9b507219ee95db113a917678b2", true, \ |
| 409 | + "30c81c46a35ce411e5fbc1191a0a52ef", "73bed6b8e3c1743b7116e69e22229516f6eccda327bf8e5ec43718b0039adceb"); |
| 410 | + TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "73bed6b8e3c1743b7116e69e22229516", true, \ |
| 411 | + "f69f2445df4f9b17ad2b417be66c3710", "3ff1caa1681fac09120eca307586e1a78cb82807230e1321d3fae00d18cc2012"); |
| 412 | + |
| 413 | + // NIST AES CBC 256-bit encryption test-vectors |
| 414 | + TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \ |
| 415 | + "000102030405060708090A0B0C0D0E0F", false, "6bc1bee22e409f96e93d7e117393172a", \ |
| 416 | + "f58c4c04d6e5f1ba779eabfb5f7bfbd6"); |
| 417 | + TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \ |
| 418 | + "F58C4C04D6E5F1BA779EABFB5F7BFBD6", false, "ae2d8a571e03ac9c9eb76fac45af8e51", \ |
| 419 | + "9cfc4e967edb808d679f777bc6702c7d"); |
| 420 | + TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \ |
| 421 | + "9CFC4E967EDB808D679F777BC6702C7D", false, "30c81c46a35ce411e5fbc1191a0a52ef", |
| 422 | + "39f23369a9d9bacfa530e26304231461"); |
| 423 | + TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \ |
| 424 | + "39F23369A9D9BACFA530E26304231461", false, "f69f2445df4f9b17ad2b417be66c3710", \ |
| 425 | + "b2eb05e2c39be9fcda6c19078c6a9d1b"); |
| 426 | + |
| 427 | + // The same vectors with padding enabled |
| 428 | + TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \ |
| 429 | + "000102030405060708090A0B0C0D0E0F", true, "6bc1bee22e409f96e93d7e117393172a", \ |
| 430 | + "f58c4c04d6e5f1ba779eabfb5f7bfbd6485a5c81519cf378fa36d42b8547edc0"); |
| 431 | + TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \ |
| 432 | + "F58C4C04D6E5F1BA779EABFB5F7BFBD6", true, "ae2d8a571e03ac9c9eb76fac45af8e51", \ |
| 433 | + "9cfc4e967edb808d679f777bc6702c7d3a3aa5e0213db1a9901f9036cf5102d2"); |
| 434 | + TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \ |
| 435 | + "9CFC4E967EDB808D679F777BC6702C7D", true, "30c81c46a35ce411e5fbc1191a0a52ef", |
| 436 | + "39f23369a9d9bacfa530e263042314612f8da707643c90a6f732b3de1d3f5cee"); |
| 437 | + TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \ |
| 438 | + "39F23369A9D9BACFA530E26304231461", true, "f69f2445df4f9b17ad2b417be66c3710", \ |
| 439 | + "b2eb05e2c39be9fcda6c19078c6a9d1b3f461796d6b0d6b2e0c2a72b4d80e644"); |
| 440 | +} |
| 441 | + |
307 | 442 | BOOST_AUTO_TEST_SUITE_END()
|
0 commit comments