Visual C# - Checking installed certificate - Does nothing if it doesnt exist - c#

This is probably a very basic error, but i am pulling my hair trying to understand why this is happening.
I have a check against the store certificates if it contains a certain certificate with a name. If it doesnt, then update a label.text.
It does the check just fine and it finds it, but no matter what i do it doesnt handle if it isnt there. Its not doing anything. No text beeing displayed. I have also tried a simple else without the (!mCert) but still no go.
// Certificate controls
X509Store store = new X509Store("My", StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
foreach (X509Certificate2 mCert in store.Certificates)
{
if (mCert.Issuer.Contains("Cert-Name"))
{
label3.Text = "Found certificate";
}
else if (!mCert.Issuer.Contains("Cert-Name"))
{
label3.Text = "Didnt find the certificate";
}
}
So the else if statement isnt doing anything. Even if i just put an else instead there it isnt updating the label3.text.

If the store is empty and cant find any certificates the foreach will never run, thats why the if statements never get processed.
Adding this before the foreach will solve it
if (store.Certificates.Count==0)

"My" store of local machine is very likely to be empty (unless you install things such as IIS, where the installer generates test certificates).
Thus, switch to other stores, such as using StoreName enumeration,
https://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.storename(v=vs.110).aspx
You can always open MMC to see stores and certificates,
https://msdn.microsoft.com/en-us/library/ms788967(v=vs.110).aspx

Related

Cant get private key from certificate

So, I having trouble to get the private key from the certificate. This is my first time working with certificates and I have tried to find a solution to this but I cant make i work. It's a console application and a need the key to sign a SOAP message/request.
Here is a code sample; (Let me know if you need anything more)
public static X509Certificate2 FindCertificate(string issuedBy)
{
var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
//We gets the certificate from store
var certificate = store.Certificates.Cast<X509Certificate2>().FirstOrDefault(c => c.Issuer.Contains($"CN={issuedBy}"));
if (certificate.HasPrivateKey) // Result: True
{
//PrivateKey throws error: Keyset dosent exist
var key = certificate.PrivateKey;
}
if (certificate == null)
{
throw new ArgumentException($"Could not find certificate issued by: '{issuedBy}'", nameof(issuedBy));
}
var expireDate = DateTime.Parse(certificate.GetExpirationDateString());
if (expireDate < DateTime.Now)
{
throw new Exception($"Certificate has already expired: '{expireDate}'");
}
return certificate;
}
An alternative to your own solution (so you don't have to run VS in administrator mode is to give your own user privileges to read the private key.
Open the certificate manager for your machine certificates (type in "certificates" in Windows home menu search and choose "Manage computer certificates"
Find the certificate and right click -> "All Tasks" -> "Manage Private Keys..."
Click "Add..."
Type in your username (and click "Check Names" to see if you typed it in correctly)
Click "OK" and "OK"
Now you should be able to run your application (and VS) normally with access to the private key.
I was able to get it to work now just by start Visual Studio in Admin mode.

PushSharp's notification to Apple generate temp RSA files on server

I'm having a problem with my WCF push notification service.
Every time it sends a push notification to apple, a new RSA is generated inside the "C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys" folder.
I think that the problem causing this might be related to the Apple p12 Certificate.
Why does that happen? Is there any way to prevent the generating of those RSA?
I'm using PushSharp library and my code looks like this:
pushBroker = new PushBroker();
pushBroker.RegisterAppleService(
new PushSharp.Apple.ApplePushChannelSettings(false, appleCert, p12Pass, false)
, null);
The temporary file is where Windows has put the RSA private key that it loaded out of the appleCert PFX blob.
If the file appears, then disappears (since you called it a "temp" file), then everything's working as expected. If it appears and stays forever then PushSharp is loading the certificate with PersistKeySet, which says that the private key shouldn't be deleted.
I don't know if https://github.com/has-taiar/PushSharp.Web/blob/master/PushSharp.Apple/ApplePushChannelSettings.cs is the real source of ApplePushChannelSettings, but it'll do. Looking at that source, they seem to be using PersistKeySet, making the file permanent.
You have two practical approaches:
1) Load the certificate into an X509Store as a one-time operation (using PersistKeySet on load because you need to for store persistence). The file becomes permanent, but gets used for forever, so it's cool.
2) Load the certificate yourself from the PFX and (ideally) Dispose the certificate when you're done. I don't know if you have any sort of on-shutdown notification that you can more-or-less reliably use, but calling cert.Dispose() (or, on older Framework versions, cert.Close()) is more reliable than waiting on the GC and Finalizer to do the cleanup for you.
If you do have a good shutdown event:
// Note that I'm not specifying any X509KeyStorageFlags here.
// You don't want it PersistKeySet (that's the whole point) and you don't
// need it to be exportable (unless you get exceptions without Exportable, in which case
// PushSharp is doing something naughty).
private X509Certificate _cert = new X509Certificate2(appleCert, p12CerPass);
...
_broker.RegisterAppleService(new PushSharp.Apple.ApplePushChannelSettings(_cert, false));
...
// In some OnShutdown type location
_cert.Dispose();
If not:
// Still don't specify any load flags. Especially not PersistKeySet.
var cert = new X509Certificate2(appleCert, p12CerPass);
_broker.RegisterAppleService(new PushSharp.Apple.ApplePushChannelSettings(cert, false));
No matter what you'll still end up with a permanently leaked file every time your process abnormally terminates, since the file-deletion code won't get a chance to kick in.
A solution exists to completely avoid creating the temporary file, and that is to use the EphemeralKeySet flag which was added to .NET Core 2.0 (currently in preview). It's not yet available in .NET Framework.
// Keep the private key in memory, never let it touch the hard drive.
var cert = new X509Certificate2(appleCert, p12CerPass, X509KeyStorageFlags.EphemeralKeySet);
_broker.RegisterAppleService(new PushSharp.Apple.ApplePushChannelSettings(cert, false));
But I don't know if PushSharp is available for .NET Core.
I had the same problem and i found the solution
to prevent generate key every time you send new push notification,
the code should be like this. and it work perfect for me
var cert = X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable;
var certificate1 = new X509Certificate2(appleCert, p12CerPass,cert);
_broker.RegisterAppleService(new PushSharp.Apple.ApplePushChannelSettings(certificate1, false));

Adding a Certificate to x509Store doesn't do anything C#

I'm trying to add certificates but the Add function doesn't seem to do anything.
I have two certificates. Both I can add manually by right clicking and saving to the personal "testStore" store but they don't get saved when I try to add them programmatically. I even added just one of them, and the X509Store object contains it just as expected, but when I call .Add(cert), nothing gets saved there.
//I've already added 1 cert manually
X509Certificate2 cert2 = new X509Certificate2(#"C:\temp\Cert2.cer");
X509Store store = new X509Store("testStore", StoreLocation.CurrentUser);
store.Open(OpenFlags.MaxAllowed);
//here store.Certificates has the one Certificate I added manually as expected.
store.Certificates.Add(cert2);
//here store.Certificates still only has the first certificate, cert2 still isn't there..
store.Close();
Am I missing something?
Edit
I've also tried using StorePermission (as below) and also tried impersonating the administrator account and those didn't help either
StorePermission sp = new StorePermission( PermissionState.Unrestricted);
sp.Flags = StorePermissionFlags.AllFlags;
sp.Assert();
I got it to work... It turns out you should use store.Add() instead of store.Certificates.Insert();
//When LocalMachine is used, .Add() requires that you run the app as an administrator in order to work.
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
X509Certificate2 cert = new X509Certificate2("C:\\test\\test.cer");
store.Open(OpenFlags.MaxAllowed);
store.Add(cert);
store.Close();
Try with this flag:
store.Open (OpenFlags.ReadWrite);
http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.openflags(v=vs.110).aspx

How to obtain CN of the certificates in particular store?

i want to obtain the CN of the certificates stored in the MY store as i want to verify if the certificate exists or not in that store.
I don't know the which method should be used to perform this task.
I tried using below code but it doesn't works
X509Certificate2Collection cers = store.Certificates.Find(X509FindType.FindBySubjectName,"Root_Certificate",false);
if(cers.Count>0)
{
//certificate present
}
else
{
//certificate not present
}
Does the subjectName gives CN?
is there any other method?
Please suggest me how to check whether a particular certificate is present or not and i want to do it using CN.
You could use the store.Certificates.Find(X509FindType.FindBySubjectName, "SubjectName", false)
function to search for a certificate by its subject name. Do NOT include "CN=" in the subject name.
To search more specific you could use the thumbprint to search for your certificate.
The following code sample demonstrates this:
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.IncludeArchived);
foreach (var c in store.Certificates)
{
Console.Out.WriteLine(c.Thumbprint);
Console.Out.WriteLine(c.Subject);
}
// Find by thumbprint
X509Certificate2Collection col =
store.Certificates.Find(X509FindType.FindByThumbprint, "669502F7273C447A62550D41CD856665FBF23E48", false);
store.Close();
I've added a foreach loop to the code sample to iterate over all certificates in the selected store.
Your certificate must be listed there. If not, you probably use the wrong store.
Note, there is a My store for the Machine and the Current User. So, be sure to open the right store.
To get the thumbprint of your certificate follow these steps:
Open certmgr.msc.
Double click on your certificate.
Go to the details tab.
Under thumbprint you will find the thumbprint of your certificate.
Hope, this helps.

Registry access exception problem

I'm currently building a registry explorer, mostly because I want to support some much better searching operations. Like 'find all' and regular expressions. One problem I'm facing is that some keys throw a security exception when opening. I HAVE TRIED running the app with administrator priviledges, my user account is an administrator also. I embedded a manifest with "requireAdministrator" requested priviledges. I have also tried setting the ClickOnce security settings to Full trust, which is incompatible with requireAdministrator, or so Visual Studio tells me.... Nothing seems to help with avoiding this exception.
I would just like to iterate over all of the keys. I do not wish to add/delete keys. If a user wishes to delete a key and does not have permission to do so, it would display an error message. I just want to be able to have unrestricted READ access. Is this possible?
FTR: I'm on Win7 x64 and using Vs2010u and project is written in C# on .net 4.0. If regedit is capable of reading all keys even if it doesn't let you edit some of them. It would seem appropriate that we too can make an app to do the same thing. Though I'm finding it very difficult, and there doesn't seem to be any real help on the www. Only link-link circles, yay.
[EDIT]
Here's the code that reads the keys:
private void IterateSubKeys(RegistryKeyModel key) {
var subKeys = key.Key.GetSubKeyNames();
var values = key.Key.GetValueNames();
foreach (var valuename in values) {
try {
var valueKind = key.Key.GetValueKind(valuename);
var value = key.Key.GetValue(valuename);
key.Values.Add(new RegistryValueModel(valuename, value, valueKind));
}
catch { }
}
foreach (var keyname in subKeys) {
try {
var subkey = key.Key.OpenSubKey(
keyname,
RegistryKeyPermissionCheck.ReadSubTree,
RegistryRights.ReadKey);
key.SubKeys.Add(new RegistryKeyModel(subkey));
}
catch { Console.WriteLine("Error reading key: {0}", keyname); }
}
}
This is by design. There are lots of security related keys that can only accessible to the System account. You can't use that account. Regedit can't read these keys either, they are just not visible. Avoiding the expensive exception is going to require pinvoke.

Categories

Resources