We have a service that will generate a CA cert and use that CA cert to sign all other required certs on startup.
The CA cert has an associated private key and is stored in the windows certificate store with Exportable flag. This works fine on most machines but on one of our QA's machine we run into some nasty issues.
When I load the CA cert from the cert store in code and checked HasPrivateKey flag it returns true. Then when I attempt to use the CA cert to sign another cert. It throws keyset does not exist exception.
In the certificate store it says the certificate is valid. On the general page it says
You have a private key that corresponds to this certificate
Good sign! But when we try to right click -> Task -> Export it. The include private key button is grayed out and says
The associated private key cannot be found. Only the certificate can
be exported
We thought its a permission issue so we run mmc in admin mode and still the same result.
On my dev machine I noticed that the private key file is stored in %APPDATA%\Microsoft\Crypto\Keys but its not the case for our QA's machine. We cannot find the private key file in the same folder with the timestamp = CA cert generated time. We also looked into
%ALLUSERSPROFILE%\Application Data\Microsoft\Crypto\SystemKeys
%WINDIR%\ServiceProfiles\LocalService
%ALLUSERSPROFILE%\Application Data\Microsoft\Crypto\Keys
but no luck still.
The account used to run the service is Local System so permission shouldnt be an issue here. No special anti-virus installed other than Windows Defender and nothing in Defender's history either.
Related
We are using IdentityServer4 and our version loads the signing key from a PFX file in file system or from the windows certificate store. Using the certificate works. The question is - which certificate issuer should be used in production?
Is a certificate from a public CA recommended? Or is it enough to have a self-signed certificate (without a CA at all) such as it can be created with IIS Manager?
In our tests we have found that the client could still validate the signature in the access token, even if the signing certificate would not have a valid CA chain on the client.
In the docs, it says that you can also use raw key material instead of a certificate:
http://docs.identityserver.io/en/latest/topics/crypto.html#token-signing-and-validation
In this scenario there would be no CA chain whatsoever.
That leads me to the assumption, that when the client loads the public signing key (via the HTTP(s) endpoint), the CA chain information might not be passed anyways. Is that right? Through the loading mechanism via HTTPs you also have a combined security mechanism.
So my conclusion is that for the signing credential a self-signed cert is just as safe as one from VeriSign. Can this be confirmed?
There is no certificate involved in signing and verifying the tokens. Only a private and public key (RSA or ECDSA key).
However a certificate can be useful to "import/transport" the keys into .NET. So, because of that we don't care about who issued the certificate.
When importing the key, one approach is to bundle the certificate that holds the public key + the private key and store it in a PKCE#12 file (.pfx/.p12 extension). Then load that file into .NET. Before .NET 5 working with keys was a bit hard.
The more important thing is that you can manage and deploy the private key in a secure way and that it is persisted over time.
Optionally, you can add support for key-rotation.
I am developing a desktop application. I can code sign it with .pfx file. I will get that from CA. But what if I want to install it in a different system. Will it reflect there as well? Because I can't share my .pfx file with everyone.
You should not share the *pfx as it contains the private key.
The trust to the signature comes from the trust chain - so when the issuing CA and all intermediate CAs up to the root CA are in the trust store (Windows Trust Store, MAC Key Chain or cacerts.pem for OpenSSL/Java) the signature is trusted as long as
the certificate is not revoked
the signature certificate is not expired or the signature contains a counter signature (RFC3161 timestamp).
How can I export the Token Signing Certificate that is created when ADFS 3.0 is installed? When I open up the certificate MMC, I am able to see the certificate however the message 'You have a private key that corresponds to this certificate' is missing and I am unable to export the private key. I read in the article ADFS deep dive: Certificate Planning that I can find it in Active Directory in the following container:
CN=ADFS,CN=Microsoft,CN=Program Data,DC=domain,DC=com
However, although I can get to that container, all I see is a GUID inside and do not know how to export the private key out of Active Directory.
How can I get the private key?
******************************************** EDIT ********************************************
In case anyone comes to this later, the certs are actually in the personal cert store of the ADFS service account but they are NOT exportable. You almost certainly want the SSL cert private key NOT the token signing cert private key. The documentation
I was following to set up ADFS for SharePoint was a little confusing. The private key had to exported for the SSL cert, however the thumbprint of the token signing cert had to be placed in the web config. I was incorrectly trying to export the private key of the token signing cert.
******************************************** EDIT ********************************************
You mean the self-signed ones you get with automatic rollover?
If so, where do you see these with mmc?
They are stored in a combination of an AD container and the ADFS DB.
So you can't export in the normal manner.
For a very good reason - security. If you have the private key you can send / hack anything and it will be accepted as coming from ADFS.
The public key is available in the metadata.
If you have to do this, turn off automatic rollover and use your own certificates.
I'm trying to get this external REST webservice that requires both a server-side certificate and a private key (both of which I got from the publisher as *.pem files of that service).
For my testing, I googled and found a way to combine these two pieces into a *.pfx file - and loading a X509Certificate2 instance from that binary file on disk works just fine.
Now I was trying to put this into the Cert Store on my production Windows Server 2008.
I can get the X509Certificate2 from the cert store in my C# code - no problem:
X509Store store = new X509Store(StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindBySerialNumber, "serial-number-here", false);
if (certs.Count > 0)
{
X509Certificate2 cert = certs[0];
// set the certificate on the RestClient to call my REST service
_restClient.ClientCertificates.Add(cert);
}
store.Close();
But when I do this, then the web service barfs at me, claiming it needs a "SSL certificate"...
Also: when I was loading the X509Certificate2 from disk, from that *.pfx file, I had to provide a password - nothing needs to be provided here, when loading from the cert store.... odd....
It seems that even though I imported the *.pfx which contains both the server-side certificate and our private key, somehow I cannot get both back from the cert store...
Any idea how I can get this to work? Do I need to load the private key from the cert store in a second step? How?
These certificates still remain mainly a big voodoo-like mystery to me ..... can anyone enlighten me?
The first thing to check is to see whether the certificate store does have the private key.
Open up the certificate management snappin and find your certificate, double click it and make sure it has the red highlighted section like in the image below:
Next, if the private key is in the store then maybe the account accessing the certificate does not have permissions on the private key. There are two ways to check this:
In the certificate management snappin, right click the certificate > All tasks > Manage private keys. (You should be able to check and edit permissions here)
In your code you could access the PrivateKey property (i.e. Do var privateKey = cert.PrivateKey and see whether you get it back).
You did not write how is the web service implemented.
if it is deployed on IIS
if it is self hosted
Your code to get certificate from store is correct. The question is where did you import the pfx - CurrentUser or LocalMachine store. You are using CurrentUser store in the code example. If you imported the certificate to LocalMachine store it will not be found. Also, please specify the store name - StoreName.My (in MMC or certmgr.msc it means Personal) in the constructor of X509Store (it might be default, but who knows all the defaults anyway :) )
But when I do this, then the web service barfs at me, claiming it
needs a "SSL certificate"...
You need to ensure you have Client Authentication in the extended key usage of the certificate.
Also: when I was loading the X509Certificate2 from disk, from that
*.pfx file, I had to provide a password - nothing needs to be provided here, when loading from the cert store.... odd....
It's how it works. When you have a pfx then the private key in it is secured/encrypted with password (password can be an empty string). When you import pfx to certificate store then the private key is secured/encrypted with other key (not exactly sure what key it is). However you can add another level of protection to the private key by specifying strong protection when importing pfx to the store (I do not recommend it when used with ASP.NET, or web services or anything that does not have a desktop). But when it is your personal certificate to sign emails then it might be good to enable it. Windows will then popup a window whenever an application will try to use the private key.
#DanL might be right about the rights to the private key and his
1) - set rights on private key and
2) - accessing private key in X509Certificate2
are written OK. I would just add to 1) that you are trying to connect to the REST service from a ASP.NET application or another web service on IIS then the name of the account that you need to add permission for is IIS APPPOOL\name_of_the_apppool_your_app_runs_under
I want to export the certificate and private key from one machine to another so I can reuse the provisioning profile.
There's a private key under the certificate in keychain access.
1)I exported the the certificate as certifcate .cer file then I imported that from another machine. However , it's missiong the private key. and xcode on the new machine complaining no valid signing key available for the imported provisioning profile.
2) Next I try to export the certificate and the private key as personal information exhange .p12 format, this time it prompted me to input a password which I did.
3)I imported the .p12 file into the new machine, this time the new machine complaining error, cannot read the contents.
So, what should I do to properly export both the certificate and private key and import them into the new machine.
Hope it may help you
In Keychain, select three items: Your private key, public key and the cert from Apple
CMD+Click to select "export 3 items"
and you will export one .cer file. Then double click to import the file without keying any password to protect so.
or you should import cert first and then import both public and private key.
Make sure you also have the Apple Developer Relations Root CA certificate in your keychain. That is what is used to verify the certificate. See in your keychain access whether it has been paired correctly.
With Xcode 5.0+, this has become very simple.
1. On the computer with the developer credentials,
Goto Xcode->Preferences->Accounts.
Click on the gears to export the profile. Choose a password as it includes all your credentials of apple-developer program.
2. Share the exported file with the new computer.
3. Import the profile in your Xcode->preferences->Accounts.