OpenSSL中PEM_read_bio_PUBKEY加载部分公钥返回NULL的原因分析
OpenSSL加载SMIME公钥失败原因分析
问题场景
使用OpenSSL进行SMIME加解密时,通过以下代码加载公钥:
EVP_PKEY* createPublicKey(const char* publicKeyString) { BIO* bio = BIO_new_mem_buf((void*)publicKeyString, -1); EVP_PKEY* pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); BIO_free(bio); return pkey; }
其中第二个公钥能正常加载,但第一个公钥调用PEM_read_bio_PUBKEY返回NULL:
加载失败的公钥:
-----BEGIN PUBLIC KEY----- MIGJAoGBAKvXgzoezmG2CrUt9jptn09LKscdS9vyTe1jP3vHfylbU93/+GVIhjlw d7mM0ulSsi+O53+HElDQjY2ufqePRKGJ3NGzisF0YopEvU36xq0L2IG7g7gny08n 7f3HXg6TC0FcwOJRBVDhVXUwl3RiH06jGFp+iq2Ok3vngLrrFeg/AgMBAAE= -----END PUBLIC KEY-----
加载成功的公钥:
-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoMeN556vV68LEAQ1KE22 n6fHTCsVV1CwKMo8L6WvCMD13xNs72MwA+FNNOZUTg2+2HvaH7ZnwNgLPeY/O+Rc vTBLI90qGxAubGYnvp+76hNROzXQfLFlTQdGiu2vF0oiCU00EDKM4xzL8iOf7H8A aw9f6S0Y9UiaZAMJ0CLXwv6yWLvxHgNGiJ1Z3VGrUnW16K9EGyoNMYARPiJqSMaG Grw26SUBzA485zzZfiIgnruriuiBQPp9dL5vvGAvRFODCcj45Jqpo25hTSADQTw3 kUUQ5WRRy2Din1VAEWJflCUMAf+VowODoglZP5YOSkf8lsBlVpekroWNFVaQehs3 MwIDAQAB -----END PUBLIC KEY-----
原因分析
公钥格式差异
- 第一个公钥是PKCS#1格式的RSA公钥,虽然PEM头标注为
BEGIN PUBLIC KEY,但实际编码是PKCS#1规范的RSAPublicKey结构。 - 第二个公钥是PKCS#8格式的通用公钥,这是
PEM_read_bio_PUBKEY默认支持的格式,可兼容RSA、EC等多种密钥类型。
- 第一个公钥是PKCS#1格式的RSA公钥,虽然PEM头标注为
函数适配问题
PEM_read_bio_PUBKEY仅支持读取PKCS#8格式的公钥,对于PKCS#1格式的RSA公钥,需要使用专门的PEM_read_bio_RSAPublicKey函数加载。
解决方法
方法一:修改代码适配PKCS#1格式
替换加载函数为PEM_read_bio_RSAPublicKey,并转换为EVP_PKEY类型:
EVP_PKEY* createPublicKey(const char* publicKeyString) { BIO* bio = BIO_new_mem_buf((void*)publicKeyString, -1); RSA* rsa = PEM_read_bio_RSAPublicKey(bio, NULL, NULL, NULL); EVP_PKEY* pkey = EVP_PKEY_new(); EVP_PKEY_assign_RSA(pkey, rsa); BIO_free(bio); return pkey; }
方法二:转换公钥格式为PKCS#8
用OpenSSL命令行将第一个公钥转换为PKCS#8格式,原代码即可直接加载:
openssl rsa -pubin -in pkcs1_public.key -out pkcs8_public.key -pubout -outform PEM
结论
第一个公钥并非无效,只是格式不符合PEM_read_bio_PUBKEY的要求,通过调整加载函数或转换公钥格式即可解决问题。
内容的提问来源于stack exchange,提问作者a_adler
相关产品推荐
相关产品推荐

