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

OpenSSL 3.1.0中使用EVP_DigestSign_* API进行RSA签名的密钥问题

问题分析与解决方案

核心原因

你用EVP_RSA_gen(2048)生成的是RSA*类型的密钥对象,但EVP_DigestSignInit函数要求传入的密钥参数是EVP_PKEY*类型(这也是EC密钥能用的原因,EVP_EC_gen直接返回EVP_PKEY*)。类型不匹配导致无法正确获取密钥,触发error:40800066:lib(129)::cant get key.错误。

修复步骤

  1. 将RSA包装为EVP_PKEY
    生成RSA密钥后,需要用EVP_PKEY_new()创建空的EVP_PKEY对象,再用EVP_PKEY_assign_RSA()将RSA密钥关联进去:

    RSA* rsa = EVP_RSA_gen(2048);
    if (rsa == NULL) {
        // 处理生成错误
    }
    EVP_PKEY* rsaKeyPair = EVP_PKEY_new();
    if (rsaKeyPair == NULL || !EVP_PKEY_assign_RSA(rsaKeyPair, rsa)) {
        // 处理包装错误:若EVP_PKEY_assign_RSA失败,需手动释放rsa
        RSA_free(rsa);
        EVP_PKEY_free(rsaKeyPair);
    }
    

    注意:EVP_PKEY_assign_RSA会接管RSA对象的所有权,后续只需释放EVP_PKEY*,无需单独释放RSA*。

  2. 替换已弃用的EVP_MD_CTX_create
    OpenSSL 3.x中EVP_MD_CTX_create()已被弃用,直接启用代码中注释的EVP_MD_CTX_new():

    ctxRSA = EVP_MD_CTX_new();
    
  3. 完善资源清理
    签名完成后,务必释放所有申请的资源:

    EVP_MD_CTX_free(ctxRSA);
    EVP_PKEY_free(rsaKeyPair);
    OPENSSL_free(sig);
    

修复后的关键代码片段

// 生成并包装RSA密钥
RSA* rsa = EVP_RSA_gen(2048);
if (rsa == NULL) {
    ERR_error_string(ERR_get_error(), err_buffer);
    // 错误处理
}
EVP_PKEY* rsaKeyPair = EVP_PKEY_new();
if (rsaKeyPair == NULL || !EVP_PKEY_assign_RSA(rsaKeyPair, rsa)) {
    ERR_error_string(ERR_get_error(), err_buffer);
    RSA_free(rsa);
    EVP_PKEY_free(rsaKeyPair);
    // 错误处理
}

// 签名流程
EVP_MD_CTX* ctxRSA = EVP_MD_CTX_new();
if (ctxRSA == NULL) {
    ERR_error_string(ERR_get_error(), err_buffer);
    // 错误处理
}

int rc = EVP_DigestSignInit(ctxRSA, NULL, EVP_sha256(), NULL, rsaKeyPair);
if (rc != 1) {
    ERR_error_string(ERR_get_error(), err_buffer);
    // 错误处理
}

// 后续DigestSignUpdate、DigestSignFinal逻辑保持不变

// 资源清理
EVP_MD_CTX_free(ctxRSA);
EVP_PKEY_free(rsaKeyPair);
OPENSSL_free(sig);

额外说明

  • OpenSSL 3.x推荐统一使用EVP_PKEY接口处理所有密钥类型,避免直接操作RSA/EC等底层对象,提升代码兼容性。
  • 若编写新代码,更推荐用EVP_PKEY_generate结合参数模板生成RSA密钥,符合OpenSSL 3.x的设计风格:
    EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
    if (pctx == NULL || EVP_PKEY_keygen_init(pctx) <= 0 || EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, 2048) <= 0) {
        // 错误处理
    }
    EVP_PKEY* rsaKeyPair = NULL;
    if (EVP_PKEY_generate(pctx, &rsaKeyPair) <= 0) {
        // 错误处理
    }
    EVP_PKEY_CTX_free(pctx);
    

内容的提问来源于stack exchange,提问作者Michał Pura

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 03:13:20