代码之家  ›  专栏  ›  技术社区  ›  Aaronaught

导出不带私钥的X.509证书

  •  11
  • Aaronaught  · 技术社区  · 15 年前

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

    似乎所有x509certificate2.export方法都将导出私钥(如果它存在),如pkcs 12,这与我想要的相反。

    有没有办法用C来完成这个任务,或者我需要开始深入了解Capicom?

    3 回复  |  直到 7 年前
        1
  •  18
  •   Aaronaught    15 年前

    对于任何其他可能偶然发现这一点的人,我都明白了。如果您指定 X509ContentType.Cert 作为 X509Certificate.Export ,它只导出公钥。另一方面,指定 X509ContentType.Pfx 包含私钥(如果存在)。

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

        2
  •  8
  •   Steve P    9 年前

    我发现下面的程序有助于让自己确信 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();
        }
    }
    

    输出如下:

    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
    
        3
  •  1
  •   Nathan    15 年前

    有一个 OpenSSL .NET wrapper 你可能会觉得有用。