Implementing AES encryption and decryption using OpenSSL

<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();
}

Title of this article:<Implementing AES encryption and decryption using OpenSSL>Author:minimini
Original link:https://www.xxmjw.com/post/21.html
Unless otherwise specified, all content is original. Please indicate when reprinting.

Related

minimini

minimini