How to retrieve all certificates in your X509Store - c#

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

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

All in one ...
I have an apache server (xamp) with https. I access through https and c# (vs2010)
to a PHP upload page
Install the certificate from i.e in the personal folder certificate, for example.
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();

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.

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

Related

Accessing Certificate Programatically for SAML2

Setup:
I have a .Net Framework WebForms app and just setup SAML2 using Sustainsys.Saml2 setup on Azure. I'm also using Git for version control (VC) and Azure Key Vault for App Settings and Connection Strings.
Question:
What are other ways I can store and access the certificate for SAML2, even if I can access it programmatically (I'm currently accessing/setting the certificate programmatically)?
I want to prevent adding certificates to our VC as well as adding it manually to the Azure directory.
I tried looking into Key Vault Certificates, but I'm unsure if I can even use this.
You can upload your certificate to your Azure App Service --> TSLSSL setting --> Private Key Certificates (.pfx).
Once uploaded there you can retrieve it programmatically via C# with the following:
public static X509Certificate2 GetX509Certificate2(string certThumbprint, bool validOnly = true, StoreName storeName = StoreName.My, StoreLocation storeLocation = StoreLocation.CurrentUser) {
using (var certStore = new X509Store(storeName, storeLocation)) {
var certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, certThumbprint, validOnly);
// Get the first cert with the thumbprint
var cert = (X509Certificate2) certCollection.OfType<X509Certificate>().FirstOrDefault();
certStore.Close();
return cert;
}
}
Call it via:
var cert = GetX509Certificate2(certificateThumbprint, false, storeLocation: StoreLocation.LocalMachine);
Personally, so it can work locally, deployed and on any of our devs computers, I use the following code so that it can search different locations where it may be stored:
var cert = GetX509Certificate2(certificateThumbprint, false, storeLocation: StoreLocation.CurrentUser);
if (cert == null) {
cert = GetX509Certificate2(certificateThumbprint, false, storeLocation: StoreLocation.LocalMachine);
}

How to add PFX installed certificate to Windows.Web.Http.HttpClient

i have manually installed pfx extention certificate to my machine . How to get and pass in Windows.Web.Http.HttpClient
i tried following way but no luck
var myFilter = new HttpBaseProtocolFilter();
CertificateQuery certQuery = new Windows.Security.Cryptography.Certificates.CertificateQuery();
certQuery.FriendlyName = "TEST"; // This is the friendly name of the certificate that was just installed.
IReadOnlyList<Certificate> certificates = await Windows.Security.Cryptography.Certificates.CertificateStores.FindAllAsync(certQuery);
var client = new HttpClient(certificates[0]);
Can someone help me on this how to add manually installed certificate in httpclient ?
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certs = store.Certificates.Find(
X509FindType.FindByIssuerName, "TEST", false);
//Change FindType to your liking, it doesn't support FriendlyName,
//maybe use your method?
WebRequestHandler handler = new WebRequestHandler();
X509Certificate2 certificate = GetMyX509Certificate();
handler.ClientCertificates.Add(certificate);
HttpClient client = new HttpClient(handler);
There you have it. Maybe use your certificate for the Add method but I don't know if they're compatible.

Adding Certificate to Local Machine Store

I've created a self signed certificate and I'm trying to place it in the Root, and Personal stores of the local machine through code.Previously the following code was working:
var cert = new X509Certificate2(PathToCert, Password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
if (cert != null)
{
var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
store.Open(OpenFlags.MaxAllowed);
if (!store.Certificates.Contains(cert))
{
store.Add(cert);
}
store.Close();
var store1 = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store1.Open(OpenFlags.MaxAllowed);
if (!store1.Certificates.Contains(cert))
{
store1.Add(cert);
}
store1.Close();
}
When I try to add the certificate to the stores (even when running as admin) it will not put them into the Local Machine Stores, it puts the certificate in my CURRENT USER store.
How do I make it put the certificate in the LOCAL MACHINE?

Find certificate location on box/server

I am trying to find where the certificate is stored on my local machine and then as well as our dev servers. I can go Run -> MMC -> File - > Add/Remove SnapIns and select certificates and Current User and see my personal certificates. However, I am trying to utilize this code for an HttpWebRequest and I cannot find the url.
string certPath = #"e:\mycertificate.cer"; //This Value
X509Certificate myCert = X509Certificate.CreateFromCertFile(certPath);
request.ClientCertificates.Add(myCert);
In another area we set up a proxy and do it like this.
proxy.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName, CertificateName);
So obviously a little different implementation and I am unsure as to where/how to find the location to fill in for the first example.
Solution that worked for me
public WebRequest GetWebRequest(string address)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(address);
X509Certificate myCert = null;
X509Store store = new X509Store("My");
store.Open(OpenFlags.ReadOnly);
foreach (X509Certificate2 mCert in store.Certificates)
{
if (mCert.FriendlyName.Contains("certname"))
{
myCert = mCert;
}
}
if (myCert != null) { request.ClientCertificates.Add(myCert); }
return request;
}
Assuming like you want to pick a certificate somehow and not really care if it is from file or not. In this case you can use certificate store object and find one you need (i.e. by thumbprint). Check out this Get list of certificates from the certificate store in C# and MSDN article on X509Store.Certificates which contains sample too:
X509Store store = new X509Store("My");
store.Open(OpenFlags.ReadOnly);
foreach (X509Certificate2 mCert in store.Certificates){
//TODO's
}

Find Certificate by hash in Store C#

How to get Certificate by hash in Windows Store using C#?
sha1 example:7a0b021806bffdb826205dac094030f8045d4daa
this loop works but:
X509Store store = new X509Store(StoreName.My);
store.Open(OpenFlags.ReadOnly);
foreach (X509Certificate2 mCert in store.Certificates)
{
Console.WriteLine( mCert.Thumbprint);
}
store.Close();
Is there a direct method?
var cert = store.Certificates.Find(
X509FindType.FindByThumbprint,
thumbprint,
true
).OfType<X509Certificate>().FirstOrDefault();
Use the Find method on the collection
store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, true)

Categories

Resources