11

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

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

有什么方法可以使用 C# 来实现这一点,还是我需要开始深入研究 CAPICOM?

4

3 回答 3

20

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

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

于 2009-05-26T19:03:06.250 回答
10

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

它输出以下内容:

原始:RawData.Length = 1337,HasPrivateKey = True
证书 A:RawData.Length = 1337,HasPrivateKey = False,certBytes.Length = 1337
证书 B:RawData.Length = 1337,HasPrivateKey = True,certBytes.Length = 3187
证书 C:RawData.Length = 1337,HasPrivateKey = False,certBytes.Length = 1337
RawData 等于原始 RawData: True
于 2015-04-07T02:10:00.713 回答
1

您可能会发现有一个OpenSSL .NET 包装器很有用。

于 2009-05-21T16:29:28.117 回答