如何将CNG API生成的RSA密钥导出为标准PEM格式文件?
CNG生成RSA密钥转标准PEM格式的解决方案
问题根因
你直接对BCryptExportKey导出的BCRYPT_RSAPRIVATE_BLOB/BCRYPT_RSAPUBLIC_BLOB做Base64编码无法得到标准PEM的核心原因是:
- 上述两种Blob是微软自定义的专有二进制格式,头部固定为
RSA2(私钥)、RSA1(公钥)的Magic标识,不是PEM要求的标准ASN.1 DER编码的密钥结构 - 标准PEM文件中Base64编码的内容是DER格式的密钥,你看到的
MIIE开头就是2048位RSA私钥DER头部经Base64编码后的固定特征,编码微软专有Blob自然不会出现该标识
正确转换步骤
核心逻辑
先将CNG导出的专有Blob解析出RSA密钥的各参数,再组装为标准DER编码结构,最后对DER数据做Base64编码、添加PEM头尾标记即可。
你可以选择手动拼接ASN.1结构,也可以直接用Windows内置的CryptEncodeObjectAPI完成转换,避免手动拼写出错,以下为API转换的参考流程:
- 解析
BCRYPT_RSAPRIVATE_BLOB导出缓冲区,提取密钥参数:
导出缓冲区的前8个字节是BCRYPT_RSAKEY_BLOB头部,后续依次存储模数、公钥指数、私钥指数、大质数p、大质数q等核心参数,直接读取对应偏移量的内容即可。 - 调用
CryptEncodeObject生成标准DER编码:// 填充RSA私钥参数结构 CRYPT_RSA_PRIVATE_KEY_INFO rsaPrivKey = {0}; // 把从CNG Blob里解析出的模数、指数等参数赋值给rsaPrivKey对应字段 ... // 计算DER编码所需缓冲区大小 DWORD derSize = 0; CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, &rsaPrivKey, NULL, &derSize); // 分配缓冲区后生成DER编码 BYTE* derBuffer = (BYTE*)malloc(derSize); CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, &rsaPrivKey, derBuffer, &derSize); - 对生成的
derBuffer做Base64编码,按每行64个字符拆分后,前后添加PEM头尾标记:
此时生成的就是标准PEM格式的RSA私钥,开头会出现你预期的-----BEGIN RSA PRIVATE KEY----- 拆分后的Base64编码内容 -----END RSA PRIVATE KEY-----MIIE标识。
公钥转换说明
公钥的转换逻辑和私钥一致,只需要在调用CryptEncodeObject时,将编码类型替换为X509_PUBLIC_KEY_INFO,最后添加对应公钥的PEM头尾标记-----BEGIN PUBLIC KEY-----/-----END PUBLIC KEY-----即可。
内容的提问来源于stack exchange,提问作者Unknown1987
相关产品推荐
相关产品推荐

