45

I am using the following code to retrieve all certificates in my PC from an asp.net webapp. The certificates collection is empty, and I can't understand why.

I tried impersonating my own user account and I didn't succeed as well. What am I doing wrong?

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 :(
rick schott
  • 21,012
  • 5
  • 52
  • 81
Pablo
  • 2,054
  • 8
  • 30
  • 56
  • 1
    I can make it work locally, when I publish and the client accesses the system, it can not find the certificates. Is there any way to find the certificates on the client, with the application on the server? – Mariana Jan 10 '19 at 19:42
  • For those coding a UWP app you will need to add the Shared User Certificates capability in the mainifest. Otherwise, you'll get an empty list instead of an exception. – Guy Lowe Mar 16 '22 at 02:46

4 Answers4

63

Add this line of code to the second line and see how it works:

store.Open(OpenFlags.ReadOnly);

and then this at the bottom :):

store.Close();
Chris B. Behrens
  • 6,255
  • 8
  • 45
  • 71
  • 1
    I also use this to open the store: store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); – rick schott Jan 18 '11 at 21:44
  • 2
    @rickschott: Good point, but since they're bit flags, and the enum value of `OpenFlags.ReadOnly` is 0, specifying it alongside other flags has no specific effect. It will be treated as read-only as long as you don't give the `OpenFlags.ReadWrite` (value 1) flag. `OpenFlags.ReadOnly` is really just a default value to give because the function requires a parameter. Its description isn't even correct technically, since, as I said, it's not a real flag; it doesn't contain a bit to change. – Nyerguds Jun 27 '13 at 10:38
  • 2
    Or you can just wrap it in a `using` block since `X509Store` implements `IDisposable` ;) – RJ Cuthbertson Jul 13 '16 at 20:07
  • 1
    @RJCuthbertson The `IDisposable` interface is only supported by the `X509Store` class since .NET Framework 4.6. Before that you had to wrap it in a `try-finally` block. – Redwolf Mar 16 '17 at 18:33
  • I can make it work locally, when I publish and the client accesses the system, it can not find the certificates. Is there any way to find the certificates on the client, with the application on the server? – Mariana Jan 10 '19 at 19:42
  • It is likely that the security context your client is running in does not have permissions to view the certs you're targeting. – Chris B. Behrens Jan 10 '19 at 20:33
22

All in one ...

I have an apache server (xamp) with https. I access through https and c# (vs2010) to a PHP upload page

  1. Install the certificate from i.e in the personal folder certificate, for example.

  2. To view the certicates run "certmgr.msc" , at least in win7

Listing the personal certificates

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

Find specific certificate

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
  • 4,809
  • 10
  • 46
  • 63
cealex
  • 229
  • 2
  • 2
  • I've made an edit to improve the markup of this post and introduce capitalisation, but the first sentence and point still make limited sense to me. Anyone with a better understanding up for editing? – doppelgreener Feb 21 '13 at 04:49
  • I can make it work locally, when I publish and the client accesses the system, it can not find the certificates. Is there any way to find the certificates on the client, with the application on the server? – Mariana Jan 10 '19 at 19:42
3

I can find certificates by ...

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 will have the certificates I care about ... if it is just one then I get first element in the collection.

Nabheet
  • 1,285
  • 1
  • 12
  • 22
2

Look in your certificate store(mmc/add/certificate snap-in/my user account/Certificates - Current User/Personal/Certificates) to see the subject name to make sure "CN=mypc.domainname" is whats actually on the cert.

"CN=mypc.domainname"

vs

"CN = mypc.domainname"

...etc

rick schott
  • 21,012
  • 5
  • 52
  • 81
  • Yes, I just didn't want to expose my real pc/domain name here. ;) – Pablo Jan 18 '11 at 21:45
  • I know that's not the real CN name you have, just want you to make sure your "mypc.domainame", whatever it really is, is whats on your cert. – rick schott Jan 18 '11 at 21:47