使用PEM_read_bio_PUBKEY()加载公钥失败,请求排查问题
公钥加载失败问题排查与解决
问题场景
你通过以下OpenSSL命令生成密钥文件:
$ openssl genrsa -out test-priv.pem 4096 $ openssl req -subj '/C=US/ST=Texas/L=Fort Worth/O=ABC Corporation, Inc./OU=Software/CN=abc_corp.com' -x509 -nodes -key test-priv.pem -out test-public.pem -days 365 -addext keyUsage=digitalSignature -addext extendedKeyUsage=codeSigning,emailProtection
随后用C代码调用PEM_read_bio_PUBKEY加载test-public.pem,编译运行后提示Unable to load key filename : test-public.pem。
错误原因
你用openssl req -x509生成的不是纯公钥文件,而是X.509格式的证书文件——证书里确实包含公钥,但PEM_read_bio_PUBKEY函数仅支持加载PEM格式的纯公钥(比如用openssl rsa -pubout导出的文件),直接用它读取证书会失败。
两种解决方法
方法一:重新生成纯公钥文件
从已有的私钥中导出纯公钥:
$ openssl rsa -in test-priv.pem -pubout -out test-pub.pem
运行程序时改用新生成的纯公钥文件:
$ ./key_test test-pub.pem
原代码无需修改。
方法二:修改代码读取X.509证书并提取公钥
调整load_pubkey函数,先读取证书再从中提取公钥:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <openssl/pem.h> #include <openssl/x509.h> EVP_PKEY *load_pubkey(const char *file) { BIO *key = NULL; EVP_PKEY *pkey = NULL; X509 *x509 = NULL; if (file == NULL) { printf("no keyfile specified\n"); goto end; } key = BIO_new(BIO_s_file()); if (key == NULL) { goto end; } if (BIO_read_filename(key, file) <= 0) { printf("Error opening : %s\n", file); goto end; } // 读取X.509证书 x509 = PEM_read_bio_X509(key, NULL, NULL, NULL); if (x509 == NULL) { printf("Failed to read X.509 certificate\n"); goto end; } // 从证书中提取公钥 pkey = X509_get_pubkey(x509); end: if (x509 != NULL) X509_free(x509); if (key != NULL) BIO_free(key); if (pkey == NULL) printf("Unable to load key filename : %s\n", file); return (pkey); } int main(int argc, char *argv[]) { load_pubkey((const char *)argv[1]); return 0; }
编译命令不变:
$ gcc key_test.c -lssl -lcrypto -o key_test
直接用原证书文件运行即可:
$ ./key_test test-public.pem
内容的提问来源于stack exchange,提问作者Cprogrammer
相关产品推荐
相关产品推荐

