23

我正在尝试以编程方式在本地计算机的证书存储中导入 X509 证书(pfx / PKCS#12)。这个特定的证书有一个证书链,证书路径看起来像这样:

  • 根证书 CA
    • 组织证书 CA
      • 组织 2 证书 CA
        • 我的证书

我使用的代码如下所示:

cert = new X509Certificate2(pathToCert, password);

if (cert != null)
{
    var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
    store.Open(OpenFlags.ReadWrite);
    if (!store.Certificates.Contains(cert))
    {
        store.Add(cert);
    }
}

此代码确实导入了证书,但它似乎忽略了链。如果我在商店里查看证书,证书路径只显示:

  • 我的证书

但是,当我手动导入 pfx 时,它确实显示了完整路径。我是在这里跳过一步,还是缺少一些参数?有人可以对此有所了解吗?

4

4 回答 4

20

您应该能够通过将 PFX 文件作为 X509Certificate2Collection 对象打开来遍历 PFX 中的证书(并将每个证书导入您选择的证书存储区)。

以下是 X509Certificate2Collection 上的文档:

http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2collection.aspx

MSDN 在该文档页面中提供了一些示例代码,说明如何检查集合中的每个证书。

一旦您了解了有关每个证书的 CN/颁发者/其他信息,就应该清楚每个证书需要添加到哪个证书存储区。为此,您可以使用 X509Store 类和 StoreName 枚举来指定要打开/添加到的商店:

http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509store.aspx

http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.storename.aspx

另请参阅我对类似 SO 问题的回答:

如何使用 c# 从 pfx 文件中检索证书?

正如对该答案的最新评论之一所述,当您尝试将证书导入当前用户的根存储(“StoreName.Root”和“StoreLocation.CurrentUser”作为名称/位置)时,您将收到一个弹出对话框询问你去确认。

为了解决这个问题,我刚刚在我的证书导入方法中添加了一点 MS UI 自动化代码,在提示符上单击“确定”。

或者,正如评论者“CodeWarrior”在其他 SO 答案的评论中所说,为避免弹出对话框,您可以尝试将根证书放入 LocalMachine 存储而不是 CurrentUser。

示例代码:

string certPath = <YOUR PFX FILE PATH>;
string certPass = <YOUR PASSWORD>;

// Create a collection object and populate it using the PFX file
X509Certificate2Collection collection = new X509Certificate2Collection();
collection.Import(certPath, certPass, X509KeyStorageFlags.PersistKeySet);

foreach (X509Certificate2 cert in collection)
{
    Console.WriteLine("Subject is: '{0}'", cert.Subject);
    Console.WriteLine("Issuer is:  '{0}'", cert.Issuer);

    // Import the certificate into an X509Store object
}
于 2012-02-05T20:43:47.847 回答
9

为了将来参考,我发现了另一种方法,使用 X509Chain 对象:

var cert = new X509Certificate2(pathToCert, password);

X509Chain chain = new X509Chain();
chain.Build(cert);
for (int i = 0; i < chain.ChainElements.Count; i++)
{
   //add to the appropriate store
}
于 2012-02-13T12:40:36.800 回答
1

对于任何想要“到适当的商店”代码通用解决方案的人

这是我使用 VB 创建的,因此移植到 C# 应该不难。我用上面的帖子让我开始了,我在这方面完全是 NooB。

    Dim certPath = "C:\Users\08353153\Documents\Visual Studio 2015\Projects\WindowsApplication2\WindowsApplication2\bin\Debug\8870-thebigchess.pfx"
    Dim certPass = "eduSTAR.NET"
    Dim Collection As New X509Certificate2Collection
    Collection.Import(certPath, certPass, X509KeyStorageFlags.PersistKeySet)

    Dim certOne As X509Certificate2 = Collection(0)
    Dim certTwo As X509Certificate2 = Collection(2)
    Dim certThree As X509Certificate2 = Collection(1)

    Dim personal As New X509Store(StoreName.My, StoreLocation.LocalMachine)
    personal.Open(OpenFlags.ReadWrite)
    personal.Add(certOne)
    personal.Close()

    Dim trust As New X509Store(StoreName.Root, StoreLocation.LocalMachine)
    trust.Open(OpenFlags.ReadWrite)
    trust.Add(certTwo)
    trust.Close()

    Dim intermed As New X509Store(StoreName.CertificateAuthority, StoreLocation.LocalMachine)
    intermed.Open(OpenFlags.ReadWrite)
    intermed.Add(certThree)
    intermed.Close()
于 2016-01-08T04:55:43.877 回答
-1

X.509 证书仅包含将其链接到根证书(包括中间机构)的链,但这些证书不包含在证书中。当验证最终证书(非自签名)时使用此链 - 它必须指向受信任的根证书。更准确地说,每个 CA 的公钥用于解码和验证已颁发证书的哈希值。重复此过程,直到达到根证书。检查整个链后,如果根证书受信任,则最终证书也受信任。当然,该过程还包括其他验证(例如开始日期、结束日期、证书撤销列表),但我只详细说明了与链的使用相关的部分。

所以你已经正确地将“我的证书”连同链一起导入到“根证书 CA”——这个链在“我的证书”中编码,你可以通过查看它的属性来确认这一点,但是这个链只是一个链接,它没有包含“根证书 CA”、“组织证书 CA”和“组织 2 证书 CA”证书中的任何一个。

我希望这可以解决您的问题,但如果没有,您能否更具体地说明您要完成的工作?

于 2012-02-04T14:53:06.957 回答