I have created a self-signed SSL certificate for the localhost CN. Firefox accepts this certificate after initially complaining about it, as expected. Chrome and IE, however
UPDATE 11/2017: This answer probably won't work for most newer versions of Chrome.
UPDATE 02/2016: Better Instructions for Mac Users Can be Found Here.
On the site you want to add, right-click the red lock icon in the address bar:
Click the tab labeled Connection, then click Certificate Information
Click the Details tab, the click the button Copy to File.... This will open the Certificate Export Wizard, click Next to get to the Export File Format screen.
Choose DER encoded binary X.509 (.CER), click Next
Click Browse... and save the file to your computer. Name it something descriptive. Click Next, then click Finish.
Open Chrome settings, scroll to the bottom, and click Show advanced settings...
Under HTTPS/SSL, click Manage certificates...
Click the Trusted Root Certification Authorities tab, then click the Import... button. This opens the Certificate Import Wizard. Click Next to get to the File to Import screen.
Click Browse... and select the certificate file you saved earlier, then click Next.
Select Place all certificates in the following store. The selected store should be Trusted Root Certification Authorities. If it isn't, click Browse... and select it. Click Next and Finish
Click Yes on the security warning.
Restart Chrome.
UPDATE FOR CHROME 58+ (RELEASED 2017-04-19)
As of Chrome 58, the ability to identify the host using only commonName
was removed. Certificates must now use subjectAltName
to identify their host(s). See further discussion here and bug tracker here. In the past, subjectAltName
was used only for multi-host certs so some internal CA tools don't include them.
If your self-signed certs worked fine in the past but suddenly started generating errors in Chrome 58, this is why.
So whatever method you are using to generate your self-signed cert (or cert signed by a self-signed CA), ensure that the server's cert contains a subjectAltName
with the proper DNS
and/or IP
entry/entries, even if it's just for a single host.
For openssl, this means your OpenSSL config (/etc/ssl/openssl.cnf
on Ubuntu) should have something similar to the following for a single host:
[v3_ca] # and/or [v3_req], if you are generating a CSR
subjectAltName = DNS:example.com
or for multiple hosts:
[v3_ca] # and/or [v3_req], if you are generating a CSR
subjectAltName = DNS:example.com, DNS:host1.example.com, DNS:*.host2.example.com, IP:10.1.2.3
In Chrome's cert viewer (which has moved to "Security" tab under F12) you should see it listed under Extensions
as Certificate Subject Alternative Name
:
WINDOWS JUN/2017 Windows Server 2012
I followed @Brad Parks answer. On Windows you should import rootCA.pem in Trusted Root Certificates Authorities store.
I did the following steps:
openssl genrsa -out rootCA.key 4096
openssl req -x509 -new -nodes -key rootCA.key -newkey rsa:4096 -sha256 -days 1024 -out rootCA.pem
openssl req -new -newkey rsa:4096 -sha256 -nodes -keyout device.key -out device.csr
openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days 2000 -sha256 -extfile v3.ext
Where v3.ext is:
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
IP.1 = 192.168.0.2
IP.2 = 127.0.0.1
Then, in my case I have a self hosted web app, so I need to bind certificate with IP address and port, certificate should be on MY store with private key information, so I exported to pfx format.
openssl pkcs12 -export -out device.pfx -inkey device.key -in device.crt
With mmc console (File/Add or Remove Snap-ins/Certificates/Add/Computert Account/LocalComputer/OK) I imported pfx file in Personal store.
Later I used this command to bind certificate (you could also use HttpConfig tool):
netsh http add sslcert ipport=0.0.0.0:12345 certhash=b02de34cfe609bf14efd5c2b9be72a6cb6d6fe54 appid={BAD76723-BF4D-497F-A8FE-F0E28D3052F4}
certhash=Certificate Thumprint
appid=GUID (your choice)
First I tried to import the certificate "device.crt" on Trusted Root Certificates Authorities in different ways but I'm still getting same error:
But I realized that I should import certificate of root authority not certificate for domain. So I used mmc console (File/Add or Remove Snap-ins/Certificates/Add/Computert Account/LocalComputer/OK) I imported rootCA.pem in Trusted Root Certificates Authorities store.
Restart Chrome and et voilà it works.
With localhost:
Or with IP address:
The only thing I could not achieve is that, it has obsolete cipher (red square on picture). Help is appreciated on this point.
With makecert it is not possible add SAN information. With New-SelfSignedCertificate (Powershell) you could add SAN information, it also works.
Allowing insecure localhost work fine via this method chrome://flags/#allow-insecure-localhost
Just that you need to create your development hostname to xxx.localhost.
Filippo Valsorda wrote a cross-platform tool, mkcert, to do this for lots of trust stores. I presume he wrote it for the same reason that there are so many answers to this question: it is a pain to do the "right" thing for SubjectAltName
certificates signed by a trusted root CA.
mkcert
is included in the major package management systems for Windows, macOS, and several Linux flavors. It is also mentioned in the Chromium docs in Step 4 of Testing Powerful Features.
mkcert
mkcert
is a simple tool for making locally-trusted development certificates. It requires no configuration.$ mkcert -install Created a new local CA at "/Users/filippo/Library/Application Support/mkcert"
If you're on a mac and not seeing the export tab or how to get the certificate this worked for me:
Click "Certificate Information"
Now you should see this:
Drag that little certificate icon do your desktop (or anywhere).
Double click the .cer file that was downloaded, this should import it into your keychain and open Keychain Access to your list of certificates.
In some cases, this is enough and you can now refresh the page.
Otherwise:
Now reload the page in question and it should be problem solved! Hope this helps.
To make this a little easier you can use the following script (source):
Save the following script as whitelist_ssl_certificate.ssh
:
#!/usr/bin/env bash -e
SERVERNAME=$(echo "$1" | sed -E -e 's/https?:\/\///' -e 's/\/.*//')
echo "$SERVERNAME"
if [[ "$SERVERNAME" =~ .*\..* ]]; then
echo "Adding certificate for $SERVERNAME"
echo -n | openssl s_client -connect $SERVERNAME:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | tee /tmp/$SERVERNAME.cert
sudo security add-trusted-cert -d -r trustRoot -k "/Library/Keychains/System.keychain" /tmp/$SERVERNAME.cert
else
echo "Usage: $0 www.site.name"
echo "http:// and such will be stripped automatically"
fi
Make the script executable (from the shell):
chmod +x whitelist_ssl_certificate.ssh
Run the script for the domain you want (simply copy/pasting the full url works):
./whitelist_ssl_certificate.ssh https://your_website/whatever