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

如何使用C++基于RSA私有PEM密钥与SHA256算法实现签名

你目前使用的RSA_sign接口默认采用PKCS#1 v1.5填充,和你给出的openssl命令指定的RSASSA-PSS填充模式不匹配,这是签名结果不一致的核心原因。

正确实现代码

基于OpenSSL的EVP高阶接口实现,完全匹配你给出的openssl命令参数:

#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/err.h>

int rsa_pss_sha256_sign(const char* signString, const char* pem_private_key_path, unsigned char** out_sig, size_t* out_sig_len) {
    // 初始化OpenSSL依赖
    ERR_load_crypto_strings();
    OpenSSL_add_all_algorithms();

    // 1. 读取PEM格式私钥
    FILE* privateKeyFile = fopen(pem_private_key_path, "rb");
    if (!privateKeyFile) {
        return -1;
    }
    EVP_PKEY* pkey = PEM_read_PrivateKey(privateKeyFile, NULL, NULL, NULL);
    fclose(privateKeyFile);
    if (!pkey) {
        ERR_print_errors_fp(stderr);
        return -1;
    }

    size_t messageLength = strlen(signString);
    // 2. 创建签名上下文
    EVP_MD_CTX* md_ctx = EVP_MD_CTX_new();
    if (!md_ctx) {
        EVP_PKEY_free(pkey);
        return -1;
    }

    // 3. 初始化签名操作,指定摘要算法为SHA256
    if (EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, pkey) != 1) {
        EVP_MD_CTX_free(md_ctx);
        EVP_PKEY_free(pkey);
        return -1;
    }

    // 4. 配置PSS填充参数,和openssl命令参数完全对应
    EVP_PKEY_CTX* pkey_ctx = EVP_MD_CTX_get_pkey_ctx(md_ctx);
    if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1 ||
        EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, 20) != 1 ||
        EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha256()) != 1) {
        EVP_MD_CTX_free(md_ctx);
        EVP_PKEY_free(pkey);
        return -1;
    }

    // 5. 传入待签名原始数据
    if (EVP_DigestSignUpdate(md_ctx, signString, messageLength) != 1) {
        EVP_MD_CTX_free(md_ctx);
        EVP_PKEY_free(pkey);
        return -1;
    }

    // 6. 动态获取签名长度,分配缓冲区
    size_t sigLen = 0;
    if (EVP_DigestSignFinal(md_ctx, NULL, &sigLen) != 1) {
        EVP_MD_CTX_free(md_ctx);
        EVP_PKEY_free(pkey);
        return -1;
    }
    *out_sig = (unsigned char*)malloc(sigLen);

    // 7. 生成最终签名
    if (EVP_DigestSignFinal(md_ctx, *out_sig, &sigLen) != 1) {
        free(*out_sig);
        EVP_MD_CTX_free(md_ctx);
        EVP_PKEY_free(pkey);
        return -1;
    }
    *out_sig_len = sigLen;

    // 释放资源
    EVP_MD_CTX_free(md_ctx);
    EVP_PKEY_free(pkey);
    CRYPTO_cleanup_all_ex_data();
    ERR_free_strings();
    return 0;
}

参数对应说明

代码里的配置和你给出的openssl命令参数一一对应:

  • EVP_sha256() 对应命令的-sha256,指定摘要算法为SHA256
  • EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) 对应-sigopt rsa_padding_mode:pss,指定PSS填充模式
  • EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, 20) 对应-sigopt rsa_pss_saltlen:20,指定盐长度为20字节
  • EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, EVP_sha256()) 对应openssl默认的PSS掩码生成算法配置,使用SHA256作为MGF1的摘要算法

注意事项

  • 签名缓冲区长度通过EVP_PKEY_size(pkey)动态获取,无需硬编码,可适配2048/4096等不同长度的RSA密钥
  • 所有OpenSSL资源使用完成后会调用对应的释放接口,避免内存泄漏
  • 如果签名失败,可以调用ERR_print_errors_fp(stderr)打印错误信息快速排查问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 11:27:02