如何以编程方式将带有证书链的pfx导入证书存储区?

我正在尝试以编程方式在我的本地计算机的证书存储中导入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时,它确实显示完整路径。 我在这里跳过一步,还是我错过了一些参数? 有人可以对此有所了解吗?

您应该能够通过打开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 = ; string certPass = ; // 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 } 

为了将来参考,我发现了另一种使用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 } 

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

这是我用VB创建的,所以不应该很难移植到C#。 我用上面的post让我开始,我就是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() 

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

因此,您已将“我的证书”与链一起正确导入“根证书CA” – 此链在“我的证书”中编码,您可以通过查看其属性来确认这一点,但此链只是一个链接而不是包含任何“根证书CA”,“组织证书CA”和“组织2证书CA”证书。

我希望这能解决你的问题,但如果没有,你能否更具体地说明你想要完成什么?