如何从PEM文件中获取私钥?
我有一个 .PEM 文件,其中包含用于 SSL 数据传输的公钥和私钥,如下所示:
-----BEGIN RSA PRIVATE KEY-----
private key data
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
public key data
-----END CERTIFICATE-----
当我想通过以下代码加载 .PEM 文件时:
X509Certificate2 xx = new X509Certificate2("c:\\myKey.pem");
我收到一个异常:“找不到请求的对象。” ,具有完整的堆栈:
System.Security.Cryptography.CryptographicException was unhandled
Message=Cannot find the requested object.
Source=mscorlib
StackTrace:
at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
at System.Security.Cryptography.X509Certificates.X509Utils._QueryCertFileType(String fileName)
at System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromFile(String fileName, Object password, X509KeyStorageFlags keyStorageFlags)
at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(String fileName)
at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(String fileName)
at DLLTest.SSL_Test.test() in E:\Projects\DLLTest\DLLTest\SSL_Test.cs:line 165
at DLLTest.SSL_Test.Run() in E:\Projects\DLLTest\DLLTest\SSL_Test.cs:line 21
at DLLTest.Program.Main(String[] args) in E:\Projects\DLLTest\DLLTest\Program.cs:line 21
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
如果我交换私钥部分和公钥部分的位置,代码将工作并加载数据,并且我可以从对象中获取公钥信息,例如。发行人名称, 并且其 HasPrivateKey 为 false。为什么?我是否误解并做错了什么?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
有一篇关于代码项目的文章,其中包含所有您需要执行此操作的代码。它只是几个类,所以它是一个轻量级的解决方案。
要从 PEM 文件中获取证书或密钥的字节,无论文件中密钥和证书的顺序如何,都可以使用以下方法。
将 PEM 文件加载到字符串中并调用上面的方法来获取表示证书的字节。接下来,将获得的字节传递给 X509Certificate2 的构造函数:
从 PEM 文件加载 (RSA) 私钥有点复杂,但您也可以在上述文章中找到对此的支持以及使用 Crypto .DecodeRsaPrivateKey 方法。
There's an article on the Code Project that has all the code you need to do this. It's just a couple of classes so it's a light-weight solution.
To get the bytes for either a certificate or a key from the PEM file the following method will work, regardless of the order of the key and certificate in the file.
Load the PEM file into a string and call the method above to get the bytes that represent the certificate. Next you pass the obtained bytes to the constructor of an X509Certificate2 :
Loading the (RSA) private key from the PEM file is a bit more complicated but you'll find support for that in the above mentioned article as well using the
Crypto.DecodeRsaPrivateKey
method.AFAIK .NET 框架在任何地方都不支持 PEM。
您可以轻松地解决
X509Certificate
部分,因为您可以提取 -----BEGIN CERTIFICATE----- 之间的 base64 字符串strong> 和 -----END CERTIFICATE----- 行,将其转换为byte[]
并创建X509Certificate。
一个简单的解决方案是从 Mono.Security 的 X509Certificate.cs 来执行此操作。
获取私钥有点棘手,因为获取 byte[] 对重建 RSA 实例没有太大帮助(我们可以假设,因为 PEM 标头声明它是 RSA)。
这次你最好从 Mono.Security 的 PKCS8.cs 文件并 sioply 调用解码方法。
免责声明: 我是上面讨论的 Mono 代码的主要作者,所有这些代码都可以在 MIT.X11 许可证下使用
AFAIK the .NET framework does not support PEM anywhere.
You can hack around this easily for the
X509Certificate
part since you can extract the base64 string between the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- lines, convert it into abyte[]
and create theX509Certificate
from it.An easy solution is to copy-paste code from Mono.Security's X509Certificate.cs to do this.
Getting the private key is a bit tricky since getting the
byte[]
won't be of much help to reconstruct the RSA instance (which we can assume since the PEM header states it's RSA).This time you better copy-paste from Mono.Security's PKCS8.cs file and sioply call the decode method.
Disclaimer: I'm the main author of the Mono code discussed above and it is all available under the MIT.X11 license
我遇到了同样的问题,并且 - 作为记录 - 我在这里发布了一个完整的、有效的代码示例(由于已知原因,密钥被删除)。它主要是在互联网上找到的东西和我的家庭项目要求的汇编。
以下代码的功能
代码:
I had the same problem and - for the record - I post here a complete, working code sample (the key is cut for known reasons). It's mostly a compilation of stuff found on the Internet and my home project requirements.
Following code's features
The code:
另一种方法是将客户端 PEM 证书转换为 Windows 支持的 PFX 格式。例如,可以使用 openssl 来完成此操作,方法是运行:(
其中“cert.pfx”是输出文件,“cert.key”包含私钥,“cert.pem”包含输入证书,“ca.pem”包含输入证书)。 pem”包含签名者的证书)。
A different approach is to convert the client PEM certificate to the PFX format supported by Windows. This can be done using, for example, openssl, by running:
(where "cert.pfx" is the output file, "cert.key" contains the private key, "cert.pem" contains the input certificate, and "ca.pem" contains the certificate of the signer).
你不知道。
.NET 不支持它。
您会看到,PEM 编码确实支持多种密钥类型(例如 ECDSA)。
因此,如果有人为您提供了一种从 PEM 文件读取 .NET RSA 密钥的方法,您也许能够读取该 RSA 密钥(如果 PEM 也有 D、P、Q、DP DQ、InverseQ),但那就是离读PEM还有很长的路要走。
此外,.NET 版本的 RSA 仅实现基于(模数、指数和 D、P、Q、DP、DQ、InverseQ)的 RSA。真正的 PEM 编码的 RSA 密钥不需要支持参数 D、P、Q、DP、DQ、InverseQ。可以,但不是必须的。 RSA 真正需要的只是模数和指数。仅包含模数和指数的 PEM 编码的 RSA 密钥是完全有效的 PEM 密钥,特别是当您需要与 Python 进行互操作时,Python 可以执行此类操作。
但是,您可以使用 BouncyCastle 读取 PEM 编码的私钥和公钥。
见下文。
要在不添加对 BouncyCastle 的依赖的情况下将这些加密密钥(任何类型)通用到 .NET,最好的选择是读取 BouncyCastle 中的 PEM 文件,创建一个 PFX 文件(包含私钥和公钥),然后读取带有 System.Security.Cryptography.X509Certificates.X509Certificate2 的 PFX 文件。然后,您可以从该证书获取已解码的私钥和公钥(假设它们使用 .NET 支持的加密算法)。
哦,以下是如何使用 PFX 进行操作:
You don't.
.NET doesn't support it.
You see, the PEM-encoding does support multiple keys types (e.g. ECDSA).
So if somebody provides you with a way to read a .NET RSA key from a PEM-file, you maybe able to read that RSA-key (if the PEM also has D, P, Q, DP DQ, InverseQ), but that's a long way from reading PEM.
Also the .NET version of RSA only implements RSA based on (Modulus,Exponent and D, P, Q, DP, DQ, InverseQ). A real PEM-encoded RSA key does not need to support parameters D, P, Q, DP, DQ, InverseQ. It can, but it doesn't have to. All RSA really needs is Modulus and Exponent. And a PEM-encoded RSA key containing only modulus and Exponent is a perferctly valid PEM-key, especially when you need interop with Python, which does such things.
However, you can read a PEM-encoded private and public key with BouncyCastle.
See below.
To get these cryptographic keys (of any kind) generically to .NET without adding a dependency on BouncyCastle, your best bet is to read the PEM-files in BouncyCastle, create a PFX-file (which contains private and public key), then read that PFX-file with System.Security.Cryptography.X509Certificates.X509Certificate2. From that certificate, you can then get the private and public key already decoded, assuming they use a cryptographic algorithm of a kind that .NET does support.
Oh, and here's how to do the things with PFX:
我不了解 .NET(但了解 Java),但答案应该是相同的。
您的 pem 文件包含证书和私钥。
这是 OpenSSL 中的常见导出。
要在 Java 中实例化
X509Certificate
对象,您只需使用文件中的以下部分:.NET 中应该是一样的。
只需加载文件并加载 PEM 的该部分即可。
对私钥执行相同的操作。
在java中,您将使用相应的对象(即PrivateKey)来加载它。
使用适合 .NET 的
I don't know .NET (but Java) but the answer should be the same.
Your pem file contains both the certificate and private key.
This is a usual export in OpenSSL.
To instantiate an object of
X509Certificate
in Java you would use only the part of the file that says:It should be the same in .NET.
Just load the file and load that part of PEM.
Do the same for private key.
In java you would use the corresponding object i.e. PrivateKey to load it.
Use the appropriate for .NET
我遇到了同样的问题,找到了如下解决方案:
首先使用此工具将 prkey.pem 转换为 prkey.xml //https://superdry.apphb.com/tools/online-rsa-key-converter
I encountered the same issue and found a solution as below:
First convert prkey.pem into prkey.xml with this tool //https://superdry.apphb.com/tools/online-rsa-key-converter