<pre class="prism-highlight prism-language-cpp">namespace aes {
enum class variant {
AES128 = 16,
AES192 = 24,
AES256 = 32
};
enum class mode {
CBC,
ECB
};
ylib::buffer en(const ylib::buffer& data, const std::string& key,ylib::codec::aes::variant variant,ylib::codec::aes::mode mode);
ylib::buffer de(const ylib::buffer& ciphertext, const std::string& key, variant var, mode mod);
}
<pre class="prism-highlight prism-language-cpp">ylib::buffer codec::aes::en(const ylib::buffer& data, const std::string& key, ylib::codec::aes::variant var, ylib::codec::aes::mode mod)
{
try
{
const EVP_CIPHER* cipher;
unsigned char keyFixed[EVP_MAX_KEY_LENGTH] = { 0 }; // 最大密钥长度
std::memcpy(keyFixed, key.data(), ylib_min(key.size(), sizeof(keyFixed)));
switch (var) {
case variant::AES128:
cipher = (mod == mode::CBC) ? EVP_aes_128_cbc() : EVP_aes_128_ecb();
break;
case variant::AES192:
cipher = (mod == mode::CBC) ? EVP_aes_192_cbc() : EVP_aes_192_ecb();
break;
case variant::AES256:
cipher = (mod == mode::CBC) ? EVP_aes_256_cbc() : EVP_aes_256_ecb();
break;
default:
throw std::runtime_error("Unsupported AES variant");
}
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
if (!ctx) {
std::cerr << "Failed to create EVP_CIPHER_CTX" << std::endl;
throw std::runtime_error("Failed to create EVP_CIPHER_CTX");
}
if (1 != EVP_EncryptInit_ex(ctx, cipher, NULL, keyFixed, NULL)) {
std::cerr << "Failed to initialize AES encryption" << std::endl;
EVP_CIPHER_CTX_free(ctx);
throw std::runtime_error("Failed to initialize AES encryption");
}
std::vector<unsigned char> out_buf(data.size() + EVP_MAX_BLOCK_LENGTH);
int out_len1, out_len2;
if (1 != EVP_EncryptUpdate(ctx, out_buf.data(), &out_len1, reinterpret_cast<const unsigned char*>(data.data()), (int)data.length())) {
std::cerr << "Failed to encrypt data" << std::endl;
EVP_CIPHER_CTX_free(ctx);
throw std::runtime_error("Failed to encrypt data");
}
if (1 != EVP_EncryptFinal_ex(ctx, out_buf.data() + out_len1, &out_len2)) {
std::cerr << "Failed to finalize AES encryption" << std::endl;
EVP_CIPHER_CTX_free(ctx);
throw std::runtime_error("Failed to finalize AES encryption");
}
EVP_CIPHER_CTX_free(ctx);
out_buf.resize(out_len1 + out_len2);
return ylib::buffer(reinterpret_cast<const char*>(out_buf.data()), out_buf.size());
}
catch (const std::exception& e)
{
std::cout << e.what() << std::endl;
}
return ylib::buffer();
}
ylib::buffer codec::aes::de(const ylib::buffer& ciphertext, const std::string& key, variant var, mode mod)
{
try
{
const EVP_CIPHER* cipher;
unsigned char keyFixed[EVP_MAX_KEY_LENGTH] = { 0 }; // max key length
std::memcpy(keyFixed, key.data(), ylib_min(key.size(), sizeof(keyFixed)));
switch (var) {
case variant::AES128:
cipher = (mod == mode::CBC) ? EVP_aes_128_cbc() : EVP_aes_128_ecb();
break;
case variant::AES192:
cipher = (mod == mode::CBC) ? EVP_aes_192_cbc() : EVP_aes_192_ecb();
break;
case variant::AES256:
cipher = (mod == mode::CBC) ? EVP_aes_256_cbc() : EVP_aes_256_ecb();
break;
default:
throw std::runtime_error("Unsupported AES variant");
}
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
if (!ctx) {
std::cerr << "Failed to create EVP_CIPHER_CTX" << std::endl;
throw std::runtime_error("Failed to create EVP_CIPHER_CTX");
}
if (1 != EVP_DecryptInit_ex(ctx, cipher, NULL, keyFixed, NULL)) {
std::cerr << "Failed to initialize AES decryption" << std::endl;
EVP_CIPHER_CTX_free(ctx);
throw std::runtime_error("Failed to initialize AES decryption");
}
std::vector<unsigned char> out_buf(ciphertext.length() + EVP_MAX_BLOCK_LENGTH);
int out_len1, out_len2;
if (1 != EVP_DecryptUpdate(ctx, out_buf.data(), &out_len1, reinterpret_cast<const unsigned char*>(ciphertext.data()), (int)ciphertext.length())) {
std::cerr << "Failed to decrypt data" << std::endl;
EVP_CIPHER_CTX_free(ctx);
throw std::runtime_error("Failed to decrypt data");
}
if (1 != EVP_DecryptFinal_ex(ctx, out_buf.data() + out_len1, &out_len2)) {
std::cerr << "Failed to finalize AES decryption" << std::endl;
EVP_CIPHER_CTX_free(ctx);
throw std::runtime_error("Failed to finalize AES decryption");
}
EVP_CIPHER_CTX_free(ctx);
out_buf.resize(out_len1 + out_len2);
return ylib::buffer(reinterpret_cast<const char*>(out_buf.data()), out_buf.size());
}
catch (const std::exception& e)
{
std::cout << e.what() << std::endl;
}
return ylib::buffer();
}