diff --git a/examples/main.cpp b/examples/main.cpp index 66b8343..ebc87b0 100644 --- a/examples/main.cpp +++ b/examples/main.cpp @@ -2,21 +2,31 @@ using namespace lklibs; -void encrypt() +void encryptWithAES() { - std::string input = "Hello, World!"; - std::string key = "asdqwerty123asd1234safd324dfdsdf"; + auto plainText = "This text will be encrypted soon"; + auto key = "mySecretKey"; - auto encrypted = CryptoService::encryptWithAES(input, key); - auto decrypted = CryptoService::decryptWithAES(encrypted, key); + auto encryptedText = CryptoService::encryptWithAES(plainText, key); - std::cout << "Encrypted: " << encrypted << std::endl; - std::cout << "Decrypted: " << decrypted << std::endl; + std::cout << "Encrypted Text: " << encryptedText << std::endl; +} + +void decryptWithAES() +{ + auto encryptedText = "D9ktQq1ZnV32JXr5YUpSJcTegqrfCHFi7aDNPGgrtsRmYLqS5YLGBKemqUwPzEeYLVN6ww4hL6ZptcZBLktbhg=="; + auto key = "mySecretKey"; + + auto plainText = CryptoService::decryptWithAES(encryptedText, key); + + std::cout << "Decrypted Text: " << plainText << std::endl; } int main() { - encrypt(); + encryptWithAES(); + + decryptWithAES(); return 0; } diff --git a/src/libcpp-crypto.hpp b/src/libcpp-crypto.hpp index 5458227..b01fdf5 100644 --- a/src/libcpp-crypto.hpp +++ b/src/libcpp-crypto.hpp @@ -32,7 +32,6 @@ SOFTWARE. #define LIBCPP_CRYPTO_HPP #include -#include #include #include #include @@ -40,9 +39,8 @@ SOFTWARE. #include #include #include -#include -#include #include +#include namespace lklibs { @@ -64,6 +62,7 @@ namespace lklibs for (auto c : input) { char_array_3[i++] = c; + if (i == 3) { char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; @@ -72,7 +71,9 @@ namespace lklibs char_array_4[3] = char_array_3[2] & 0x3f; for (i = 0; i < 4; i++) + { ret += base64_chars[char_array_4[i]]; + } i = 0; } @@ -81,17 +82,23 @@ namespace lklibs if (i) { for (int j = i; j < 3; j++) + { char_array_3[j] = '\0'; + } char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); for (int j = 0; j < i + 1; j++) + { ret += base64_chars[char_array_4[j]]; + } while (i++ < 3) + { ret += '='; + } } return ret; @@ -105,27 +112,32 @@ namespace lklibs "0123456789+/"; std::string ret; - int in_len = input.size(); int i = 0; unsigned char char_array_4[4], char_array_3[3]; for (auto c : input) { if (c == '=' || !isBase64(c)) + { break; + } char_array_4[i++] = c; if (i == 4) { for (i = 0; i < 4; i++) + { char_array_4[i] = base64_chars.find(char_array_4[i]); + } char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; for (i = 0; i < 3; i++) + { ret += char_array_3[i]; + } i = 0; } @@ -134,17 +146,23 @@ namespace lklibs if (i) { for (int j = i; j < 4; j++) + { char_array_4[j] = 0; + } - for (int j = 0; j < 4; j++) - char_array_4[j] = base64_chars.find(char_array_4[j]); + for (unsigned char& j : char_array_4) + { + j = base64_chars.find(j); + } char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; for (int j = 0; j < i - 1; j++) + { ret += char_array_3[j]; + } } return ret; @@ -162,17 +180,14 @@ namespace lklibs public: static std::string encryptWithAES(const std::string& plaintext, const std::string& key) { - if (key.size() != 32) // AES-256 requires a 256-bit key - { - throw std::invalid_argument("Key length must be 256 bits (32 characters)."); - } + std::string adjustedKey = adjustKeyLength(key); std::vector iv(AES_BLOCK_SIZE); generateRandomIV(iv); std::vector ciphertext(plaintext.size() + AES_BLOCK_SIZE); - int ciphertext_len = encrypt(reinterpret_cast(plaintext.c_str()), plaintext.length(), reinterpret_cast(key.c_str()), iv.data(), ciphertext.data()); + int ciphertext_len = encrypt(reinterpret_cast(plaintext.c_str()), plaintext.length(), reinterpret_cast(adjustedKey.c_str()), iv.data(), ciphertext.data()); ciphertext.resize(ciphertext_len); @@ -182,10 +197,7 @@ namespace lklibs static std::string decryptWithAES(const std::string& ciphertext, const std::string& key) { - if (key.size() != 32) // AES-256 requires a 256-bit key - { - throw std::invalid_argument("Key length must be 256 bits (32 characters)."); - } + std::string adjustedKey = adjustKeyLength(key); auto encryptedText = Base64Converter::decode(ciphertext); @@ -194,7 +206,7 @@ namespace lklibs std::vector plaintext(encryptedText.size() - AES_BLOCK_SIZE); - int plaintext_len = decrypt(reinterpret_cast(encryptedText.data() + AES_BLOCK_SIZE), encryptedText.size() - AES_BLOCK_SIZE, reinterpret_cast(key.c_str()), iv.data(), plaintext.data()); + int plaintext_len = decrypt(reinterpret_cast(encryptedText.data() + AES_BLOCK_SIZE), encryptedText.size() - AES_BLOCK_SIZE, reinterpret_cast(adjustedKey.c_str()), iv.data(), plaintext.data()); if (plaintext_len == -1) { @@ -215,11 +227,14 @@ namespace lklibs static void handleErrors() { unsigned long errCode; - while (errCode = ERR_get_error()) + + while ((errCode = ERR_get_error())) { - char* err = ERR_error_string(errCode, NULL); - std::cerr << err << std::endl; + char errBuff[256]; + ERR_error_string_n(errCode, errBuff, sizeof(errBuff)); + std::cerr << errBuff << std::endl; } + throw std::runtime_error("An OpenSSL error occurred"); } @@ -299,6 +314,24 @@ namespace lklibs handleErrors(); } } + + static std::string adjustKeyLength(const std::string& key) + { + if (key.size() == 32) + { + return key; + } + else if (key.size() > 32) + { + return key.substr(0, 32); + } + else + { + std::string adjusted_key = key; + adjusted_key.append(32 - key.size(), '0'); + return adjusted_key; + } + } }; } #endif //LIBCPP_CRYPTO_HPP diff --git a/test/test.cpp b/test/test.cpp index e69de29..d778c82 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -0,0 +1,21 @@ +#include "libcpp-crypto.hpp" +#include + +using namespace lklibs; + +TEST(EncryptWithAESTest, EncryptionWithAESMustBeCompletedSuccessfullyWithAValidKey) +{ + std::string plainText = "Test message to be used during tests"; + std::string key = "mySecretKey"; + + auto encryptedText = CryptoService::encryptWithAES(plainText, key); + + ASSERT_FALSE(encryptedText.empty()) << "encryptedText is empty"; +} + +int main(int argc, char** argv) +{ + testing::InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +}