// // Created by Stepan Usatiuk on 30.04.2023. // #include "AES.h" #include #include #include #include "Exception.h" std::vector AES::encrypt(const std::vector &in, const std::string &password, const std::string &salt) { return AES::encrypt(in, AES::deriveKey(password, salt)); } std::vector AES::decrypt(const std::vector &in, const std::string &password, const std::string &salt) { return AES::decrypt(in, AES::deriveKey(password, salt)); } std::vector AES::encrypt(const std::vector &in, const std::array &key) { std::unique_ptr ctx(EVP_CIPHER_CTX_new(), &EVP_CIPHER_CTX_free); if (!ctx) throw Exception("Error initializing encryption context!"); std::vector out(in.size() + AES_BLOCK_SIZE + 32); if (!RAND_bytes(reinterpret_cast(out.data()), 32)) throw Exception("Error generating IV!"); if (!EVP_EncryptInit_ex(ctx.get(), EVP_aes_256_cbc(), nullptr, key.data(), reinterpret_cast(out.data()))) throw Exception("Error encrypting!"); int outlen = static_cast(out.size()) - 32; if (!EVP_EncryptUpdate(ctx.get(), reinterpret_cast(out.data() + 32), &outlen, reinterpret_cast(in.data()), static_cast(in.size()))) throw Exception("Error encrypting!"); int finlen = 0; if (!EVP_EncryptFinal_ex(ctx.get(), reinterpret_cast(out.data() + outlen + 32), &finlen)) throw Exception("Error encrypting!"); out.resize(outlen + finlen + 32); return out; } std::vector AES::decrypt(const std::vector &in, const std::array &key) { if (in.size() < 32) throw Exception("Array to decrypt is too small!"); std::unique_ptr ctx(EVP_CIPHER_CTX_new(), &EVP_CIPHER_CTX_free); if (!ctx) throw Exception("Error initializing encryption context!"); std::vector out(in.size() - 32); int outlen = static_cast(out.size()); if (!EVP_DecryptInit_ex(ctx.get(), EVP_aes_256_cbc(), nullptr, key.data(), reinterpret_cast(in.data()))) throw Exception("Error decrypting!"); if (!EVP_DecryptUpdate(ctx.get(), reinterpret_cast(out.data()), &outlen, reinterpret_cast(in.data() + 32), static_cast(in.size() - 32))) throw Exception("Error decrypting!"); int finlen = 0; if (!EVP_DecryptFinal_ex(ctx.get(), (unsigned char *) (out.data() + outlen), &finlen)) throw Exception("Error decrypting!"); out.resize(outlen + finlen); return out; } std::array AES::deriveKey(const std::string &password, const std::string &salt) { std::array key;//NOLINT if (!PKCS5_PBKDF2_HMAC_SHA1(password.data(), static_cast(password.length()), reinterpret_cast(salt.data()), static_cast(salt.length()), 10000, 32, key.data())) throw Exception("Error deriving key!"); return key; }