导出X.509证书没有私钥

我认为这很简单,但显然不是。 我安装了一个具有私钥,可导出的证书,我想以编程方式仅使用公钥导出它。 换句话说,我想要一个等效于在通过certmgr导出并导出到.CER时选择“不导出私钥”的结果。

似乎所有X509Certificate2.Export方法都会导出私钥(如果存在),如PKCS#12,这与我想要的相反。

有没有办法使用C#来实现这一目标,还是我需要开始深入了解CAPICOM?

对于其他可能偶然发现的人,我想通了。 如果将X509ContentType.Cert指定为X509Certificate.Export的第一个(也是唯一的)参数,则它仅导出公钥。 另一方面,指定X509ContentType.Pfx包括私钥(如果存在)。

我本来可以发誓我上周看到了不同的行为,但我在测试时必须已经安装了私钥。 当我今天删除该证书并从头开始时,我看到导出的证书中没有私钥。

我发现以下程序有助于让我自己确认证书的RawData属性只包含公钥(MSDN对此不清楚),并且上面关于X509ContentType.CertX509ContentType.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(); 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(); } } 

它输出以下内容:

 Orig:RawData.Length = 1337,HasPrivateKey = True
证书A:RawData.Length = 1337,HasPrivateKey = False,certBytes.Length = 1337
证书B:RawData.Length = 1337,HasPrivateKey = True,certBytes.Length = 3187
 cert C:RawData.Length = 1337,HasPrivateKey = False,certBytes.Length = 1337
 RawData等于原始RawData:True

您可能会发现有用的OpenSSL .NET包装器 。