OpenSSL 1.1.1升级至3.0.5后i2d_X509_REQ返回-1的兼容问题求助
问题解决:OpenSSL 3.0.5中i2d_X509_REQ返回-1的兼容性问题及错误排查方法
一、先解决错误原因打印问题
要定位OpenSSL接口调用失败的具体原因,仅靠返回的错误码无法获取有效信息,需要打印OpenSSL的错误栈。按以下步骤实现:
- 新增错误处理头文件引用:
#include <openssl/err.h>
- 实现错误打印函数:
void print_openssl_errors() { ERR_print_errors_fp(stderr); // 将错误信息输出到标准错误流 ERR_clear_error(); // 清空错误栈,避免干扰后续错误判断 }
- 在
i2d_X509_REQ调用失败后触发打印:
int length = i2d_X509_REQ(CR, NULL); if (length <= 0) { std::cout << "i2d_X509_REQ fail " << length << std::endl; print_openssl_errors(); // 输出具体错误原因 }
调用后会看到类似X509_REQ not signed的明确错误信息,这是定位问题的核心依据。
二、i2d_X509_REQ返回-1的根本原因及修复
你的代码创建了X509_REQ对象并设置了主题名称、公钥,但缺少对证书请求的签名步骤。OpenSSL 3.0版本对X.509结构的有效性检查大幅收紧,未签名的证书请求属于无效结构,无法被正确编码;而OpenSSL 1.1.1对未签名请求的编码限制更宽松,这是兼容性差异的关键。
修复步骤:
在X509_REQ_set_pubkey之后添加签名逻辑,使用生成的私钥对证书请求进行签名:
// 用SHA256摘要算法对证书请求签名 if (X509_REQ_sign(CR, pkey, EVP_sha256()) <= 0) { std::cout << "X509_REQ_sign failed" << std::endl; print_openssl_errors(); }
完成签名后,再调用i2d_X509_REQ(CR, NULL)即可正常获取证书请求的DER编码长度。
三、修复后的关键代码片段
// ... 原有代码 ... if(1 == X509_REQ_set_pubkey(CR, pkey)) { std::cout << "X509_REQ_set_pubkey success" << std::endl; } // 新增:对证书请求进行签名 if (X509_REQ_sign(CR, pkey, EVP_sha256()) <= 0) { std::cout << "X509_REQ_sign failed" << std::endl; print_openssl_errors(); } int length = i2d_X509_REQ(CR, NULL); if (length <= 0) { std::cout << "i2d_X509_REQ fail " << length << std::endl; print_openssl_errors(); } else { std::cout << "i2d_X509_REQ success, length: " << length << std::endl; } // ... 后续资源清理代码 ...
四、额外注意事项
- OpenSSL 3.0对所有X.509相关结构的合规性要求更高,必填字段缺失、未签名等情况都会导致编码失败。
- 操作完成后记得释放资源:
X509_REQ_free(CR);、EVP_PKEY_free(pkey);,避免内存泄漏。
内容的提问来源于stack exchange,提问作者APT
相关产品推荐
相关产品推荐

