2009-05-21 121 views
9

我认为这将是直截了当的,但显然它不是。我有一个证书安装了一个私钥,可导出的,我想以编程方式导出与公钥只。换句话说,当我通过certmgr导出并导出到.CER时,我想要一个相当于选择“不导出私钥”的结果。导出X.509证书无私钥

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

是否有任何方式使用C#来完成此任务,还是我需要开始深入CAPICOM?

回答

17

对于任何可能遇到此问题的人,我都明白了。如果您指定X509ContentType.Cert作为X509Certificate.Export的第一个(也是唯一)参数,它只会导出公钥。另一方面,指定X509ContentType.Pfx包含私钥(如果存在)。

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

+0

你知道,如果有只导出私钥不整证书的方式?我必须摆脱私钥为字节数组,我不找到任何方法来做到这一点.... – RRR 2011-10-24 08:34:02

6

我发现下面的计划自己放心,证书的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<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(); 
    } 
} 

它输出以下:

 
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