OpenSSL函数d2i_PublicKey与d2i_PUBKEY的区别、适用场景及问题排查
d2i_PublicKey与d2i_PUBKEY的区别及选型方案
核心差异
- 解码格式适配不同
d2i_PublicKey适配算法专属裸公钥格式,以RSA为例仅能解码纯RSAPublicKey结构,不包含算法标识前缀。调用时必须提前传入对应算法类型常量(如EVP_PKEY_RSA),数据格式/算法类型不匹配时直接返回NULL。d2i_PUBKEY适配X.509标准SubjectPublicKeyInfo格式,该结构内置算法标识字段,调用时无需提前指定算法类型,函数会自动识别并完成解码。
异常场景根因
特定用例下d2i_PublicKey解码失败的核心原因是该用例的公钥数据为SubjectPublicKeyInfo封装格式,d2i_PublicKey无法识别带算法标识的封装结构因此返回空,替换为d2i_PUBKEY刚好匹配输入格式因此解码成功。
选型规则
- 若明确输入为无算法前缀的裸公钥(如旧系统自定义导出的单算法公钥、直接从算法密钥生成接口导出的原始公钥),选择
d2i_PublicKey,需提前确认公钥对应的算法类型。 - 若输入为跨系统传输的标准公钥、从证书中提取的公钥等遵循X.509规范的公钥,优先选择
d2i_PUBKEY,无需提前感知算法类型,兼容性更强。
通用兼容方案
如果无法提前确定输入公钥的格式,可以增加降级重试逻辑,注意d2i系列函数会修改输入的指针参数,每次重试前需要重置指针到数据起始位置:
EVP_PKEY *decode_public_key(const unsigned char *data, long len, int expected_key_type) { EVP_PKEY *pkey = NULL; const unsigned char *tmp = data; // 优先尝试解码标准SubjectPublicKeyInfo格式 pkey = d2i_PUBKEY(NULL, &tmp, len); if (pkey != NULL) { return pkey; } // 解码失败则重置指针,尝试解码指定类型的裸公钥 tmp = data; pkey = d2i_PublicKey(expected_key_type, NULL, &tmp, len); return pkey; } // 调用示例 EVP_PKEY *result = decode_public_key(publicKeyData, publicKey.size(), EVP_PKEY_RSA); // 使用完毕后调用EVP_PKEY_free(result)释放内存
内容的提问来源于stack exchange,提问作者Somnath Saha
相关产品推荐
相关产品推荐

