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

C# 如何以编程方式将带有证书链的pfx导入证书存储?,c#,pfx,x509certificate2,pkcs#12,C#,Pfx,X509certificate2,Pkcs#12,我正试图以编程方式将X509证书(pfx/PKCS#12)导入本地计算机的证书存储中。此特定证书具有证书链,证书路径如下所示: cert = new X509Certificate2(pathToCert, password); if (cert != null) { var store = new X509Store(StoreName.My, StoreLocation.LocalMachine); store.Open(OpenFlags.ReadWrite);

我正试图以编程方式将X509证书(pfx/PKCS#12)导入本地计算机的证书存储中。此特定证书具有证书链,证书路径如下所示:

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);
    }
}
  • 根证书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时,它确实会显示完整路径。
我是跳过了一步,还是缺少了一些参数?有人能解释一下吗?

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

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


我希望这能解决您的问题,但如果不能解决,您能否更具体地说明您要实现的目标?

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

以下是X509Certificate2Collection上的文档:

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

一旦您知道每个证书的CNs/颁发者/其他信息,就应该清楚每个证书需要添加到哪个证书存储中。为此,您可以使用X509Store类和StoreName枚举指定要打开/添加到的存储:

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

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

为了解决这个问题,我刚刚在cert导入方法中添加了一点MS UI自动化代码,在提示符下单击OK

或者,正如评论员“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
}
string certPath=;
字符串certPass=;
//创建集合对象并使用PFX文件填充它
X509Certificate2Collection=新的X509Certificate2Collection();
导入(certPath、certPass、X509KeyStrageFlags.PersistKeySet);
foreach(收集中的X509Certificate2证书)
{
WriteLine(“主题是:{0}',cert.Subject);
WriteLine(“颁发者是:{0}',cert.Issuer);
//将证书导入X509Store对象
}

为了将来参考,我发现了另一种方法,使用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
}
var cert=new X509Certificate2(路径插入,密码);
X509Chain chain=新的X509Chain();
建造连锁店(cert);
对于(int i=0;i
适用于任何希望“存储到适当的存储”代码通用解决方案的人

这是我用VB创建的,所以移植到C并不难。我用上面的帖子开始了我的工作,我完全不知道该怎么做

    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()

PFX通常与PKCS#12混淆,在您的情况下,您只需要一个证书链,您可以轻松地使用PEM文件来实现。但是你有自己的私钥文件吗?在这种情况下,您确实需要PKCS#12@IanNorton:它实际上是PKCS#12证书。在这方面我没有任何选择。在这种情况下,您希望读取包含x509对象的p12文件。是否有任何方法将该存储用作SOAP调用上验证证书的存储??感谢证书理论。问题是,我在导入过程中丢失了链信息,我试图在代码中解决这个问题。在导入集合后,这不起作用,集合只包含一个证书(我的证书)。不过,我想您已经了解了一些情况。我曾经遇到过同样的问题(将PFX文件作为X509Certificate2对象打开只会导致导入叶/用户证书)。因此,X509Certificate2显然不起作用,除非您只需要叶证书。将PFX作为X509Certificate2集合打开是一个解决方案-当您这样做并检查集合的长度(或在for循环中打印集合中每个证书的主题/颁发者)时,您是否看到了链中的所有证书?最后,我似乎有所进展。我做了一个新的出口从我的证书商店,现在似乎是与您的代码。它现在显示所有的证书,除了根证书。。。有什么想法吗?为了获得关于PFX文件内容的第二个意见,可以尝试使用“openssl.exe pk”