Certificate private key throws CryptographicException under IIS Web Server - c#

In my ASP.NET application I'm loading a certificate from the certificate store:
var myCert = CertificateUtils.GetCertificate("thumbprint");
This certificate contains a key pair which is used to decrypt the encrypted application settings.
The certificate is installed in Personal certificate store under the Local Computer. It works well when the application is running under the IIS Express. But if I execute it under the full IIS Web Server, the myCert instance is missing the private key.
The PrivateKey field of myCert object contains an exception:
'myCert.PrivateKey' threw an exception of type 'System.Security.Cryptography.CryptographicException'
I have checked that other fields of myCert object contain same values (like, for example, certificate serial number, thumbprint or expiration), so it seems it's getting the same certificate under both IIS and IIS Express. Only the private key is missing in the case of full IIS.
The only thing I have changed was the Local Development Server in project's properties ("Use IIE Express" / "Use IIS Web Server"). It's running inside the Azure Emulator Express in both cases.
Does anyone have an idea, why is this happenning?

Running on IIS Express, the program uses your credentials to access the certificate, while on IIS the pool identity's credentials are used. You can easily check the certificate ACL to see who is allowed or not.
Follow these steps:
Check what Application Pool your web site uses
Open Internet Information Services Manager, select Sites in the Connections tree on the left. Select your site in the middle panel and click Basic settings under Actions on the right panel.
Check what identity the Application Pool uses
Select Application Pools in the Connections tree on the left and find the identity in the middle panel. It'll be probably "NETWORK SERVICE".
Add read permissions for the identity used by Application Pool to your certificate
Open the Microsoft Management Console (mmc), add the Certificates snap-in for local Computer account and find your certificate under Personal certificates. Open its context menu, All Tasks and Manage Private Keys.... Click Add.., enter the identity ("NETWORK SERVICE") and click Check Names and OK. Under Permissions for allow only the Read permission.
You can read details in this question: How to give ASP.NET access to a private key in a certificate in the certificate store?

I was having this problem to debug the application ".PrivateKey' threw an exception of type 'System.Security.Cryptography.CryptographicException"
I solve like this:
In mmc > Local Computer > Personal > Certificate > right click on certificate > All Tasks > Manage Private Keys:
Add "everyone" user and select Total Control.

Related

Calling service using certificate :Error - "Keyset does not exist"

I am currently trying to access a service provided by a 3rd party. They have issued us a certificate in PKCS format. The certificate is installed in Local computer - Trusted root directory.
Our application at run time finds this certificate and sends it to the authentication URL hosted by the 3rd party, where it is authenticated and the SAML tokens are issued. This is then used to call the actual service that does the functionality we desire.
when I run my application consuming this service via the service reference in the development machine [Windows 7] everything works smoothly.
Now the pain point is since we have a Citrix environment where the testing would take place, we get an error as
Exception in METHOD: SOAP security negotiation with "Service URL" for
target failed. Inner Exception:
System.Security.Cryptography.CryptographicException: Keyset does not
exist.
Can any one help me in resolving this issue, as am unable to reproduce it my local and it happens only in the server OS, am not sure if its an issue with privileges or some code issue.
There are two likely causes of this issue:
The certificate does not have a private key.
The user your process runs as does not have permissions to read the private key.
As you already have this up & running in your development environment, lets assume the cause is 2.
If you don't know it already, you need to determine the user account that your process runs as on your test server. Then open MMC on the test server and add the Certificates snap-in. Find the certificate, right-click and choose All Tasks | Manage Private Keys... and grant read access to the user.
Read lots more about this at:
X509Certificate - Keyset does not exist
CryptographicException 'Keyset does not exist', but only through WCF
Service failure with CryptographicException – Keyset does not exist
Wcf: Keyset does not exist
Thanks for the information. The root cause for this issue was permission issue for the certificate. Since the certificate was installed in the server with Admin privileges, the permission had to be given to all the users for accessing the certificate.

Certificate issue using WCF with SSL

I'm trying to connect to a service that a 3rd party company is publishing. For the authentication part, we use two certificates, one with a public key and one with a private key.
I've made an console application just to test the certificates in differente stores, with the following possibilities:
Location: Current User; Store: Personal
Location: Local Machine; Store: Personal (installed with admin user. I don't have admin permissions)
It was working until I've changed my computer to another this week. I've tested on other machines and it's working on both configurations. But mine only works when I try the 'Current User Location'. Why? My application needs to use the 'Local Machine Location'.
The only possibility I can think about is some kind of permission. But I'm not finding any clue on web. All the similar links say something about the bindings, wrong certificates, overriding ServiceCallBack, etc.
Someone knows if any permission is needed to use the certificate from LocalMachine?
Obs: the application can find the certificate, but when it uses I got the following error:
Could not establish trust relationship for the SSL/TLS secure channel with authority 'name-of-certificate'
Note: I know there is other posts similar to this, but the problem/scenario is really different.
Possibly the identity of the application pool has to rights to read the private key of the certificate from the Local Machine store.
To add the permission, go to the Certificate snapin, right click the certificate, select All Tasks and Manage private keys. From there, add the application pool identity.
Also, as always, make sure that the application pool's "Load user profile" setting is set to true.

SSL Certificate not in X509Store when uploaded to Azure Website

I have installed a .pfx to my Azure website using the management portal upload certificate.
I am now trying to access them using the code below:
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
certificateStore.Open(OpenFlags.ReadOnly);
var certificates = certificateStore.Certificates;
StringBuilder sb = new StringBuilder();
foreach (var certificate in certificates)
{
sb.AppendLine(certificate.Subject);
}
When published to Azure, a bunch of certificates are listed but not the one that one that I have uploaded.
The certificates listed are here:
CN=WW.azurewebsites.windows.net, OU=CIS(RD), O=Microsoft
CN=FullOSTransport
CN=client.geo.to.stamp.azurewebsites.windows.net
CN=ma.waws-prod-am2-005.azurewebsites.windows.net, OU=OrganizationName, O=Microsoft,
L=Redmond, S=WA, C=US
CN=FullOSTransport
CN=FullOSTransport
I purchased the certificate from Verisign and it appears to be uploaded correctly and does appear in the 'HTTPS' bar in the browser (in Chrome).
Any help would be really appreciated as I'm at a loss here.
Update
It looks like we would need to convert to a Cloud Service for the above code to work. But can I add the certificates to my app_data folder as suggested here?
http://blog.tylerdoerksen.ca/2015/11/29/pfx-certificate-files-and-azure-web-apps/
This seems to work for Azure-Websites without the use of web roles.
Thanks
I have faced the similar issue, below is the solution that worked for me.
Solution:
once you have uploaded your certificate through the Azure portal you need to add an appsetting (also through the portal) called WEBSITE_LOAD_CERTIFICATES and set the value for this to the thumbprint of your uploaded certificate. This can be a comma separated list of multiple thumbprints if you want, or even * to load all your uploaded certificates
Then load ur certificate using the below code.
var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
var certs = store.Certificates.Find(X509FindType.FindByThumbprint, YOUR_THUMBPRINT, false);
I have installed a .pfx to my Azure website using the management portal upload certificate.
I recently had to go through this process for an Azure Web Site so these are the things I would try in this order to save the time.
What you can do to debug?
First, remote into the machine and find whether the certificate exists there. You can find that using mmc.exe and add certificates snap-in. See here for complete instructions.
In the case of an Azure Web Site, you have to enable the remote desktop by going into Azure Management Portal, and then create a session into the VM that has your Web Site deployed.
Deploying certificates
If certificate does not exist, you will have to deploy it. For testing, you could do it manually by going into the VMs using the remote session and importing the certificate.
In the case of Web Site, if you want it to be deployed automatically, you will have to update the service definition files for that role to make sure that the certificate will be deployed properly. Also, keep in mind that your certificate should be uploaded as a "Service Certificate" and not a "Management Certificate" if you want your roles to be able to use it. If you are using Visual studio, you could also add it to your project and that may deploy it.
Permissions
Additionally, (and especially if you had manually deployed the certificate e.g. on a VM), you will need to check that IIS has permissions to access the certificate. This page here explains deploying certificates and how to give appropriate permissions. If your certificate is included in the deployment package, then this is not necessary as Azure Deployment will take care of it.
FYI: It works locally because the certificate already exists in the store your code is looking into, and there's nothing that is going to remove the certificate (unless you do it manually) to verify that if you deployed locally again, the certificate will be deployed again (assuming that your deployment locally and on Azure cloud is exactly the same). In many cases, the local environment and Azure cloud environment can be different (unfortunately), because Azure will provision clean VMs, and everything needs to be deployed properly. On the local machines, we have a lot of "leftovers".

Issue regarding Enabling SSL on IIS 7.0 Using Self-Signed Certificates

if we need to secure web site or use HTTPS for our web site then we need to use certificate at iis level. in development pc we often use Self-Signed Certificates which can be created very easily from IIS.
i visit this url http://weblogs.asp.net/scottgu/archive/2007/04/06/tip-trick-enabling-ssl-on-iis7-using-self-signed-certificates.aspx to learn how to create & use SSL for our site
after doing everything when we run or test the site in local pc then i feel Self-Signed Certificates does not work like real life certificate which people buy. here i am adding couple of picture from there you can see what kind of problem i am talking about.
just see the second picture and look at url. in case of ssl a lock sign come with green color.
so just guide me what else we need to do as a result Self-Signed Certificates just works like real life certificate in my pc. please discuss this in detail or redirect me to right article which can show what else to configure as a result browser address bar should properly reflect for SSL.
thanks
The certificate works the same. The problem is that a self-signed certificate is not always included in the browser's Trusted Issuing authority. If your sole purpose is for development, you can follow this method here of adding your issuer (self) to trusted authority or adding the certificate itself as trusted.
In production website, you need to purchase an SSL certificate because your visitors' browsers cannot trust self-signed certificates as they cannot verify the issuer.
Having said that, for development and testing purposes, the behaviour you described is fine, but if you really need to get rid of the warning, you need to register the certificate in your local PC (all PCs that you don't want to see the warning on) and then use the same certificate for your website in IIS.
Follow this guide from step 2 onward, but here are the outlines:
First you need to copy the certificate to your local PC:
In IIS, export the certificate to a file.
Copy the file to your local PC.
Use MMC to import the certificate from the file. Make sure you import it to Personal folder.
Repeat the last two steps for all PCs.
Now that you have the certificate registered in your local PC, you need to tell your PC to trust it:
View the certificate in MMC and go to the second "Details" tab.
Scroll-down to the "Thumbprint" and selected it to display the certificate hash.
Copy the has into the clipboard (the hash identifies your certificate).
Open Notepad and paste the hash there.
Remove all the spaces from the hash using the "Replace" feature in Notepad.
Use the hash in the following command:
netsh http add sslcert ipport=0.0.0.0:443 appid={214124cd-d05b-4309-9af9-9caa44b2b74a} certhash=PASTE_YOUR_CERT_HASH_HERE
Note: The "AppId" doesn't really matter, its just a GUID.
In MMC, move the certificate from the Personal folder to the Trusted Root Certificates folder.

Websphere MQ access to SSL certificate when running inside IIS7 as DefaultAppPool?

I have a C# Web service which is running under IIS 7.5 on Windows Server 2008 R2 using the DefaultAppPool user as the application identity (IIS APPPOOL\DefaultAppPool). The Web service uses IBM Websphere MQ (7.0.1.2) to do it's stuff and uses the SSL certificates stored in a key.kdb setup via IBMs KeyMan utility.
Normally (for C# apps that are not running IIS) I need to label the personal certificate within the kdb so that it's name matches the user that is running the app i.e. the certificate would be labelled as ibmwebspheremqbs6mjb (see http://www-01.ibm.com/support/docview.wss?uid=swg21245474) and this allows the app to successfully access the SSL certificates within the key.kdb.
But..... when running as a Web service and naming the certificate ibmwebspheremqdefaultapppool the application cannot access the SSL certs. If I change the AppPool identity to be bs6mjb then everything works (I'm not allowed to run the app pool as bs6mjb).
I'd prefer not to setup a default certificate as mentioned in the link above, does anyone know what the certificate should be labelled as to work with DefaultAppPool?
For MQ clients the certificate label must have the user name who runs the client. In your case, for example ibmwebspheremqbs6mjb. If the certificate label is something else, the MQ client (actually GSKit libraries) will not find the certificate to connect to queue manager. I think that's what is happening when you have the label as ibmwebspheremqdefaultapppool.
This blog has interesting and useful details. You may want to check under what user IIS runs and create a certificate for that user and do the required SSL setup between client and MQ queue manager.

Categories

Resources