How to check if a certificate is installed - c#

I just started with .NET and C#. I am trying to check if a computer certificate is there or not. Its a Wireless certificate to be specific.
Here is my code so far:
public void Analyser_Load(object sender, EventArgs e)
{
X509Store store = new X509Store(StoreLocation.LocalMachine);
X509Certificate2Collection col = store.Certificates
.Find(X509FindType.FindBySubjectName, "MyCertName", false);
}

This works:
X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var certificates = store.Certificates.Find(
X509FindType.FindBySubjectName,
"subjectName",
false);
if (certificates != null && certificates.Count > 0)
{
Console.WriteLine("Certificate already exists");
}

The collection itself will be empty if the certificate was not found.
if(col.Count > 0) {
// Cert found!
}
My method for obtaining our certificate:
X509Store store = new X509Store("My", StoreLocation.CurrentUser);
X509Certificate2 cert = default(cert);
try
{
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates.Find(X509FindType.FindBySubjectName, "find.my#cert.com", true);
cert = collection[0];
}
catch(Exception e)
{
throw new Exception("Error while fetching certificate. Please check that the application user can access the store.\r\n" + e.Message);
}
finally
{
store.Close();
}

Related

Why do I get an exception when using .CER Certificate with httpClient in my console app?

I've been looking around the web and tested different solutions, but I still have not found a solution that can solve my problem.
I keep getting an exception, after adding my certificate with .CER extension. When attempting to invoke the web service from my console app, it fails with the message saying:
Could not establish a secure channel for ssl/tls.
Is it something I'm doing wrong in my code? Hope that I can get some help...
public void GetCVR()
{
string url = #"My url";
string certPath = #"My Path to the Certificate.cer";
ServicePointManager.ServerCertificateValidationCallback +=
(sender, certificate, chain, sslPolicyErrors) =>
{
switch (sslPolicyErrors)
{
case System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors:
case System.Net.Security.SslPolicyErrors.RemoteCertificateNameMismatch:
case System.Net.Security.SslPolicyErrors.RemoteCertificateNotAvailable:
break;
}
Console.WriteLine(sslPolicyErrors + " " + chain + " " + certificate);
Console.ReadLine();
return true;
};
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(new X509Certificate2(certPath));
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
var _client = new HttpClient(handler);
_client.DefaultRequestHeaders.Add("User-Agent", Guid.NewGuid().ToString());
_client.DefaultRequestHeaders.Add("Connection", "keep-alive");
_client.BaseAddress = new Uri(baseUrl);
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = _client.GetAsync(url).Result;
}
}
Update 15-09-2019
Ok I change my code above and I add two methods:
private void AddCertificate(string cer)
{
X509Store store = new X509Store(StoreName.Root, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadWrite);
store.Add(new X509Certificate2(X509Certificate2.CreateFromCertFile(cer)));
store.Close();
}
private X509Certificate2 GetMyCert()
{
string certThumbprint = "7a61a6fc";
X509Certificate2 cert = null;
// Load the certificate
var store = new X509Store(StoreName.Root, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certCollection = store.Certificates.Find
(
X509FindType.FindBySerialNumber,
certThumbprint,
false
);
if (certCollection.Count > 0)
{
cert = certCollection[0];
}
store.Close();
return cert;
}
So instead of:
handler.ClientCertificates.Add(new X509Certificate2(certPath));
I first add the certificate to the key store and then I retrieve it as follows.
In debug it looks fine.
X509Certificate2 cert = GetMyCert();
handler.ClientCertificates.Add(cert);
But it still fails with the message saying:
Could not establish a secure channel for ssl/tls.

x509 Certificate for localhost in windows for using AuthenticateAsServer()

hi I want to Create X509Certificate To Use in SslStream.AuthenticateAsServer() on windows 10 loopbak.
I try to Create Certificate with OpenSsl and Makecert Script but certificates not work.
please help me.
my Code :
X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
RawStringData = RawStringData.Replace("CONNECT ", "GET https://");
RawStringData = RawStringData.Replace(":443", "/");
RawStringData = RawStringData.Replace("Proxy-Connection", "Connection");
RawByteArrayData = Encoding.ASCII.GetBytes(RawStringData);
Port = 443;
ServerSocket.Connect(HostEntry.AddressList[0], Port);
HttpsStream = new SslStream(new NetworkStream(ServerSocket));
HttpsStream.AuthenticateAsClient(Host);
HttpsStream.Write(RawByteArrayData);
int Count = HttpsStream.Read(NewData, 0, NewData.Length);
string pfxpath = #"D:\test.pfx";
X509Certificate2 cert = new X509Certificate2(File.ReadAllBytes(pfxpath));
byte[] pfxData = File.ReadAllBytes(pfxpath);
cert = new X509Certificate2(pfxData,"", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
X509Certificate x509 = store.Certificates.Find(X509FindType.FindByIssuerName, "localhost", false)[0];
ssl = new SslStream(new NetworkStream(A) , false , Verification , null );
ssl.AuthenticateAsServer(cert , false, System.Security.Authentication.SslProtocols.Tls, true);
ssl.Write(NewData);

C# smartcard working on terminal

I wrote this code and it's working perfect when we have running app on this same PC where we plug smartcards.
But how I need to do to make this code running when my app is run on terminal and user has smartcards connect to his own PC.
On terminal session I allow to use smartcard for terminal.
User can see this cert but when this cert was chosen then I get error about no private key..
How to use smartcard on a remote PC ?
private X509Certificate2 LetUserChooseCertificate()
{
X509Certificate2 cert = null;
try
{
// Open the store of personal certificates.
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);//StoreName.My StoreLocation.CurrentUser
//X509Store store = new X509Store("addressbook", StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
X509Certificate2Collection fcollection = (X509Certificate2Collection)collection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
X509Certificate2Collection scollection = X509Certificate2UI.SelectFromCollection(fcollection, "Signing", "Choose cert", X509SelectionFlag.SingleSelection);
if (scollection != null && scollection.Count == 1)
{
cert = scollection[0];
if (cert.HasPrivateKey == false)
{
//MessageBox.Show("This certificate does not have a private key associated with it");
//cert = null;
}
}
store.Close();
}
catch (Exception)
{
//MessageBox.Show("Unable to get the private key");
//cert = null;
}
return cert;
}

X509Certificate2 crash IIS

Here is the code that breaks IIS, after doing research I found the following post
X509Certificate2 makes IIS crash and it fixed my problem
var cert = new X509Certificate2();
cert.Import(Resources.wildcard, "xxx", X509KeyStorageFlags.Exportable);
The fixed code
var cert = new X509Certificate2();
cert.Import(Resources.wildcard, "xxx", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
But now this causes my signing to throw the following exception
n exception of type 'System.Security.Cryptography.CryptographicException' occurred in mscorlib.dll but was not handled in user code
Additional information: Invalid provider type specified.
My code
public class RsaSha1
{
private readonly X509Certificate2 _certificate;
public RsaSha1(X509Certificate2 certificate)
{
_certificate = certificate;
}
public string Sign(string signatureBaseString)
{
return SignCore(signatureBaseString);
}
string SignCore(string baseString)
{
using (var hash = Hash(baseString))
{
return Base64Encode(Sign(hash));
}
}
private static string Base64Encode(byte[] signature)
{
return Convert.ToBase64String(signature);
}
private byte[] Sign(SHA1CryptoServiceProvider hash)
{
var formatter = new RSAPKCS1SignatureFormatter(_certificate.PrivateKey).
Tap(it => it.SetHashAlgorithm("MD5"));
//The line above throws the Exception if X509KeyStorageFlags.MachineKeySet is added,
//but without X509KeyStorageFlags.MachineKeySet my application works in a console application (stress testing) but not in IIS (in a web application)
return formatter.CreateSignature(hash);
}
SHA1CryptoServiceProvider Hash(string signatureBaseString)
{
var sha1 = new SHA1CryptoServiceProvider();
var bytes = Encoding.ASCII.GetBytes(signatureBaseString);
using (var crypto = new CryptoStream(Stream.Null, sha1, CryptoStreamMode.Write))
{
crypto.Write(bytes, 0, bytes.Length);
}
return sha1;
}
}
EDIT 1:
New information, it seems that when I add X509KeyStorageFlags.MachineKeySet then _certificate.PrivateKey would throw the Exception but when I remove X509KeyStorageFlags.MachineKeySet then IIS would crash. PS I am using a certificate generated from StartSSL
I imported the Certificate into the LocalMachine Store (not via code)
then in my Software I changed
var cert = new X509Certificate2();
cert.Import(Resources.wildcard, "xxx", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
to
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
foreach (X509Certificate2 certificate in store.Certificates)
{
if (certificate.SubjectName.Name != null && certs.SubjectName.Name.Contains("*.domain.xxx"))
{
cert = certificate;
}
}
This seemed to work better than loading the certificate from a file and also it doesn't break IIS when loaded

How do we store a pfx file in CertStore which is protected using password, retrieve it using password

Can a pfx certificate stored in Cert Store be protected using a password?
I have following function which is trying to export pfx file using password and store to client store.
public bool StoreCertificate(StoreName storeName, StoreLocation storeLocation,X509Certificate2 cert,String password,
X509KeyStorageFlags keyStoreFlags = X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet)
{
var store = new X509Store(storeName, storeLocation);
try
{
store.Open(OpenFlags.ReadWrite);
byte[] pfx = cert.Export(X509ContentType.Pfx, password);
cert = new X509Certificate2(pfx, password, keyStoreFlags);
store.Add(cert);
store.Close();
}
catch (Exception error)
{
m_log.LogError("Add to certificate store failed" + error.ToString());
return false;
}
finally
{
if (store != null)
{
store.Close();
}
}
return true;
}
But while retrieving I was able to retrieve everything without any password using following simple function.
public X509Certificate2 LoadFromStore(StoreName storeName, StoreLocation storeLocation, String password, String subject, X509KeyStorageFlags keyStoreFlags = X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet )
{
var store = new X509Store(storeName, storeLocation);
try
{
store.Open(OpenFlags.ReadWrite);
foreach (var c in store.Certificates)
{
if (c.Subject.Contains(subject))
{
return c;
}
}
}
finally
{
if (store != null)
{
store.Close();
}
}
return null;
}
Is there any easy way of protecting the contents of certificate which includes private key while storing to CertStore?.
Or,
Do we need to associate with an use account?.

Categories