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
相关产品推荐
相关产品推荐

