1

在我的代码中,我枚举了所有本地 IIS 站点,并为每个站点尝试验证端口 443 的证书。

using( var sm = new ServerManager() ) {
  foreach( var site in sm.Sites ) {
    foreach( var binding in site.Bindings ) {
       if( binding.EndPoint.Port == 443 ) {
          var thumbprint = binding.CertificateHash;
          var storeName = binding.CertificateStoreName;
          //validation here...
       }
    }
  }
}

这段代码产生了一些字节数组,我将storeName其转换为十六进制表示。"MY"thumbprint

现在“验证”部分的工作方式如下:

var store = new X509Store("MY");
store.Open(OpenFlags.ReadOnly);
var certs = store.Certificates;
//find and validate my cert
store.Close();

这段代码产生一个空集合。然而如果我改变

var store = new X509Store("MY");

var store = new X509Store(StoreLocation.LocalMachine);

然后代码生成一个包含两个证书的集合,其中一个具有正确的指纹,我可以验证它。

为什么会发生Binding返回证书存储名称但我在存储中找不到任何具有该名称的证书?

4

2 回答 2

3

商店名称和商店位置之间存在差异。

IIS 的所有证书都存储在本地计算机位置,而不是针对特定用户帐户的证书。

这就是构造函数的X509Store样子,它只需要一个StoreLocation,您的第二个示例正在调用:

public X509Store(StoreLocation storeLocation) : this("MY", storeLocation)
{
}

它正在调用同时采用商店名称位置的构造函数。

你的第一个例子:

var store = new X509Store("MY");

正在打开MY商店CurrentUser,而不是本地机器。所以你找店了。切换到使用同时接受名称和位置的构造函数。

于 2013-03-01T10:37:21.127 回答
0

此方法将为您获取证书:

private X509Certificate2 GetServiceCertificate(String certificateSubjectName, StoreName storeName = StoreName.My, StoreLocation storeLocation = StoreLocation.CurrentUser)
{
    X509Store certificateStore = new X509Store(storeName, storeLocation);
    foreach (X509Certificate2 certificate in certificateStore.Certificates)
    {
        if (certificate.SubjectName.Name == certificateSubjectName)
        {
            return certificate;
        }
    }
    return null;
}
于 2013-03-01T10:41:50.633 回答