You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenSSL 3中AES_set_decrypt_key与AES_unwrap_key的替代方案是什么?

OpenSSL 3中替代弃用的AES_set_decrypt_key和AES_unwrap_key的方案

在OpenSSL 3中,低级AES操作API(包括AES_set_decrypt_key和AES_unwrap_key)已被弃用,官方推荐使用EVP高级加密API替代——这类API更安全、易于维护,且符合现代加密标准的最佳实践。

核心替代思路

  • 使用EVP_CIPHER_CTX上下文对象管理加密/解密状态
  • 根据密钥长度匹配对应AES-WRAP算法(EVP_aes_128_wrap/EVP_aes_192_wrap/EVP_aes_256_wrap)
  • 通过EVP_DecryptInit_ex2初始化unwrap上下文,传入密钥、IV
  • 调用EVP_DecryptUpdate执行实际密钥unwrap操作
  • 清理上下文资源并处理错误

C++版本替代实现

#include <openssl/evp.h>
#include <memory>

std::unique_ptr<uint8_t[]> rfc3394_key_unwrap(const uint8_t* key, size_t key_len,
    const void* input, size_t input_len, const void* iv) noexcept
{
    // 根据密钥长度选择对应AES-WRAP算法
    const EVP_CIPHER* cipher = nullptr;
    switch (key_len) {
        case 16: cipher = EVP_aes_128_wrap(); break;
        case 24: cipher = EVP_aes_192_wrap(); break;
        case 32: cipher = EVP_aes_256_wrap(); break;
        default: return nullptr; // 不支持的密钥长度
    }

    // 智能指针管理EVP上下文,自动释放资源
    std::unique_ptr<EVP_CIPHER_CTX, decltype(&EVP_CIPHER_CTX_free)> ctx(
        EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free);
    if (!ctx) return nullptr;

    // 初始化unwrap操作:WRAP模式下解密初始化对应unwrap
    if (EVP_DecryptInit_ex2(ctx.get(), cipher, key, static_cast<const uint8_t*>(iv), nullptr) != 1) {
        return nullptr;
    }

    const size_t output_len = input_len - 8;
    auto out = std::make_unique<uint8_t[]>(output_len);
    int out_bytes_written = 0;
    int temp_bytes = 0;

    // 执行unwrap操作
    if (EVP_DecryptUpdate(ctx.get(), out.get(), &out_bytes_written,
        static_cast<const uint8_t*>(input), static_cast<int>(input_len)) != 1) {
        return nullptr;
    }

    // WRAP模式下Final通常无额外数据,但需调用完成状态检查
    if (EVP_DecryptFinal_ex(ctx.get(), out.get() + out_bytes_written, &temp_bytes) != 1) {
        return nullptr;
    }

    // 验证输出长度是否符合预期
    if (static_cast<size_t>(out_bytes_written + temp_bytes) != output_len) {
        return nullptr;
    }

    return out;
}

C版本替代实现

#include <openssl/evp.h>
#include <stdlib.h>
#include <stdint.h>

uint8_t* rfc3394_key_unwrap(const uint8_t* key, size_t key_len,
    const void* input, size_t input_len, const void* iv)
{
    // 根据密钥长度选择对应AES-WRAP算法
    const EVP_CIPHER* cipher = NULL;
    switch (key_len) {
        case 16: cipher = EVP_aes_128_wrap(); break;
        case 24: cipher = EVP_aes_192_wrap(); break;
        case 32: cipher = EVP_aes_256_wrap(); break;
        default: return NULL; // 不支持的密钥长度
    }

    // 创建EVP上下文
    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
    if (!ctx) return NULL;

    // 初始化unwrap操作
    if (EVP_DecryptInit_ex2(ctx, cipher, key, (const uint8_t*)iv, NULL) != 1) {
        EVP_CIPHER_CTX_free(ctx);
        return NULL;
    }

    const size_t output_len = input_len - 8;
    uint8_t* out = (uint8_t*)malloc(output_len);
    if (!out) {
        EVP_CIPHER_CTX_free(ctx);
        return NULL;
    }

    int out_bytes_written = 0;
    int temp_bytes = 0;

    // 执行unwrap操作
    if (EVP_DecryptUpdate(ctx, out, &out_bytes_written,
        (const uint8_t*)input, (int)input_len) != 1) {
        free(out);
        EVP_CIPHER_CTX_free(ctx);
        return NULL;
    }

    // 完成状态检查
    if (EVP_DecryptFinal_ex(ctx, out + out_bytes_written, &temp_bytes) != 1) {
        free(out);
        EVP_CIPHER_CTX_free(ctx);
        return NULL;
    }

    // 验证输出长度
    if ((size_t)(out_bytes_written + temp_bytes) != output_len) {
        free(out);
        EVP_CIPHER_CTX_free(ctx);
        return NULL;
    }

    EVP_CIPHER_CTX_free(ctx);
    return out;
}

关键说明

  • 算法匹配:必须严格按密钥长度选择对应算法,16字节→AES-128、24字节→AES-192、32字节→AES-256
  • 资源管理:EVP_CIPHER_CTX_new和EVP_CIPHER_CTX_free负责上下文的创建与销毁,避免内存泄漏
  • 错误判断:EVP API返回1表示成功,非1则需立即清理资源并返回失败
  • WRAP特性:RFC3394的密钥unwrap对应EVP的解密流程,直接传入IV和密钥即可完成初始化

内容的提问来源于stack exchange,提问作者uckelman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 08:22:41