OpenSSL 1.0.2o中RSA_sign()返回0错误码排查求助
让我们一步步拆解你遇到的问题,结合你的OpenSSL编译配置和代码细节,可能的原因如下:
1. 私钥可能未完整加载
你的密钥导入代码里,调用read_bio2rsa后没有检查返回值。虽然你验证了公钥和私钥的n值匹配,但私钥的核心参数(比如私指数d、素因子p/q这些)可能根本没正确读进来。建议修改导入代码,加上返回值检查:
if (!read_bio2rsa(*bio, &rsa, NULL, NULL)) { EMSG("读取RSA密钥失败: %s", ERR_error_string(ERR_get_error(), NULL)); RSA_free(rsa); BIO_free(*bio); return NULL; }
私钥不完整的话,签名操作肯定执行不下去。
2. SHA256算法可能未被编译进库
你的OpenSSL配置没明确禁用SHA256,但得确认编译时是不是真的把SHA256模块包含进去了。可以在代码里加个小验证:
if (!EVP_get_digestbyname("sha256")) { EMSG("SHA256算法未加载"); return CRYPTO_ERR; }
如果返回NULL,说明编译时漏掉了SHA256,得重新编译OpenSSL,确保没加no-sha256这类禁用选项(默认是启用的)。
3. 编译宏限制了错误信息和功能
你用了-DOPENSSL_NO_STDIO,这个宏会让OpenSSL的错误信息输出失效,所以你看到的错误描述是空的。调试阶段可以先去掉这个宏,重新编译,就能拿到具体的错误提示了,排查起来会轻松很多。
另外-DOPENSSL_NO_FP_API禁用了浮点API,但SHA256和普通RSA签名不依赖浮点,这个应该不是直接原因,但可以留意有没有间接影响。
4. 私钥格式可能不匹配
你用PEM_read_bio_RSAPrivateKey读取私钥,这个函数只认PKCS#1格式的私钥(开头是-----BEGIN RSA PRIVATE KEY-----)。如果你的私钥是PKCS#8格式(开头是-----BEGIN PRIVATE KEY-----),就得换成PEM_read_bio_PrivateKey来读取。格式不对的话,哪怕n值对得上,私钥的其他参数也解析不出来。
5. 签名参数可能有问题
先确认几个参数的正确性:
- 你传入的
hash必须是有效的SHA256哈希,长度得是32字节 sig缓冲区的大小要足够,RSA签名长度等于密钥模长(比如2048位密钥需要256字节的缓冲区)
可以在调用RSA_sign前加个检查:
#include <openssl/sha.h> // ... if (hash_len != SHA256_DIGEST_LENGTH) { EMSG("哈希长度不对:预期%d,实际%d", SHA256_DIGEST_LENGTH, hash_len); return CRYPTO_ERR; } int required_sig_size = RSA_size(prv_key); if (*sig_len < required_sig_size) { EMSG("签名缓冲区太小:需要%d,实际%d", required_sig_size, *sig_len); return CRYPTO_ERR; }
6. 考虑OpenSSL版本的bug
你用的1.0.2o是2018年的老版本,虽然基础功能应该没问题,但可能存在一些已修复的bug。如果上面的排查都没解决问题,可以试试升级到1.0.2系列的最后一个版本(1.0.2zb),看看能不能解决。
内容的提问来源于stack exchange,提问作者Anisyanka

