如何检索X509Store中的所有证书

46

我正在使用以下代码从 asp.net webapp 中检索我的 PC 中的所有证书。 但是,证书集合为空,我不明白原因。

我尝试模拟自己的用户帐户,但也没有成功。 我做错了什么?

var store = new X509Store(StoreLocation.CurrentUser); //StoreLocation.LocalMachine fails too
var certificates = store.Certificates;
foreach (var certificate in certificates)
{
    var friendlyName = certificate.FriendlyName;
    Console.WriteLine(friendlyName);
}

//original problem: fetch a single certificate by its subject name
X509Certificate2 clientCertificate = CertificateUtility.GetCertificate(StoreName.My, StoreLocation.CurrentUser,  "CN=mypc.domainname"); //returns null :(

1
我可以在本地使其工作,但当我发布并且客户访问系统时,它找不到证书。有没有办法在服务器上的应用程序中查找客户端上的证书? - Mariana
对于编写UWP应用程序的开发者,您需要在清单中添加共享用户证书功能。否则,您将得到一个空列表而不是异常。 - Guy Lowe
4个回答

63
将此行代码添加到第二行并查看其运行情况:
store.Open(OpenFlags.ReadOnly);

然后在底部加上这个:):

store.Close();

1
我也使用这个来打开存储:store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); - rick schott
2
@rickschott:说得好,但由于它们是位标志,而OpenFlags.ReadOnly的枚举值为0,因此在其他标志旁指定它没有特定的效果。只要不给出OpenFlags.ReadWrite(值为1)标志,它将被视为只读。 OpenFlags.ReadOnly实际上只是一个默认值,因为该函数需要一个参数。从技术上讲,它的描述甚至不正确,因为它不是真正的标志;它不包含更改位的位。 - Nyerguds
2
或者你可以将它包装在 using 块中,因为 X509Store 实现了 IDisposable ;) - RJ Cuthbertson
1
@RJCuthbertson 自 .NET Framework 4.6 开始,IDisposable 接口仅由 X509Store 类支持。在此之前,您必须将其包装在 try-finally 块中。 - Redwolf
我可以在本地使其工作,但当我发布并且客户访问系统时,它找不到证书。有没有办法在服务器上的应用程序中查找客户端上的证书? - Mariana
你的客户端运行的安全上下文可能没有权限查看你目标证书。 - Chris B. Behrens

22

我有一个使用https的Apache服务器(xamp),我通过https和c# (vs2010)访问PHP上传页面。

  1. 在个人证书文件夹中安装来自ie的证书。

  2. 要查看证书,请运行"certmgr.msc",至少在win7上是这样的。

列出个人证书

var store = new X509Store(StoreLocation.CurrentUser); 

store.Open(OpenFlags.ReadOnly); 

var certificates = store.Certificates;
foreach (var certificate in certificates)
{
    var friendlyName = certificate.FriendlyName;
    var xname = certificate.GetName(); //obsolete
    Console.WriteLine(friendlyName);
}

store.Close();

查找特定的证书

string certificateName = "CN=localhost"; //name found in the var xname
X509Store storex = new X509Store(StoreName.My, StoreLocation.CurrentUser);
                    storex.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certificatesx =
            storex.Certificates.Find(X509FindType.FindBySubjectName, 
            certificateName,
            true);

X509Certificate certificatex = certificates[0];

storex.Close();

我已经进行了编辑,以改善此帖子的标记并引入大写字母,但第一句话和观点对我来说仍然没有太多意义。有更好理解的人可以进行编辑吗? - doppelgreener
我可以在本地使其工作,但当我发布并且客户访问系统时,它找不到证书。有没有办法在服务器上的应用程序中查找客户端上的证书? - Mariana

3

我可以通过...找到证书

var certificateStore = new X509Store(StoreName.TrustedPeople, StoreLocation.LocalMachine);

certificateStore.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);

var certificateCollection = certificateStore.Certificates.Find(X509FindType.FindBySubjectName, "mycert.me.com",false);

certificateStore.Close();

var certificate = certificateCollection[0];

certificateCollection将拥有我关心的证书...如果只有一个,则取集合中的第一个元素。


2

请在证书存储中查看 (mmc/add/certificate snap-in/my user account/Certificates - Current User/Personal/Certificates),以确认主题名称是否为“CN=mypc.domainname”,以确保证书信息正确。

"CN=mypc.domainname"

vs

"CN = mypc.domainname"

...etc


是的,我只是不想在这里暴露我的真实电脑/域名。 ;) - Pablo
我知道你的真实CN名称不是这个,只是想确保你的“mypc.domainame”(无论它的真实名称是什么)与你的证书上的一致。 - rick schott

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接