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

如何用OpenSSL EVP函数替换3.0版本废弃的RSA低级API?

替换OpenSSL 3.0中废弃的RSA低级API为EVP高级API

原代码与问题

下面是一段原本可正常运行的OpenSSL RSA加密代码:

void SwapBytes( unsigned char *pv, size_t n )
{
   unsigned char *p = pv;
   size_t lo, hi;
   for ( lo = 0, hi = n - 1; hi > lo; lo++, hi-- )
   {
      char tmp = p[lo];
      p[lo] = p[hi];
      p[hi] = tmp;
   }
}

void RSA(unsigned char *plaintext, unsigned char *ciphertext)
{
        BIGNUM *bnN = NULL;
        BIGNUM *bnE = NULL;

        RSA *keys = RSA_new();

        BN_hex2bn(&bnN, modulus);
        BN_hex2bn(&bnE, public_exp);

        RSA_set0_key(keys, bnN, bnE, NULL);

        int modulus_size = RSA_size(keys);

        SwapBytes(plaintext, modulus_size);
        
        int cipher_len = RSA_public_encrypt(modulus_size, plaintext, ciphertext, keys, RSA_NO_PADDING);

        RSA_free(keys);

        SwapBytes(ciphertext, modulus_size);
}  

编译时会触发废弃警告:

/mnt/c/Projects/src/rsa.cpp:37:102: warning: ‘int RSA_public_encrypt(int, const unsigned char*, unsigned char*, RSA*, int)’ is deprecated: Since OpenSSL 3.0 [-Wdeprecated-declarations]
   37 |         int cipher_len = RSA_public_encrypt(modulus_size, plaintext, ciphertext, keys, RSA_NO_PADDING);

虽然可以通过编译选项-Wno-deprecated-declarations抑制警告,但OpenSSL官方明确表示:

OpenSSL开发团队长期以来一直不建议使用低级API,在OpenSSL 3.0中这一要求被正式明确,所有此类低级API均已被废弃。你仍可在应用中使用它们,但编译时可能会出现废弃警告(取决于编译器是否支持该特性)。废弃的API可能会在未来版本的OpenSSL中被移除,因此强烈建议你将代码更新为使用高级API。

使用EVP高级API的替代实现

下面是使用OpenSSL EVP API重写的RSA加密代码,功能与原代码完全一致(无填充的RSA公钥加密,包含字节序反转):

#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/rsa.h>

void SwapBytes(unsigned char *pv, size_t n)
{
    unsigned char *p = pv;
    size_t lo, hi;
    for (lo = 0, hi = n - 1; hi > lo; lo++, hi--)
    {
        char tmp = p[lo];
        p[lo] = p[hi];
        p[hi] = tmp;
    }
}

int RSA_EVP_Encrypt(unsigned char *plaintext, unsigned char *ciphertext, size_t *cipher_len)
{
    // 假设modulus和public_exp是全局定义的十六进制字符串常量
    BIGNUM *bnN = BN_hex2bn(NULL, modulus);
    BIGNUM *bnE = BN_hex2bn(NULL, public_exp);
    if (bnN == NULL || bnE == NULL)
        return -1;

    RSA *rsa_key = RSA_new();
    if (RSA_set0_key(rsa_key, bnN, bnE, NULL) != 1)
    {
        RSA_free(rsa_key);
        BN_free(bnN);
        BN_free(bnE);
        return -1;
    }

    EVP_PKEY *pkey = EVP_PKEY_new();
    if (EVP_PKEY_assign_RSA(pkey, rsa_key) != 1)
    {
        EVP_PKEY_free(pkey);
        RSA_free(rsa_key);
        return -1;
    }

    EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
    if (ctx == NULL)
    {
        EVP_PKEY_free(pkey);
        return -1;
    }

    if (EVP_PKEY_encrypt_init(ctx) != 1)
    {
        EVP_PKEY_CTX_free(ctx);
        EVP_PKEY_free(pkey);
        return -1;
    }

    // 设置无填充模式,对应原代码的RSA_NO_PADDING
    if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING) != 1)
    {
        EVP_PKEY_CTX_free(ctx);
        EVP_PKEY_free(pkey);
        return -1;
    }

    int modulus_size = RSA_size(rsa_key);
    SwapBytes(plaintext, modulus_size);

    // 执行加密操作
    if (EVP_PKEY_encrypt(ctx, ciphertext, cipher_len, plaintext, modulus_size) != 1)
    {
        EVP_PKEY_CTX_free(ctx);
        EVP_PKEY_free(pkey);
        return -1;
    }

    SwapBytes(ciphertext, modulus_size);

    // 清理资源:EVP_PKEY_free会自动释放关联的RSA结构和BIGNUM
    EVP_PKEY_CTX_free(ctx);
    EVP_PKEY_free(pkey);

    return 0;
}

代码说明

  • 使用EVP_PKEY作为密钥的统一抽象层,兼容多种加密算法,符合OpenSSL 3.0的设计规范
  • 通过EVP_PKEY_assign_RSA将原有RSA密钥结构关联到EVP_PKEY,实现低级密钥结构到高级API的过渡
  • 用EVP_PKEY_CTX配置加密参数,这里设置无填充模式,与原代码逻辑对齐
  • 加密流程通过EVP_PKEY_encrypt_init初始化、EVP_PKEY_encrypt执行完成,结构更清晰
  • 资源清理更简洁:EVP_PKEY_free会自动释放关联的RSA和BIGNUM结构,无需手动逐个释放

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 04:05:25