基于OpenSSL 0.9.8a的C++应用RSA签名验证问题
解决OpenSSL 0.9.8a中RSA 4096位签名验证的EVP API问题
嘿,看你贴的代码,核心问题是把摘要生成的函数拿来做签名验证了——你最后调用的EVP_DigestFinal_ex是用来生成消息哈希的,但签名验证的收尾步骤得用EVP_DigestVerifyFinal才行。另外,OpenSSL 0.9.8a是个比较老的版本,上下文处理和新版本有点不一样,我帮你把代码修正过来,再说说需要注意的细节:
你的代码哪里出问题了?
前面的EVP_DigestInit_ex、EVP_DigestVerifyInit、EVP_DigestUpdate步骤都是对的,但最后一步选错了函数:EVP_DigestFinal_ex是用来输出计算好的消息摘要,而我们要做的是验证签名,得用专门的EVP_DigestVerifyFinal来对比签名和消息摘要的匹配性。
修正后的完整验证代码
bool verifyRSASignature(RSA* pubKey, const unsigned char* Msg, size_t MsgLen, const unsigned char* Signature, size_t SigLen) { // OpenSSL 0.9.8a还没有EVP_MD_CTX_create/destroy,直接用栈上初始化 EVP_MD_CTX ctx; EVP_MD_CTX_init(&ctx); const EVP_MD* md = EVP_get_digestbyname("SHA512"); if (!md) { fprintf(stderr, "SHA512 digest not supported\n"); EVP_MD_CTX_cleanup(&ctx); return false; } // 初始化签名验证上下文,绑定公钥和摘要算法 if (EVP_DigestVerifyInit(&ctx, NULL, md, NULL, pubKey) <= 0) { fprintf(stderr, "Failed to init verify context\n"); ERR_print_errors_fp(stderr); // 打印详细错误,方便调试 EVP_MD_CTX_cleanup(&ctx); return false; } // 喂入要验证的消息数据 if (EVP_DigestUpdate(&ctx, Msg, MsgLen) <= 0) { fprintf(stderr, "Failed to update message\n"); ERR_print_errors_fp(stderr); EVP_MD_CTX_cleanup(&ctx); return false; } // 关键:用EVP_DigestVerifyFinal验证签名,而不是生成摘要 int res = EVP_DigestVerifyFinal(&ctx, Signature, SigLen); // 清理上下文,避免内存泄漏 EVP_MD_CTX_cleanup(&ctx); // 返回结果:1=验证通过,0=验证失败,-1=发生错误 return res == 1; }
针对OpenSSL 0.9.8a的额外注意事项
- 签名格式兼容:这个版本默认只支持PKCS#1 v1.5格式的签名,如果你的签名是PSS格式,得手动配置验证参数(0.9.8a的PSS API比较繁琐,建议先确认签名生成时用的是PKCS#1 v1.5)。
- 4096位RSA支持:确保你使用的OpenSSL 0.9.8a编译时开启了大密钥长度支持,有些旧编译包可能默认限制密钥大小,遇到报错可以检查编译选项。
- 调试技巧:每个EVP函数调用失败时,用
ERR_print_errors_fp(stderr)打印错误栈,能快速定位是公钥无效、摘要算法不支持还是签名格式不匹配等问题。
内容的提问来源于stack exchange,提问作者MBA_BAT88
相关产品推荐
相关产品推荐

