Unity load Certificate from Windows Store - c#

I want to load a certificate from local windows certificate store.
With UWP my code looks like the following and I can fetch my certificate:
public static X509Certificate2 ClientCertificate()
{
X509Certificate2 cert = null;
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
for (int i = 0; i < store.Certificates.Count; i++)
{
cert = store.Certificates[i];
if (cert.Thumbprint == "68c8e9abc4b950a88701047af543a94c61c9ae38".ToUpper())
{
break;
}
}
return cert;
}
When using Unity 2019.4 I get an error message in line store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);, saying:
System.Security.Cryptography.CryptographicException: Store My doesn\'t exists.
What am I doing wrong with my Unity-code that I cannot access certificates from local windows certificate store?

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

The private key is not present in the X.509 certificate from code bu available in certificate manager

So I am trying to use certificates to establish communication between my solution and a SOAP based service.
I have their certificate and my certificate installed into the certification store.
I have made sure that my certificate has a private key that corresponds to it:
Certificate has private key corresponding to it
However when loading my certificate in my code from the store I get the error "The private key is not present in the X.509 certificate."
I printed the following and can see that the Private Key is empty and ContainsPrivateKey == False
ClientCertificatePublicKey: System.Security.Cryptography.X509Certificates.PublicKey, ClientCertificatePrivateKey: , ContainsPrivateKey False
So far I have tried:
Setting the keystorageflags to:
X509KeyStorageFlags.MachineKeySet|
X509KeyStorageFlags.PersistKeySet|
X509KeyStorageFlags.Exportable
Setting Load User Profile to true in Applicaion Pool
Below is a snippet of how I read the certificate from the store
private byte[] ReadCertificate(string certificateThumbprint)
{
X509Store store = new X509Store("MY",StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection =
(X509Certificate2Collection)store.Certificates;
X509Certificate2Collection signingCert =
collection.Find(X509FindType.FindByThumbprint,
certificateThumbprint,false);
byte[] rawdata = signingCert[0].RawData;
store.Close();
return rawdata;
}
Does anybody have any idea on how I can fix this?
byte[] rawdata = signingCert[0].RawData;
actually, this returns only public part of the certificate, without private key reference. Instead, you shall consider to return entire X509Certificate2 object.

Certificate found although deleted

I imported a certificate called S0021679776.pfx to a Windows 8 through CERTMGR.MSC.
Then I deleted it (from the certificates manager as well as deleting the file itself).
However, when I run the following code, it still finds the certificate.
Why is that? I searched for certificate by "Issue By" and it is not found.
static void FindCert(string CertificateName)
{
X509Certificate2Collection certificates;
Console.WriteLine("looking for certificate " + CertificateName);
X509Store store = new X509Store("My", StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
//FindBySubjectDistinguishedName
certificates = store.Certificates.Find(X509FindType.FindBySubjectName, CertificateName, false);
Console.WriteLine("# of certificates: " + certificates.Count.ToString());
foreach (X509Certificate2 item in certificates)
{
Console.WriteLine(item.GetName());
}
}
}
The output:
looking for certificate S0021679776
# of certificates: 1
C=DE, O=SAP Trust Community, OU=SAP Service Marketplace, CN=S0021679776

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?

How to retrieve all certificates in your X509Store

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

Categories

Resources