How to register a certificate to a port when the cert is in a custom location using netsh - certificate

My certificate is stored in a custom store under "Certificates(Local Computer)" instead of under "Personal".
Normally, if the cert is located under personal, i just use C:>netsh http add sslcert ipport:0.0.0.0: certhash= appid= certstorename=MY
where, certstorename=MY is already assumed by default if not specified.
This works fine until we were required to store the certificate in a custom store other than the existing personal, trusted people, trusted publishers, etc. etc.
If we called our new store "my cert store", how would the new netsh command look like?
how does the word "MY" map to the "Personal" store? is there a dictionary someplace that maps these?
i checked the System.Security.Cryptography.X509Certificates namespace and there exises an enum called StoreName with the following values:
AddressBook - The X.509 certificate store for other users.
AuthRoot - The X.509 certificate store for third-party certificate authorities (CAs).
CertificateAuthority - The X.509 certificate store for intermediate certificate authorities (CAs).
Disallowed - The X.509 certificate store for revoked certificates.
My - The X.509 certificate store for personal certificates.
Root - The X.509 certificate store for trusted root certificate authorities (CAs).
TrustedPeople - The X.509 certificate store for directly trusted people and resources.
TrustedPublisher - The X.509 certificate store for directly trusted publishers.
I tried all of them on the netsh command as certstorename and i always get this error:
SSL Certificate add failed, Error:1312
A specified logon session does not exist. It may already have been terminated.

What you are trying to do seems correct. Could you retry after applying hotfix http://support.microsoft.com/kb/981506 for a problem which actually matches your symptoms exactly.

A huge flaw is that even if the PrivateKey is not persisted properly, the private key icon will still show up in mmc and it will say "There is a private key associated with this certificate". To know for sure that the private key is being properly imported,
Right click on C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys and take a note of how many files are in the folder (this is where the private keys are kept).
Import the pfx file / however you are adding the certificate/key to the store
Check the file count again of that folder, there should be 1 more file than before
You can try testing this with a newly created, self-signed certificate with a tool like open-ssl. Was stuck on this for weeks until I found this stackoverflow post, Inserting Certificate (with privatekey) in Root, LocalMachine certificate store fails in .NET 4
Another gotcha is to be sure the certificate is in Local Computer (not user), but it looks like you already got that part down.

Open your certificate and double check whether it actually contains a PrivateKey. Depending on how you exported/imported it, it may have been truncated to a public-only data.
In explorer, just double click and check whether "this cert contains private key" warning label is visible on the first tab, just under the expiry dates

I had this problem when the certificate was installed in my local user store, instead of the local machine store. Installing in localMachine/my cleared it up.

Derrick. The certstorename just needs quotes. The AppId is the hardpart. Remove the EnhancedKeyUsageList part if you made a self-signed cert. Otherwise prefer to use a cert designed for a server side certificate.
$appid = "appid={"+(get-host).InstanceId.guid+"}"
$certhash = ls Cert:\LocalMachine\my | where {$_.EnhancedKeyUsageList -Match 'Server' -and $_.subject -match (hostname)}|select -expand Thumbprint -last 1
$cmdline='netsh http add sslcert ipport=0.0.0.0:443 certhash=' + $certhash + ' "' + $appid + '"'
resulting with netsh http add sslcert ipport=0.0.0.0:443 certhash=DD2AA37F947FC61766AF95ADA93DFDC1B171CB8B "appid={723b1673-7ec2-42f2-96c3-e1f5b726feaf}" certstorename="my cert store"
netsh http delete sslcert ipport=0.0.0.0:443
Invoke-Expression $cmdline
SSL Certificate successfully added

Related

iOS Alamofire SSL Pinning with both certificate about to expire and a new certificate

My application implements SSLPining with leaf certificate. And it's about to expire.
I researched and got the answer:
Some time before the certificate expires, release a new version of your app with a replacement cert in the pin list, as well as the original cert
How can i add both replacement cert and original cert to my project?
I just need to add a new certificate with any name and Will Alamofire go through all the certificate files I declare and if any match will it allow the connection?
Thanks
Yes, that will work. Alamofire's PinnedCertificatesTrustEvaluator gathers all certificates from the main bundle by default and checks to see whether the certificate received is within that set. So as long as both certificates are within that set, either of them should work.

keyset does not exist when the private key clearly exists

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.

Always encrypted: Importing certificates to certificate store "My" in location "Current user"

I'm trying to make EF6 work with always encrypted, but I'm having troubles introducing the certificates made by SQL Management Tool to the store location "Current user".
This is the error I get when I query the encrypted data:
Failed to decrypt a column encryption key using key store provider: 'MSSQL_CERTIFICATE_STORE'. The last 10 bytes of the encrypted column encryption key are: '21-14-01-0E-87-A1-04-97-CE-5F'.
Certificate with thumbprint 'C*******************************9839' not found in certificate store 'My' in certificate location 'CurrentUser'. Verify the certificate path in the column master key definition in the database is correct, and the certificate has been imported correctly into the certificate location/store.
Parameter name: masterKeyPath
I tried adding necessary certificates via mmc.exe to the Current user's personal store, but still when I run this:
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
foreach (X509Certificate2 certificate in store.Certificates)
{
Console.WriteLine(certificate.Thumbprint.ToString());
}
...the store is empty. I'm out of ideas, what am I doing wrong?

Signing certificates with an existing Root Certificate Authority

I am trying to setup some certificates for different hostnames (aliases) for SQL Server Reporting Services so that I can secure connections on my own machine for testing purposes. My understanding is that these certificates need to be signed by a trusted Root Certificate Authority (explained here). After doing some research, I've found a lot of helpful information that can generally be summarized by this post; the information I've found tells me how to create new certificates using Powershells New-SelfSignedCertificate cmdlet.
So now I know how to create a new Root CA, and I know how to create an SSL certificate for a given hostname which is signed by the new Root CA. However, I can't find anywhere that explains how to re-use an existing Root CA. I want the code to work like this:
$rootCA = <# What goes here? #>
$TestSigned = New-SelfSignedCertificate -subjectName "CN=TestSignedByRoot" -Signer $rootCA
Am I supposed to just create a new Root CA every time I want to create a certificate? That seems insane so I sure hope that's not the case. If any of you could provide some explanation and sample code it would be greatly appreciated.
To get a certificate from the certificate store with known hash:
$rootCa = ( Get-ChildItem -Path cert:\LocalMachine\My\EEDEF61D4FF6EDBAAD538BB08CCAADDC3EE28FF )
To see what certificates there are in the My store:
Get-ChildItem -Path cert:\LocalMachine\My
To get a certificate by subject name, use Where-Object to check the Subject property:
$rootCa = Get-ChildItem -Path cert:\LocalMachine\My | Where-Object {$_.Subject -eq "CN=My Awesome Root CA"}
You are missing a key word here: Trusted. Not just by you, but by any computer that tries to verify the validity of the certificate. Most companies will have a PKI solution to be able to issue certificates internally, and will have the certificate for the Root CA pushed out via GPO into the Trusted Roots folder of the local machine certificate store. The Root CA should be something that is already established, and trusted by the computers that will be connecting to your SQL server. I would recommend contacting your IT or Security department to ask about if the company has a Trusted Root CA that you can get your certificate signed by, or if they can issue you a certificate that chains to the trusted root.
Edit: Ok, I missed the point. My understanding was 'my machine' being the SQL server that you support vs other computers that would connect to it. If the only computer that you are concerned with is your own, then this comes down to:
Create a Certificate Signing Certificate (Certificate A)
Add Certificate A to the Trusted Root folder of your LocalMachine
certificate store
Create a self signed certificate (Certificate B)
using Certificate A as the signing certificate
Once you have completed steps 1 & 2 you can repeat step 3 as many times as needed to make additional certificates. You should only need 1 Root cert ever. The important part is that the Root certificate is trusted by the 'client', so that when it connects to the SQL reporting service and sees the certificate it can establish a chain of trust to the root certificate that initiated the chain.
To use an existing trusted certificate, you will need a copy of the trusted certificate in the Personal Certificates folder (cert:\LocalMachine\My) I used CertMgr. Else when you finally run your command to create the self signed certificate, you get an error
New-SelfSignedCertificate: CertEnroll::CSignerCertificate::Initialize: Cannot find object or property. 0x80092004 (-2146885628 CRYPT_E_NOT_FOUND)

Can I request a client certificate from Active Directory CA with Powershell?

I'd like to automate the task of requesting client certificates from the CA attached to our Active Directory. Currently, I use certmgr and click "Request New Certificate" from the menu and do several other selections, including selecting an appropriate policy.
Surely, Powershell can help me with this, as I already use it to get rid of old certificates. Is there a module which can be used for this or does Powershell 3 cover this out-of-the-box?
I think certreq could be what you are looking for.
Certreq can be used to request certificates from a certification authority (CA), to retrieve a response to a previous request from a CA, to create a new request from an .inf file, to accept and install a response to a request, to construct a cross-certification or qualified subordination request from an existing CA certificate or request, and to sign a cross-certification or qualified subordination request.
Then there is another useful utility when dealing with certificates in windows - certutil