OpenSSL中PEM_read_PUBKEY返回NULL问题排查求助
PEM_read_PUBKEY加载RSA公钥失败的原因分析
问题场景
尝试加载PEM格式的RSA公钥用于加密,但PEM_read_PUBKEY始终返回NULL,使用的代码如下:
QString publicKeyFilePath = QString(FILE_PATH); if (!QFile::exists(publicKeyFilePath)) { std::cout << "Doesn't exist." << std::endl; } FILE *publicKeyFile = fopen(publicKeyFilePath.toStdString().c_str(), "rb"); EVP_PKEY *publicKey = PEM_read_PUBKEY(publicKeyFile, NULL, NULL, NULL); if (publicKey == nullptr) { std::cout << "PEM_read_PUBKEY failed." << std::endl; } fclose(publicKeyFile);
对应的公钥文件内容为:
-----BEGIN RSA PUBLIC KEY----- MIICCgKCAgEAonmLnagQuiepcLyRPLbgFLRISoLFv4AMmCKXB6Ur+Ku2IwcOQcqx igMman9FAbVzrBEnN4mypVbMKkIdDQk0YUx1i0USRVzBwkdpr53z9MB2qxW8sczc tVHddQrqhS5T3W+FVUXNPJe+X798L0coUtB72f9Jn665E26EC8nQXgwJZlxfqqar ZdDntAk+/gf7Mo+ARxJBpyoUn3MxDSOc6rxLfV3NVzgWuo/MmAaeV2ltcfaRUPIw XOPn3vRQKHErHSk3cQIWwFG9xRJU41lzNpqmBLMilTAD4rrGyogqIuUKZSZ9wao2 xrpFLO3iUl4N3KCj6EYPlzRk9bkZEkrKNhxukMuHJvtq/ORM181E76O57DsY70hW UuoPK9NNoQoTGLRbVqxnq25E6NZ4FG/ajJi74zQsNZa8D0fyUE1hBIaEBj1bpoYJ nmRdCfwh2ejozFgVkrsklUjHeiUFGDu7w3EietzYZABpQSL6Bbr4uOYUMLULI53d opDw70qiysfulr85cPhxVI7dFF7BlZ68vBqbpflhTJjqeBHk554e3mzU+mWPRL4Y TqMfM9w0V5Ku2JSEGoeYf0/oPTjAPV9Fe0MAGFSdSRf86W439zHKIUUrREUwlp9L xRMqsQeF9T3shsF4fgF2jrFb0/K4ZxnD6+IlhPDt7XrqoJ54daJ9mzsCAwEAAQ== -----END RSA PUBLIC KEY-----
核心原因:PEM格式不匹配
PEM_read_PUBKEY专门用于加载PKCS#8格式的公钥(头部标识为-----BEGIN PUBLIC KEY-----),但你提供的是PKCS#1格式的RSA公钥(头部标识为-----BEGIN RSA PUBLIC KEY-----),格式不兼容直接导致加载失败。
解决办法
有两种直接可行的方案:
转换公钥格式:用OpenSSL命令把PKCS#1格式转成PKCS#8格式,命令如下:
openssl rsa -in rsa_pub.pem -pubin -outform PEM -out pkcs8_pub.pem转换后的公钥头部会自动变为
-----BEGIN PUBLIC KEY-----,此时用原代码的PEM_read_PUBKEY就能正常加载。改用对应加载函数:如果不想转换格式,直接用专门加载PKCS#1格式RSA公钥的
PEM_read_RSA_PUBKEY函数,替换原代码中的PEM_read_PUBKEY,再把返回的RSA*转为EVP_PKEY*即可:RSA *rsaPubKey = PEM_read_RSA_PUBKEY(publicKeyFile, NULL, NULL, NULL); EVP_PKEY *publicKey = EVP_PKEY_new(); EVP_PKEY_assign_RSA(publicKey, rsaPubKey);
额外排查点
- 检查文件是否成功打开:当前代码没做
fopen的返回值检查,如果文件路径含特殊字符、权限不足,都会导致文件打开失败,建议加上:FILE *publicKeyFile = fopen(publicKeyFilePath.toStdString().c_str(), "rb"); if (!publicKeyFile) { std::cout << "Failed to open public key file." << std::endl; return; } - 查看详细错误日志:在
PEM_read_PUBKEY失败后调用ERR_print_errors_fp(stderr),可以打印OpenSSL的具体错误信息,快速定位问题。
内容的提问来源于stack exchange,提问作者bopeh74638
相关产品推荐
相关产品推荐

