C# 导出没有私钥的 X.509 证书
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/893757/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Exporting X.509 certificate WITHOUT private key
提问by Aaronaught
I thought this would be straightforward but apparently it isn't. I have a certificate installed that has a private key, exportable, and I want to programmatically export it with the public key ONLY. In other words, I want a result equivalent to selecting "Do not export the private key" when exporting through certmgr and exporting to .CER.
我认为这很简单,但显然不是。我安装了一个证书,该证书有一个可导出的私钥,我想仅使用公钥以编程方式导出它。换句话说,当通过 certmgr 导出并导出到 .CER 时,我想要一个等同于选择“不导出私钥”的结果。
It seems that all of the X509Certificate2.Export methods will export the private key if it exists, as PKCS #12, which is the opposite of what I want.
似乎所有 X509Certificate2.Export 方法都将导出私钥(如果存在),作为 PKCS #12,这与我想要的相反。
Is there any way using C# to accomplish this, or do I need to start digging into CAPICOM?
有什么方法可以使用 C# 来实现这一点,还是我需要开始深入研究 CAPICOM?
采纳答案by Aaronaught
For anyone else who might have stumbled on this, I figured it out. If you specify X509ContentType.Cert
as the first (and only) parameter to X509Certificate.Export
, it only exports the public key. On the other hand, specifying X509ContentType.Pfx
includes the private key if one exists.
对于其他可能偶然发现这一点的人,我想通了。如果您将 指定X509ContentType.Cert
为第一个(也是唯一的)参数X509Certificate.Export
,则它仅导出公钥。另一方面,X509ContentType.Pfx
如果存在私钥,则指定包括私钥。
I could have sworn that I was seeing different behaviour last week, but I must have already had the private key installed when I was testing. When I deleted that certificate today and started again from scratch, I saw that there was no private key in the exported cert.
我可以发誓我上周看到了不同的行为,但我在测试时一定已经安装了私钥。今天我删除了那个证书,从头开始,我看到导出的证书中没有私钥。
回答by Nathan
There is an OpenSSL .NET wrapperyou may find useful.
您可能会发现有一个OpenSSL .NET 包装器很有用。
回答by explunit
I found the following program helpful for reassuring myself that the RawData
property of the certificate contains only the public key (MSDN is unclear on this), and that the answer above regarding X509ContentType.Cert
vs. X509ContentType.Pfx
works as expected:
我发现以下程序有助于让自己确信RawData
证书的属性仅包含公钥(MSDN 对此不清楚),并且上面关于X509ContentType.Cert
vs.的答案X509ContentType.Pfx
按预期工作:
using System;
using System.Linq;
using System.IdentityModel.Tokens;
using System.Security.Cryptography.X509Certificates;
class Program
{
static void Main( string[] args )
{
var certPath = @"C:\blah\somecert.pfx";
var certPassword = "somepassword";
var orig = new X509Certificate2( certPath, certPassword, X509KeyStorageFlags.Exportable );
Console.WriteLine( "Orig : RawData.Length = {0}, HasPrivateKey = {1}", orig.RawData.Length, orig.HasPrivateKey );
var certBytes = orig.Export( X509ContentType.Cert );
var certA = new X509Certificate2( certBytes );
Console.WriteLine( "cert A : RawData.Length = {0}, HasPrivateKey = {1}, certBytes.Length = {2}", certA.RawData.Length, certA.HasPrivateKey, certBytes.Length );
// NOTE that this the only place the byte count differs from the others
certBytes = orig.Export( X509ContentType.Pfx );
var certB = new X509Certificate2( certBytes );
Console.WriteLine( "cert B : RawData.Length = {0}, HasPrivateKey = {1}, certBytes.Length = {2}", certB.RawData.Length, certB.HasPrivateKey, certBytes.Length );
var keyIdentifier = ( new X509SecurityToken( orig ) ).CreateKeyIdentifierClause<X509RawDataKeyIdentifierClause>();
certBytes = keyIdentifier.GetX509RawData();
var certC = new X509Certificate2( certBytes );
Console.WriteLine( "cert C : RawData.Length = {0}, HasPrivateKey = {1}, certBytes.Length = {2}", certC.RawData.Length, certC.HasPrivateKey, certBytes.Length );
Console.WriteLine( "RawData equals original RawData: {0}", certC.RawData.SequenceEqual( orig.RawData ) );
Console.ReadLine();
}
}
It outputs the following:
它输出以下内容:
Orig : RawData.Length = 1337, HasPrivateKey = True cert A : RawData.Length = 1337, HasPrivateKey = False, certBytes.Length = 1337 cert B : RawData.Length = 1337, HasPrivateKey = True, certBytes.Length = 3187 cert C : RawData.Length = 1337, HasPrivateKey = False, certBytes.Length = 1337 RawData equals original RawData: True