From 2d647750b2825f6afb91aba96c481c1d3a90fff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 13 Mar 2017 22:25:17 +0100 Subject: [PATCH 1/4] Add basic AES128-CTR unit tests --- test/libdevcrypto/AES.cpp | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/test/libdevcrypto/AES.cpp b/test/libdevcrypto/AES.cpp index 55197986a49..c5fb09be724 100644 --- a/test/libdevcrypto/AES.cpp +++ b/test/libdevcrypto/AES.cpp @@ -31,9 +31,34 @@ BOOST_AUTO_TEST_SUITE(Crypto) BOOST_FIXTURE_TEST_SUITE(AES, TestOutputHelper) +BOOST_AUTO_TEST_CASE(AesEncryptConst) +{ + auto key = asBytes("0123456789abcdef"); + h128 iv; + iv[5] = 1; + auto msg = asBytes("Hello!........................................."); + auto e = encryptAES128CTR(&key, iv, &msg); + auto expected = "0378b494602bb95ef9e4832f9ba6cba50ea3423b5b2904a5ea66cfef31019ca39135f7e551829e85f64a099edc223d"; + BOOST_CHECK_GT(msg.size(), 32); + BOOST_CHECK_EQUAL(msg.size(), e.size()); + BOOST_CHECK_EQUAL(toHex(e), expected); +} + +BOOST_AUTO_TEST_CASE(AesDecryptConst) +{ + auto key = asBytes("0123456789abcdef"); + h128 iv; + iv[5] = 1; + auto msg = asBytes("Hello!........................................."); + auto d = decryptAES128CTR(&key, iv, &msg); + auto expected = "0378b494602bb95ef9e4832f9ba6cba50ea3423b5b2904a5ea66cfef31019ca39135f7e551829e85f64a099edc223d"; + BOOST_CHECK_GT(msg.size(), 32); + BOOST_CHECK_EQUAL(msg.size(), d.size()); + BOOST_CHECK_EQUAL(toHex(d.makeInsecure()), expected); +} + BOOST_AUTO_TEST_CASE(AesDecrypt) { - cnote << "AesDecrypt"; bytes seed = fromHex("2dbaead416c20cfd00c2fc9f1788ff9f965a2000799c96a624767cb0e1e90d2d7191efdd92349226742fdc73d1d87e2d597536c4641098b9a89836c94f58a2ab4c525c27c4cb848b3e22ea245b2bc5c8c7beaa900b0c479253fc96fce7ffc621"); KeyPair kp(sha3Secure(aesDecrypt(&seed, "test"))); BOOST_CHECK(Address("07746f871de684297923f933279555dda418f8a2") == kp.address()); @@ -41,7 +66,6 @@ BOOST_AUTO_TEST_CASE(AesDecrypt) BOOST_AUTO_TEST_CASE(AesDecryptWrongSeed) { - cnote << "AesDecryptWrongSeed"; bytes seed = fromHex("badaead416c20cfd00c2fc9f1788ff9f965a2000799c96a624767cb0e1e90d2d7191efdd92349226742fdc73d1d87e2d597536c4641098b9a89836c94f58a2ab4c525c27c4cb848b3e22ea245b2bc5c8c7beaa900b0c479253fc96fce7ffc621"); KeyPair kp(sha3Secure(aesDecrypt(&seed, "test"))); BOOST_CHECK(Address("07746f871de684297923f933279555dda418f8a2") != kp.address()); @@ -49,7 +73,6 @@ BOOST_AUTO_TEST_CASE(AesDecryptWrongSeed) BOOST_AUTO_TEST_CASE(AesDecryptWrongPassword) { - cnote << "AesDecryptWrongPassword"; bytes seed = fromHex("2dbaead416c20cfd00c2fc9f1788ff9f965a2000799c96a624767cb0e1e90d2d7191efdd92349226742fdc73d1d87e2d597536c4641098b9a89836c94f58a2ab4c525c27c4cb848b3e22ea245b2bc5c8c7beaa900b0c479253fc96fce7ffc621"); KeyPair kp(sha3Secure(aesDecrypt(&seed, "badtest"))); BOOST_CHECK(Address("07746f871de684297923f933279555dda418f8a2") != kp.address()); @@ -57,21 +80,18 @@ BOOST_AUTO_TEST_CASE(AesDecryptWrongPassword) BOOST_AUTO_TEST_CASE(AesDecryptFailInvalidSeed) { - cnote << "AesDecryptFailInvalidSeed"; bytes seed = fromHex("xdbaead416c20cfd00c2fc9f1788ff9f965a2000799c96a624767cb0e1e90d2d7191efdd92349226742fdc73d1d87e2d597536c4641098b9a89836c94f58a2ab4c525c27c4cb848b3e22ea245b2bc5c8c7beaa900b0c479253fc96fce7ffc621"); BOOST_CHECK(bytes() == aesDecrypt(&seed, "test")); } BOOST_AUTO_TEST_CASE(AesDecryptFailInvalidSeedSize) { - cnote << "AesDecryptFailInvalidSeedSize"; bytes seed = fromHex("000102030405060708090a0b0c0d0e0f"); BOOST_CHECK(bytes() == aesDecrypt(&seed, "test")); } BOOST_AUTO_TEST_CASE(AesDecryptFailInvalidSeed2) { - cnote << "AesDecryptFailInvalidSeed2"; bytes seed = fromHex("000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"); BOOST_CHECK(bytes() == aesDecrypt(&seed, "test")); } From c93e3b842792543fc591e0bd65afc04b8fe66024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 14 Mar 2017 19:12:58 +0100 Subject: [PATCH 2/4] Add AES128CTR tests --- test/libdevcrypto/AES.cpp | 42 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/test/libdevcrypto/AES.cpp b/test/libdevcrypto/AES.cpp index c5fb09be724..2eae7e050b6 100644 --- a/test/libdevcrypto/AES.cpp +++ b/test/libdevcrypto/AES.cpp @@ -16,6 +16,7 @@ */ #include +#include #include #include #include @@ -57,6 +58,47 @@ BOOST_AUTO_TEST_CASE(AesDecryptConst) BOOST_CHECK_EQUAL(toHex(d.makeInsecure()), expected); } +BOOST_AUTO_TEST_CASE(AES128CTR_random) +{ + std::mt19937 gen(static_cast(std::rand())); + std::uniform_int_distribution<> dis(1, 6); + constexpr auto numBytes = 234567; + bytes b; + std::generate_n(std::back_inserter(b), numBytes, [&]{ return static_cast(dis(gen)); }); + BOOST_CHECK_EQUAL(b.size(), numBytes); + + auto key = asBytes("ABCDEF0123456789"); + auto iv = h128::random(); + + auto e = encryptAES128CTR(&key, iv, &b); + auto d = decryptAES128CTR(&key, iv, &e); + BOOST_CHECK(d.makeInsecure() == b); +} + +BOOST_AUTO_TEST_CASE(AES128CTREncryptNISTTestVector) +{ + // Test vectors from http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf + auto key = fromHex("2b7e151628aed2a6abf7158809cf4f3c"); + auto initCounter = h128("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"); + auto plainText = fromHex("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"); + auto cipherText = "874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"; + + auto e = encryptAES128CTR(&key, initCounter, &plainText); + BOOST_CHECK_EQUAL(toHex(e), cipherText); +} + +BOOST_AUTO_TEST_CASE(AES128CTRDecryptNISTTestVector) +{ + // Test vectors from http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf + auto key = fromHex("2b7e151628aed2a6abf7158809cf4f3c"); + auto initCounter = h128("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"); + auto cipherText = fromHex("874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"); + auto plainText = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"; + + auto d = decryptAES128CTR(&key, initCounter, &cipherText); + BOOST_CHECK_EQUAL(toHex(d.makeInsecure()), plainText); +} + BOOST_AUTO_TEST_CASE(AesDecrypt) { bytes seed = fromHex("2dbaead416c20cfd00c2fc9f1788ff9f965a2000799c96a624767cb0e1e90d2d7191efdd92349226742fdc73d1d87e2d597536c4641098b9a89836c94f58a2ab4c525c27c4cb848b3e22ea245b2bc5c8c7beaa900b0c479253fc96fce7ffc621"); From 61ae37edf09812828c8c42c5191d2b704309716f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 13 Mar 2017 22:47:56 +0100 Subject: [PATCH 3/4] Experimental AES replacement --- libdevcrypto/AES.cpp | 277 ++++++++++++++++++++++++++++++++++++++++ libdevcrypto/AES.h | 2 + libdevcrypto/Common.cpp | 44 ++----- 3 files changed, 291 insertions(+), 32 deletions(-) diff --git a/libdevcrypto/AES.cpp b/libdevcrypto/AES.cpp index 4422f811fb7..c3ea0393691 100644 --- a/libdevcrypto/AES.cpp +++ b/libdevcrypto/AES.cpp @@ -31,6 +31,283 @@ using namespace dev; using namespace dev::crypto; using namespace CryptoPP; +// The number of columns comprising a state in AES. This is a constant in AES. Value=4 +#define Nb 4 +// The number of 32 bit words in a key. +#define Nk 4 +// Key length in bytes [128 bit] +#define KEYLEN 16 +// The number of rounds in AES Cipher. +#define Nr 10 + + +/*****************************************************************************/ +/* Private variables: */ +/*****************************************************************************/ +// state - array holding the intermediate results during decryption. +typedef uint8_t state_t[4][4]; + +// The array that stores the round keys. +static uint8_t RoundKey[176]; + +// The Key input to the AES Program +static const uint8_t* Key; + +// The lookup-tables are marked const so they can be placed in read-only storage instead of RAM +// The numbers below can be computed dynamically trading ROM for RAM - +// This can be useful in (embedded) bootloader applications, where ROM is often limited. +static const uint8_t sbox[256] = { + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; + +// The round constant word array, Rcon[i], contains the values given by +// x to th e power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8) +// Note that i starts at 1, not 0). +static const uint8_t Rcon[255] = { + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, + 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, + 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, + 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, + 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, + 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, + 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, + 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, + 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, + 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, + 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, + 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, + 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, + 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, + 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, + 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb }; + + +static uint8_t getSBoxValue(uint8_t num) +{ + return sbox[num]; +} + +// This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states. +static void KeyExpansion(void) +{ + uint32_t i, j, k; + uint8_t tempa[4]; // Used for the column/row operations + + // The first round key is the key itself. + for(i = 0; i < Nk; ++i) + { + RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; + RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; + RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; + RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; + } + + // All other round keys are found from the previous round keys. + for(; (i < (Nb * (Nr + 1))); ++i) + { + for(j = 0; j < 4; ++j) + { + tempa[j]=RoundKey[(i-1) * 4 + j]; + } + if (i % Nk == 0) + { + // This function rotates the 4 bytes in a word to the left once. + // [a0,a1,a2,a3] becomes [a1,a2,a3,a0] + + // Function RotWord() + { + k = tempa[0]; + tempa[0] = tempa[1]; + tempa[1] = tempa[2]; + tempa[2] = tempa[3]; + tempa[3] = k; + } + + // SubWord() is a function that takes a four-byte input word and + // applies the S-box to each of the four bytes to produce an output word. + + // Function Subword() + { + tempa[0] = getSBoxValue(tempa[0]); + tempa[1] = getSBoxValue(tempa[1]); + tempa[2] = getSBoxValue(tempa[2]); + tempa[3] = getSBoxValue(tempa[3]); + } + + tempa[0] = tempa[0] ^ Rcon[i/Nk]; + } + RoundKey[i * 4 + 0] = RoundKey[(i - Nk) * 4 + 0] ^ tempa[0]; + RoundKey[i * 4 + 1] = RoundKey[(i - Nk) * 4 + 1] ^ tempa[1]; + RoundKey[i * 4 + 2] = RoundKey[(i - Nk) * 4 + 2] ^ tempa[2]; + RoundKey[i * 4 + 3] = RoundKey[(i - Nk) * 4 + 3] ^ tempa[3]; + } +} + +// This function adds the round key to state. +// The round key is added to the state by an XOR function. +static void AddRoundKey(state_t* state, uint8_t round) +{ + uint8_t i,j; + for(i=0;i<4;++i) + { + for(j = 0; j < 4; ++j) + { + (*state)[i][j] ^= RoundKey[round * Nb * 4 + i * Nb + j]; + } + } +} + +// The SubBytes Function Substitutes the values in the +// state matrix with values in an S-box. +static void SubBytes(state_t* state) +{ + uint8_t i, j; + for(i = 0; i < 4; ++i) + { + for(j = 0; j < 4; ++j) + { + (*state)[j][i] = getSBoxValue((*state)[j][i]); + } + } +} + +// The ShiftRows() function shifts the rows in the state to the left. +// Each row is shifted with different offset. +// Offset = Row number. So the first row is not shifted. +static void ShiftRows(state_t* state) +{ + uint8_t temp; + + // Rotate first row 1 columns to left + temp = (*state)[0][1]; + (*state)[0][1] = (*state)[1][1]; + (*state)[1][1] = (*state)[2][1]; + (*state)[2][1] = (*state)[3][1]; + (*state)[3][1] = temp; + + // Rotate second row 2 columns to left + temp = (*state)[0][2]; + (*state)[0][2] = (*state)[2][2]; + (*state)[2][2] = temp; + + temp = (*state)[1][2]; + (*state)[1][2] = (*state)[3][2]; + (*state)[3][2] = temp; + + // Rotate third row 3 columns to left + temp = (*state)[0][3]; + (*state)[0][3] = (*state)[3][3]; + (*state)[3][3] = (*state)[2][3]; + (*state)[2][3] = (*state)[1][3]; + (*state)[1][3] = temp; +} + +static uint8_t xtime(uint8_t x) +{ + return ((x<<1) ^ (((x>>7) & 1) * 0x1b)); +} + +// MixColumns function mixes the columns of the state matrix +static void MixColumns(state_t* state) +{ + uint8_t i; + uint8_t Tmp,Tm,t; + for(i = 0; i < 4; ++i) + { + t = (*state)[i][0]; + Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ; + Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ; + Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ; + Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ; + Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ; + } +} + + +// Cipher is the main function that encrypts the PlainText. +static void Cipher(state_t* state) +{ + uint8_t round = 0; + + // Add the First round key to the state before starting the rounds. + AddRoundKey(state, 0); + + // There will be Nr rounds. + // The first Nr-1 rounds are identical. + // These Nr-1 rounds are executed in the loop below. + for(round = 1; round < Nr; ++round) + { + SubBytes(state); + ShiftRows(state); + MixColumns(state); + AddRoundKey(state, round); + } + + // The last round is given below. + // The MixColumns function is not here in the last round. + SubBytes(state); + ShiftRows(state); + AddRoundKey(state, Nr); +} + +static void BlockCopy(uint8_t* output, const uint8_t* input) +{ + uint8_t i; + for (i=0;i= 0; --j) + { + ++(ctr[j]); + + if (ctr[j]) + break; + } + } + + output[i] = (input[i]) ^ (((uint8_t*)state)[i & 0x0000000F]); + ++i; + } +} + + + bytes dev::aesDecrypt(bytesConstRef _ivCipher, std::string const& _password, unsigned _rounds, bytesConstRef _salt) { bytes pw = asBytes(_password); diff --git a/libdevcrypto/AES.h b/libdevcrypto/AES.h index 6f72369f634..33139d62c89 100644 --- a/libdevcrypto/AES.h +++ b/libdevcrypto/AES.h @@ -29,6 +29,8 @@ namespace dev { +void AES128_CTR_process_buffer(uint8_t* output, const uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv); + bytes aesDecrypt(bytesConstRef _cipher, std::string const& _password, unsigned _rounds = 2000, bytesConstRef _salt = bytesConstRef()); } diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index 6ef6cbbb308..a95dcdce612 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -163,42 +163,22 @@ std::pair dev::encryptSymNoAuth(SecureFixedHash<16> const& _k, byte bytes dev::encryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _plain) { - if (_k.size() != 16 && _k.size() != 24 && _k.size() != 32) - return bytes(); - SecByteBlock key(_k.data(), _k.size()); - try - { - CTR_Mode::Encryption e; - e.SetKeyWithIV(key, key.size(), _iv.data()); - bytes ret(_plain.size()); - e.ProcessData(ret.data(), _plain.data(), _plain.size()); - return ret; - } - catch (CryptoPP::Exception& _e) - { - cerr << _e.what() << endl; - return bytes(); - } + if (_k.size() != 16) + return {}; + + bytes ret(_plain.size()); + AES128_CTR_process_buffer(ret.data(), _plain.data(), _plain.size(), _k.data(), _iv.data()); + return ret; } bytesSec dev::decryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _cipher) { - if (_k.size() != 16 && _k.size() != 24 && _k.size() != 32) - return bytesSec(); - SecByteBlock key(_k.data(), _k.size()); - try - { - CTR_Mode::Decryption d; - d.SetKeyWithIV(key, key.size(), _iv.data()); - bytesSec ret(_cipher.size()); - d.ProcessData(ret.writable().data(), _cipher.data(), _cipher.size()); - return ret; - } - catch (CryptoPP::Exception& _e) - { - cerr << _e.what() << endl; - return bytesSec(); - } + if (_k.size() != 16) + return {}; + + bytesSec ret(_cipher.size()); + AES128_CTR_process_buffer(ret.writable().data(), _cipher.data(), _cipher.size(), _k.data(), _iv.data()); + return ret; } Public dev::recover(Signature const& _sig, h256 const& _message) From 0dac6cafedbf194328705e80b4b79998eae3d458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 14 Mar 2017 18:13:43 +0100 Subject: [PATCH 4/4] Refactor AES128-CTR --- libdevcrypto/AES.cpp | 314 ++++++++++++++++------------------- libdevcrypto/AES.h | 16 +- libdevcrypto/Common.cpp | 20 --- libdevcrypto/Common.h | 18 +- libdevcrypto/CryptoPP.cpp | 1 + libdevcrypto/SecretStore.cpp | 2 + libethcore/KeyManager.cpp | 3 +- test/libdevcrypto/crypto.cpp | 1 + 8 files changed, 168 insertions(+), 207 deletions(-) diff --git a/libdevcrypto/AES.cpp b/libdevcrypto/AES.cpp index c3ea0393691..0af9da94d90 100644 --- a/libdevcrypto/AES.cpp +++ b/libdevcrypto/AES.cpp @@ -28,101 +28,85 @@ using namespace std; using namespace dev; -using namespace dev::crypto; using namespace CryptoPP; -// The number of columns comprising a state in AES. This is a constant in AES. Value=4 -#define Nb 4 -// The number of 32 bit words in a key. -#define Nk 4 -// Key length in bytes [128 bit] -#define KEYLEN 16 -// The number of rounds in AES Cipher. -#define Nr 10 - - -/*****************************************************************************/ -/* Private variables: */ -/*****************************************************************************/ -// state - array holding the intermediate results during decryption. -typedef uint8_t state_t[4][4]; - -// The array that stores the round keys. -static uint8_t RoundKey[176]; - -// The Key input to the AES Program -static const uint8_t* Key; - -// The lookup-tables are marked const so they can be placed in read-only storage instead of RAM -// The numbers below can be computed dynamically trading ROM for RAM - -// This can be useful in (embedded) bootloader applications, where ROM is often limited. -static const uint8_t sbox[256] = { - //0 1 2 3 4 5 6 7 8 9 A B C D E F - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; +namespace +{ + +// This code is modified version of https://github.com/kokke/tiny-AES128-C. + +constexpr int Nb = 4; ///< Number of columns in a AES state. +constexpr int Nk = 4; ///< The number of 32 bit words in a key. +constexpr int c_keySize = 16; ///< Key length in bytes (128 bit). +constexpr int Nr = 10; ///< The number of rounds in AES Cipher. + +using state_t = byte[4][4]; + +/// The lookup-tables. +const byte sbox[256] = { + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +}; // The round constant word array, Rcon[i], contains the values given by // x to th e power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8) // Note that i starts at 1, not 0). -static const uint8_t Rcon[255] = { - 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, - 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, - 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, - 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, - 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, - 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, - 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, - 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, - 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, - 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, - 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, - 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, - 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, - 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, - 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, - 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb }; - - -static uint8_t getSBoxValue(uint8_t num) -{ - return sbox[num]; -} - -// This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states. -static void KeyExpansion(void) +const byte Rcon[255] = { + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, + 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, + 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, + 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, + 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, + 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, + 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, + 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, + 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, + 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, + 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, + 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, + 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, + 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, + 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, + 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb +}; + +/// Produces Nb(Nr+1) round keys. The round keys are used in each round +/// to decrypt the states. +void keyExpansion(byte* roundKeys, byte const* key) { - uint32_t i, j, k; - uint8_t tempa[4]; // Used for the column/row operations + int i; + byte tempa[4]; // Used for the column/row operations // The first round key is the key itself. - for(i = 0; i < Nk; ++i) + for (i = 0; i < Nk; ++i) { - RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; - RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; - RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; - RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; + roundKeys[(i * 4) + 0] = key[(i * 4) + 0]; + roundKeys[(i * 4) + 1] = key[(i * 4) + 1]; + roundKeys[(i * 4) + 2] = key[(i * 4) + 2]; + roundKeys[(i * 4) + 3] = key[(i * 4) + 3]; } // All other round keys are found from the previous round keys. for(; (i < (Nb * (Nr + 1))); ++i) { - for(j = 0; j < 4; ++j) + for (int j = 0; j < 4; ++j) { - tempa[j]=RoundKey[(i-1) * 4 + j]; + tempa[j] = roundKeys[(i-1) * 4 + j]; } if (i % Nk == 0) { @@ -131,7 +115,7 @@ static void KeyExpansion(void) // Function RotWord() { - k = tempa[0]; + auto k = tempa[0]; tempa[0] = tempa[1]; tempa[1] = tempa[2]; tempa[2] = tempa[3]; @@ -143,55 +127,45 @@ static void KeyExpansion(void) // Function Subword() { - tempa[0] = getSBoxValue(tempa[0]); - tempa[1] = getSBoxValue(tempa[1]); - tempa[2] = getSBoxValue(tempa[2]); - tempa[3] = getSBoxValue(tempa[3]); + tempa[0] = sbox[tempa[0]]; + tempa[1] = sbox[tempa[1]]; + tempa[2] = sbox[tempa[2]]; + tempa[3] = sbox[tempa[3]]; } tempa[0] = tempa[0] ^ Rcon[i/Nk]; } - RoundKey[i * 4 + 0] = RoundKey[(i - Nk) * 4 + 0] ^ tempa[0]; - RoundKey[i * 4 + 1] = RoundKey[(i - Nk) * 4 + 1] ^ tempa[1]; - RoundKey[i * 4 + 2] = RoundKey[(i - Nk) * 4 + 2] ^ tempa[2]; - RoundKey[i * 4 + 3] = RoundKey[(i - Nk) * 4 + 3] ^ tempa[3]; + roundKeys[i * 4 + 0] = roundKeys[(i - Nk) * 4 + 0] ^ tempa[0]; + roundKeys[i * 4 + 1] = roundKeys[(i - Nk) * 4 + 1] ^ tempa[1]; + roundKeys[i * 4 + 2] = roundKeys[(i - Nk) * 4 + 2] ^ tempa[2]; + roundKeys[i * 4 + 3] = roundKeys[(i - Nk) * 4 + 3] ^ tempa[3]; } } -// This function adds the round key to state. -// The round key is added to the state by an XOR function. -static void AddRoundKey(state_t* state, uint8_t round) +/// Adds the round key to state. +/// The round key is added to the state by an XOR function. +void addRoundKey(state_t* state, byte const* roundKeys, int round) { - uint8_t i,j; - for(i=0;i<4;++i) - { - for(j = 0; j < 4; ++j) - { - (*state)[i][j] ^= RoundKey[round * Nb * 4 + i * Nb + j]; - } - } + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 4; ++j) + (*state)[i][j] ^= roundKeys[round * Nb * 4 + i * Nb + j]; } -// The SubBytes Function Substitutes the values in the -// state matrix with values in an S-box. -static void SubBytes(state_t* state) +/// Substitutes the values in the +/// state matrix with values in an S-box. +void subBytes(state_t* state) { - uint8_t i, j; - for(i = 0; i < 4; ++i) - { - for(j = 0; j < 4; ++j) - { - (*state)[j][i] = getSBoxValue((*state)[j][i]); - } - } + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 4; ++j) + (*state)[j][i] = sbox[(*state)[j][i]]; } -// The ShiftRows() function shifts the rows in the state to the left. -// Each row is shifted with different offset. -// Offset = Row number. So the first row is not shifted. -static void ShiftRows(state_t* state) +/// Shifts the rows in the state to the left. +/// Each row is shifted with different offset. +/// Offset = Row number. So the first row is not shifted. +void shiftRows(state_t* state) { - uint8_t temp; + byte temp; // Rotate first row 1 columns to left temp = (*state)[0][1]; @@ -205,108 +179,112 @@ static void ShiftRows(state_t* state) (*state)[0][2] = (*state)[2][2]; (*state)[2][2] = temp; - temp = (*state)[1][2]; + temp = (*state)[1][2]; (*state)[1][2] = (*state)[3][2]; (*state)[3][2] = temp; // Rotate third row 3 columns to left - temp = (*state)[0][3]; + temp = (*state)[0][3]; (*state)[0][3] = (*state)[3][3]; (*state)[3][3] = (*state)[2][3]; (*state)[2][3] = (*state)[1][3]; (*state)[1][3] = temp; } -static uint8_t xtime(uint8_t x) +inline byte xtime(byte x) { - return ((x<<1) ^ (((x>>7) & 1) * 0x1b)); + return static_cast(x<<1) ^ (((x>>7) & 1) * 0x1b); } // MixColumns function mixes the columns of the state matrix -static void MixColumns(state_t* state) +void mixColumns(state_t* state) { - uint8_t i; - uint8_t Tmp,Tm,t; - for(i = 0; i < 4; ++i) + byte Tmp,Tm,t; + for(auto i = 0; i < 4; ++i) { t = (*state)[i][0]; Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ; Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ; Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ; Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ; - Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ; + Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ; } } - // Cipher is the main function that encrypts the PlainText. -static void Cipher(state_t* state) +void cipher(state_t* state, byte const* roundKeys) { - uint8_t round = 0; - // Add the First round key to the state before starting the rounds. - AddRoundKey(state, 0); + addRoundKey(state, roundKeys, 0); // There will be Nr rounds. // The first Nr-1 rounds are identical. // These Nr-1 rounds are executed in the loop below. - for(round = 1; round < Nr; ++round) + for (int round = 1; round < Nr; ++round) { - SubBytes(state); - ShiftRows(state); - MixColumns(state); - AddRoundKey(state, round); + subBytes(state); + shiftRows(state); + mixColumns(state); + addRoundKey(state, roundKeys, round); } // The last round is given below. // The MixColumns function is not here in the last round. - SubBytes(state); - ShiftRows(state); - AddRoundKey(state, Nr); + subBytes(state); + shiftRows(state); + addRoundKey(state, roundKeys, Nr); } -static void BlockCopy(uint8_t* output, const uint8_t* input) +void AES128_CTR_process_buffer(byte* output, const byte* input, size_t length, const byte* key, const byte* iv) { - uint8_t i; - for (i=0;i= 0; --j) + { + ++(ctr[j]); + + if (ctr[j]) + break; + } + } + + output[i] = (input[i]) ^ ((&state[0][0])[i & 0x0000000F]); } } +} -void dev::AES128_CTR_process_buffer(uint8_t* output, const uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv) +bytes dev::encryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _plain) { - state_t state; - uint32_t i = 0; - uint8_t ctr[KEYLEN]; - - BlockCopy(ctr, iv); - Key = key; - KeyExpansion(); - - while (i < length) - { - if ((i & 0x0000000F) == 0) - { - BlockCopy(&state[0][0], ctr); - Cipher(&state); - - for (int j = KEYLEN - 1; j >= 0; --j) - { - ++(ctr[j]); - - if (ctr[j]) - break; - } - } + if (_k.size() != 16) + return {}; - output[i] = (input[i]) ^ (((uint8_t*)state)[i & 0x0000000F]); - ++i; - } + bytes ret(_plain.size()); + AES128_CTR_process_buffer(ret.data(), _plain.data(), _plain.size(), _k.data(), _iv.data()); + return ret; } +bytesSec dev::decryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _cipher) +{ + if (_k.size() != 16) + return {}; + bytesSec ret(_cipher.size()); + AES128_CTR_process_buffer(ret.writable().data(), _cipher.data(), _cipher.size(), _k.data(), _iv.data()); + return ret; +} bytes dev::aesDecrypt(bytesConstRef _ivCipher, std::string const& _password, unsigned _rounds, bytesConstRef _salt) { diff --git a/libdevcrypto/AES.h b/libdevcrypto/AES.h index 33139d62c89..498e60cbf8c 100644 --- a/libdevcrypto/AES.h +++ b/libdevcrypto/AES.h @@ -24,12 +24,24 @@ #pragma once -#include "Common.h" +#include namespace dev { -void AES128_CTR_process_buffer(uint8_t* output, const uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv); +/// Encrypts payload with specified IV/ctr using AES128-CTR. +bytes encryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _plain); + +/// Decrypts payload with specified IV/ctr using AES128-CTR. +bytesSec decryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _cipher); + +/// Encrypts payload with specified IV/ctr using AES128-CTR. +inline bytes encryptSymNoAuth(SecureFixedHash<16> const& _k, h128 const& _iv, bytesConstRef _plain) { return encryptAES128CTR(_k.ref(), _iv, _plain); } +inline bytes encryptSymNoAuth(SecureFixedHash<32> const& _k, h128 const& _iv, bytesConstRef _plain) { return encryptAES128CTR(_k.ref(), _iv, _plain); } + +/// Decrypts payload with specified IV/ctr using AES128-CTR. +inline bytesSec decryptSymNoAuth(SecureFixedHash<16> const& _k, h128 const& _iv, bytesConstRef _cipher) { return decryptAES128CTR(_k.ref(), _iv, _cipher); } +inline bytesSec decryptSymNoAuth(SecureFixedHash<32> const& _k, h128 const& _iv, bytesConstRef _cipher) { return decryptAES128CTR(_k.ref(), _iv, _cipher); } bytes aesDecrypt(bytesConstRef _cipher, std::string const& _password, unsigned _rounds = 2000, bytesConstRef _salt = bytesConstRef()); diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index a95dcdce612..5d3c0734bf9 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -161,26 +161,6 @@ std::pair dev::encryptSymNoAuth(SecureFixedHash<16> const& _k, byte return make_pair(encryptSymNoAuth(_k, iv, _plain), iv); } -bytes dev::encryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _plain) -{ - if (_k.size() != 16) - return {}; - - bytes ret(_plain.size()); - AES128_CTR_process_buffer(ret.data(), _plain.data(), _plain.size(), _k.data(), _iv.data()); - return ret; -} - -bytesSec dev::decryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _cipher) -{ - if (_k.size() != 16) - return {}; - - bytesSec ret(_cipher.size()); - AES128_CTR_process_buffer(ret.writable().data(), _cipher.data(), _cipher.size(), _k.data(), _iv.data()); - return ret; -} - Public dev::recover(Signature const& _sig, h256 const& _message) { int v = _sig[64]; diff --git a/libdevcrypto/Common.h b/libdevcrypto/Common.h index ad95bcbada0..a67b6f0c1dc 100644 --- a/libdevcrypto/Common.h +++ b/libdevcrypto/Common.h @@ -115,26 +115,12 @@ bool decryptECIES(Secret const& _k, bytesConstRef _sharedMacData, bytesConstRef /// Encrypts payload with random IV/ctr using AES128-CTR. std::pair encryptSymNoAuth(SecureFixedHash<16> const& _k, bytesConstRef _plain); -/// Encrypts payload with specified IV/ctr using AES128-CTR. -bytes encryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _plain); - -/// Decrypts payload with specified IV/ctr using AES128-CTR. -bytesSec decryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _cipher); - -/// Encrypts payload with specified IV/ctr using AES128-CTR. -inline bytes encryptSymNoAuth(SecureFixedHash<16> const& _k, h128 const& _iv, bytesConstRef _plain) { return encryptAES128CTR(_k.ref(), _iv, _plain); } -inline bytes encryptSymNoAuth(SecureFixedHash<32> const& _k, h128 const& _iv, bytesConstRef _plain) { return encryptAES128CTR(_k.ref(), _iv, _plain); } - -/// Decrypts payload with specified IV/ctr using AES128-CTR. -inline bytesSec decryptSymNoAuth(SecureFixedHash<16> const& _k, h128 const& _iv, bytesConstRef _cipher) { return decryptAES128CTR(_k.ref(), _iv, _cipher); } -inline bytesSec decryptSymNoAuth(SecureFixedHash<32> const& _k, h128 const& _iv, bytesConstRef _cipher) { return decryptAES128CTR(_k.ref(), _iv, _cipher); } - /// Recovers Public key from signed message hash. Public recover(Signature const& _sig, h256 const& _hash); - + /// Returns siganture of message hash. Signature sign(Secret const& _k, h256 const& _hash); - + /// Verify signature. bool verify(Public const& _k, Signature const& _s, h256 const& _hash); diff --git a/libdevcrypto/CryptoPP.cpp b/libdevcrypto/CryptoPP.cpp index 66aaf93ffdc..55b529b241a 100644 --- a/libdevcrypto/CryptoPP.cpp +++ b/libdevcrypto/CryptoPP.cpp @@ -27,6 +27,7 @@ #include #include #include "ECDHE.h" +#include "AES.h" static_assert(CRYPTOPP_VERSION == 570, "Wrong Crypto++ version"); diff --git a/libdevcrypto/SecretStore.cpp b/libdevcrypto/SecretStore.cpp index 0b792f117cb..e508c434fa0 100644 --- a/libdevcrypto/SecretStore.cpp +++ b/libdevcrypto/SecretStore.cpp @@ -30,6 +30,8 @@ #include #include #include +#include "AES.h" + using namespace std; using namespace dev; namespace js = json_spirit; diff --git a/libethcore/KeyManager.cpp b/libethcore/KeyManager.cpp index 18e9c02ed27..129719a7702 100644 --- a/libethcore/KeyManager.cpp +++ b/libethcore/KeyManager.cpp @@ -21,13 +21,14 @@ #include "KeyManager.h" #include -#include #include #include #include #include #include #include +#include + using namespace std; using namespace dev; using namespace eth; diff --git a/test/libdevcrypto/crypto.cpp b/test/libdevcrypto/crypto.cpp index 875db598ba7..5b69703023c 100644 --- a/test/libdevcrypto/crypto.cpp +++ b/test/libdevcrypto/crypto.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include using namespace std;