pjohansson
pjohansson

Reputation: 18766

Getting Chrome to accept a self-signed localhost certificate

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 Internet Explorer. However, they refuse to accept it, even after adding the certificate to the system certificate store under Trusted Roots. Even though the certificate is listed as correctly installed when I click "View certificate information" in Chrome's HTTPS popup, it still insists the certificate cannot be trusted.

What am I supposed to do to get Chrome to accept the certificate and stop complaining about it?

Upvotes: 1812

Views: 1994497

Answers (30)

Binyamin
Binyamin

Reputation: 7803

For development purposes on Windows, you can add the Chrome shortcut flag --ignore-certificate-errors.

It is expected to ignore certificate errors and allows you to access invalid certificate websites.

Better detailed instructions are in https://support.opendns.com/entries/66657664.

Enter image description here


Update: In this days this approach no longer works, and you can use https://mkcert.dev to generate a certificate for local domains, and setup it in your web server configuration.

Example

choco install mkcert
mkcert -install
mkcert mydomain.com

then in Apache configuration

Listen *:443
<VirtualHost *:443>
    ServerName mydomain.com
    DocumentRoot /www
    SSLEngine On
    SSLCertificateFile /mydomain.com.pem
    SSLCertificateKeyFile /mydomain.com-key.pem
</VirtualHost>

Upvotes: 0

mpowrie
mpowrie

Reputation: 641

To create a self-signed certificates in Windows that Chrome v58 and later will trust, launch PowerShell with elevated privileges and type:

New-SelfSignedCertificate -CertStoreLocation Cert:\LocalMachine\My -Subject "fruity.local" -DnsName "fruity.local", "*.fruity.local" -FriendlyName "FruityCert" -NotAfter (Get-Date).AddYears(10)
# Notes:
#    -subject "*.fruity.local" = Sets the string subject name to the wildcard *.fruity.local
#    -DnsName "fruity.local", "*.fruity.local"
#         ^ Sets the subject alternative name to fruity.local, *.fruity.local. (Required by Chrome v58 and later)
#    -NotAfter (Get-Date).AddYears(10) = make the certificate last 10 years. Note: only works from Windows Server 2016 / Windows 10 onwards!!

Once you do this, the certificate will be saved to the Local Computer certificates under the Personal\Certificates store.

You want to copy this certificate to the Trusted Root Certification Authorities\Certificates store.

One way to do this: click the Windows start button, and type certlm.msc.

Then drag and drop the newly created certificate to the Trusted Root Certification Authorities\Certificates store per the below screenshot.

Enter image description here

Upvotes: 9

Soya Bean
Soya Bean

Reputation: 107

Allowing an insecure localhost works fine via this method: chrome://flags/#allow-insecure-localhost

It is just that you need to create your development hostname to xxx.localhost.

Upvotes: 8

Ray Foss
Ray Foss

Reputation: 3883

For Fedora, Ubuntu, Linux, if you're getting the example.com Not a Certification authority error when adding the certificate using the GUI to add a new root authority. If you want to trust a server self signed certificate, it cannot make mention of an invalid authority... even if that's itself. I've only managed to make it work by trusting my authority and using that authorities key to sign server certificates.

Here's the self-signed CA certificate that it accepted. This is the only way that I found works to get around cert_authority_invalid. I tried for hours to get it to accept a self-signed end point certificate, but no cigar. The UI will accept self-signed authorities, as long as it's declared CA:TRUE. After that, all certificates signed by that key with the correct DN will be accepted by Chrome without needing to add them independently.

openssl req -new -x509 -extensions v3_req -days 8440 -config ca.conf -key rockstor.key -out rockstor.cert

[req]
distinguished_name=dn
req_extensions=v3_req
prompt = no

[v3_req]
basicConstraints=CA:TRUE,pathlen:0
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName=@alt_names

[alt_names]
DNS.1 = ca.tdpowerskills.com

[dn]
C = US
ST = LA
L = Alexandria
O = TDPS Certification Authority
OU = LEARNOPS
CN = ca.tdpowerskills.com

openssl req -new -x509 -extensions v3_req -days 8440 -config config.conf -key rockstor.key -out rockstor.cert

[req]
distinguished_name=dn
req_extensions=v3_req
prompt = no

[v3_req]
basicConstraints=CA:FALSE
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName=@alt_names
issuerAltName=DNS:ca.tdpowerskills.com

[alt_names]
DNS.1 = big.tdps.app

[dn]
C = US
ST = LA
L = Alexandria
O = TDPS Certification Authority
OU = LEARNOPS
CN = ca.tdpowerskills.com

If that doesn't work:

  • chrome://restart to actually restart

  • Try to get more details on the error using Firefox. It tends to explain errors better. While Chrome will say: ERR_CERTIFICATE_INVALID, Firefox will throw: MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY.

  • Remember that Chrome now requires Subject Alternative Name and nearly ignores CN.

For others:

  • certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n <nickname> -i <my.crt> for server certificates

  • certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n <nickname> -i <my.crt> for CAs

  • For Firefox, the UI adding an exception certificate does work, and it will trust it once you do that.

  • Perhaps you have funky settings in /etc/pki/tls/openssl.cnf which get merged with your configuration.

  • perhaps you're not adding an extension to the configuration or command line, such as v3_req

  • Note, my method bypasses the need for a CSR by just signing the certificates with the authority key and adding details for the development servers. CSRs allow more keys for actual security.

  • I tried everything, but Chrome requires an authority with basicconstraints CA:true set. And server certificates must all be singed by a valid Authority, even if that's just another certificate that the signed themselves with CA:true.

Upvotes: 9

TetraDev
TetraDev

Reputation: 17124

The GUI for managing SSL certificates on Chromium on Linux did not work properly for me. However, their documentation gave the right answer. The trick was to run the command below that imports the self-signed SSL certificate. Just update the name of the <certificate-nickname> and certificate-filename.cer, then restart Chromium/Chrome.

From the documentation:

On Linux, Chromium uses the NSS Shared DB. If the built-in manager does not work for you then you can configure certificates with the NSS command line tools.

Get the tools

  • Debian/Ubuntu: sudo apt-get install libnss3-tools
  • Fedora: su -c "yum install nss-tools"
  • Gentoo: su -c "echo 'dev-libs/nss utils' >> /etc/portage/package.use && emerge dev-libs/nss" (You need to launch all commands below with the nss prefix, e.g., nsscertutil.) openSUSE: sudo zypper install mozilla-nss-tools

To trust a self-signed server certificate, we should use

certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n <certificate-nickname> -i certificate-filename.cer

List all certificates

certutil -d sql:$HOME/.pki/nssdb -L

The TRUSTARGS are three strings of zero or more alphabetic characters, separated by commas. They define how the certificate should be trusted for SSL, email, and object signing, and are explained in the certutil docs or Meena's blog post on trust flags.

Add a personal certificate and private key for SSL client authentication Use the command:

pk12util -d sql:$HOME/.pki/nssdb -i PKCS12_file.p12

to import a personal certificate and private key stored in a PKCS #12 file. The TRUSTARGS of the personal certificate will be set to “u,u,u”.

Delete a certificate certutil -d sql:$HOME/.pki/nssdb -D -n <certificate nickname>

Excerpt From: https://chromium.googlesource.com/chromium/src/+/HEAD/docs/linux_cert_management.md

Upvotes: 9

Alykoff Gali
Alykoff Gali

Reputation: 1221

For Chrome on macOS, if you have prepared a certificate:

  • Quit Chrome (cmd+Q).
  • Start the Keychain Access app and open the "Certificates" category.
  • Drag your certificate file onto the Keychain Access window and type the password for the certificate file.
  • Double click on your certificate and unfold the "Trust" list.
    • In row "When using this certificate," choose "Always Trust."
    • Close this stuff and type your password.
  • Start Chrome and clear all caches.
  • Check that everything is OK.

Upvotes: 7

Fodort
Fodort

Reputation: 61

It didn't work for me when I tried to import the certificate in the browser... In Chrome, open Developer ToolsSecurity, and select View certificate. Click the Details tab and export it.

Linux

sudo apt-get install libnss3-tools

certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n [EXPORTED_FILE_PATH] -i [EXPORTED_FILE_PATH]

Run this command and if you see the file You've just imported. You are good to go!

 certutil -d sql:$HOME/.pki/nssdb -L

Windows

Start => run => certmgr.msc

On the left side select Trusted Root Certification AuthoritiesPersonal. Click on actions tab → All actions/import. Then choose the file you exported before from the browser.

Don't forget to restart Chrome!!!

Upvotes: 6

zmk110
zmk110

Reputation: 902

Assuming you're on Mac OS X, you can also just open the URL in question in Safari; say; https://localhost:8080/css/app.css, allow the certificate. Restart Chrome, and it will work.

Upvotes: 2

Yevgeniy Afanasyev
Yevgeniy Afanasyev

Reputation: 41410

Click anywhere on the page and type a BYPASS_SEQUENCE:

BYPASS_SEQUENCE Chrome Version
thisisunsafe 65 - ?
badidea 62 - 64
danger ? - 61

You don't need to look for an input field; just type it. It feels strange, but it works. I tried it on macOS v10.13 (High Sierra).

To double check if they changed it again, go to the latest Chromium source code. At the moment the BYPASS_SEQUENCE looks like this:

var BYPASS_SEQUENCE = window.atob('dGhpc2lzdW5zYWZl');

Now they have it camouflaged, but to see the real BYPASS_SEQUENCE you can run following line in a browser console.

console.log(window.atob('dGhpc2lzdW5zYWZl'));

OR

As an alternative to typing the phrase, you can paste this code snippet into the console.

sendCommand(SecurityInterstitialCommandId.CMD_PROCEED)

Upvotes: 286

Logan
Logan

Reputation: 627

I created a Bash script based on some of the other answers to make it easier to generate a self-signed TLS certificate valid in Chrome (tested in Chrome 65.x).

self-signed-tls Bash script

After you install (and trust) the certificate, don't forget to restart Chrome (chrome://restart).


Another tool worth checking out is Cloudflare's cfssl toolkit.

Upvotes: 6

schlm3
schlm3

Reputation: 108

Here is a solution using only Java 8 keytool.exe instead of OpenSSL:

@echo off
set PWD=changeit
set DNSNAME=%COMPUTERNAME%

echo Create a CA key
keytool -genkeypair -alias ca -keystore test.jks -keyalg RSA -validity 3650 -ext bc:critical=ca:true -dname "CN=CA" -storepass:env PWD -keypass:env PWD
echo Generate a certificate request for approximately signing
keytool -certreq -keystore test.jks -storepass:env PWD -alias ca -file ca.csr -ext bc:critical=ca:true
echo generate signed certificate
keytool -gencert -keystore test.jks -storepass:env PWD -alias ca -infile ca.csr -outfile ca.cer -validity 3650 -ext bc:critical=ca:true
echo CA created. Import ca.cer in Windows and Firefox' certificate store as "Trusted CA".
pause

echo Create a server certificate key for %DNSNAME%
keytool -genkeypair -alias leaf -keystore test.jks -keyalg RSA -validity 3650 -ext bc=ca:false -ext san=dns:%DNSNAME%,dns:localhost,ip:127.0.0.1 -dname "CN=Leaf" -storepass:env PWD -keypass:env PWD
echo Generate a certificate request
keytool -certreq -keystore test.jks -storepass:env PWD -alias leaf -file leaf.csr -ext bc=ca:false -ext san=dns:%DNSNAME%,dns:localhost,ip:127.0.0.1
echo Generate a signed certificate
keytool -gencert -keystore test.jks -storepass:env PWD -alias ca -infile leaf.csr -outfile leaf.cer -validity 3650 -ext bc=ca:false -ext san=dns:%DNSNAME%,dns:localhost,ip:127.0.0.1

rem See content
rem keytool -printcert -file leaf.cer -storepass:env PWD

echo Install in the original keystore
keytool -importcert -keystore test.jks -storepass:env PWD -file leaf.cer -alias leaf

echo Content of test.jks:
keytool -list -v -storepass:env PWD -keystore test.jks
pause

You could also use pipes instead of files, but with the files, you can check the intermediate results if something goes wrong. SSL tested with Internet Explorer 11, Edge, Firefox 54, Chrome 60 on Windows and Chrome 60 on Android.

Please change the default password before using the script.

Upvotes: 1

phil_lgr
phil_lgr

Reputation: 372

None of the previous answers helped me on Windows 10 when testing locally on

https://localhost:<port>.

However, I found this page, indicating another flag to pass:

Service Worker Debugging

If you want to test on https://localhost with a self-signed certificate, do:

./chrome --allow-insecure-localhost https://localhost

That did not get rid of the red warning, but it did enable me to use HTTPS-only feature like service workers and web push notifications.

Upvotes: 2

UUHHIVS
UUHHIVS

Reputation: 1199

Windows Jun/2017 (Windows Server 2012)

I followed @Brad Parks's answer. On Windows you should import rootCA.pem in the 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

In my case I have a self hosted web app, so I need to bind the certificate with IP address and port. The certificate should be in 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, I imported the pfx file in the Personal store. (File ⏵ Add or Remove Snap-ins ⏵ Certificates ⏵ Add ⏵ Computer Account ⏵ LocalComputer ⏵ OK)

Later I used this command to bind the 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 is the Certificate Thumbprint
  • appid a 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 the same error:

Screenshot of Chrome saying HTTPS security is broken

But I realized that I should import certificate of the root authority, not the certificate for the domain. So I used MMC console to import rootCA.pem in the Trusted Root Certificates Authorities store. (File ⏵ Add or Remove Snap-ins ⏵ Certificates ⏵ Add ⏵ Computer Account ⏵ LocalComputer ⏵ OK)

Screenshot of certificate import wizard

Restart Chrome and et voilà, it works.

  • With localhost:

    Screenshot of Chrome trusted security for localhost

  • Or with IP address:

    Screenshot of Chrome trusted security for 192.168.0.2

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 to add SAN information. With New-SelfSignedCertificate (Powershell) you can add SAN information; that also works.

Upvotes: 35

John Landells
John Landells

Reputation: 112

This is something that keeps coming up—especially for Google Chrome on Mac OS X v10.10 (Yosemite)!

Thankfully, one of our development team sent me this link today, and the method works reliably, whilst still allowing you to control for which sites you accept certificates.

Chrome: Shortcut past the "Your connection is not private"

jersully posts:

If you don't want to bother with internal certificates...

  1. Type chrome://flags/ in the address bar.
  2. Scroll to or search for Remember decisions to proceed through SSL errors for a specified length of time.
  3. Select Remember for three months.

Upvotes: 5

LunaCodeGirl
LunaCodeGirl

Reputation: 5640

If you're on a Mac and not seeing the export tab or how to get the certificate this worked for me:

  1. Click the lock before the https://
  2. Go to the "Connection" tab
  3. Click "Certificate Information"

Now you should see this:

Different information of course and yours should be marked as trusted yet (otherwise you probably wouldn't be here)

  1. Drag that little certificate icon do your desktop (or anywhere).
  2. 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: 7. Double click the newly added certificate. 8. Under the trust drop down change the "When using this certificate" option to "Always Trust"

Now reload the page in question and it should be problem solved!

To make this a little easier you can use the following script (source):

  1. 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
    
  2. Make the script executable (from the shell):

    chmod +x whitelist_ssl_certificate.ssh
    
  3. Run the script for the domain you want (simply copy/pasting the full URL works):

    ./whitelist_ssl_certificate.ssh https://your_website/whatever
    

Upvotes: 62

What am I supposed to do to get Chrome to accept the certificate and stop complaining about it?

You should create a PKI with;

  1. self-signed Root CA.
  2. sub / intermediate certificate (signed by Root CA).
  3. normal / end-entity certificate (signed either by Root CA or sub-CA)
    • commonName or subjectAltName (SAN) as "localhost".
    • also include https://localhost/ as the URI in SAN.
  4. Import / Install that Root CA in your Windows OS as 'Trusted Root Certification Authorities'.
    • Because you mentioned Internet Explorer: Google Chrome is using the same resources while looking for certificates chain.
  5. Install that end-entity certificate as your web server certificate, and it stops complaining that error message.

Upvotes: 3

Raman
Raman

Reputation: 19665

UPDATED Apr 23/2020

Recommended by the Chromium Team

Deprecating Powerful Features on Insecure Origins

Quick Super-Easy Solution

There is a secret bypass phrase that can be typed into the error page to have Chrome proceed despite the security error: thisisunsafe (in earlier versions of Chrome, type badidea, and even earlier, danger). Do not use this unless you understand exactly why you need it!

Source code:

chromium / chromium / src (D8FC08)

(Note that window.atob('dGhpc2lzdW5zYWZl') resolves to thisisunsafe)

The latest version of the source is @ https://chromium.googlesource.com/chromium/src/+/refs/heads/master/components/security_interstitials/core/browser/resources/interstitial_large.js and the window.atob function can be executed in a JavaScript console.

For background about why the Chrome team changed the bypass phrase (the first time):

"danger" shortcut removed (#41236621)

If all else fails (Solution #1)

For quick one-offs if the "Proceed Anyway" option is not available, nor the bypass phrase is working, this hack works well:

  1. Allow certificate errors from localhost by enabling this flag (note Chrome needs a restart after changing the flag value):

chrome://flags/#allow-insecure-localhost

(and vote-up answer https://stackoverflow.com/a/31900210/430128 by @Chris)

  1. If the site you want to connect to is localhost, you're done. Otherwise, setup a TCP tunnel to listen on port 8090 locally and connect to broken-remote-site.com on port 443, ensure you have socat installed and run something like this in a terminal window:

socat tcp-listen:8090,reuseaddr,fork tcp:broken-remote-site.com:443

  1. Go to https://localhost:8090 in your browser.

If all else fails (Solution #2)

Similar to "If all else fails (Solution #1)", here we configure a proxy to our local service using ngrok. Because you can either access ngrok http tunnels via TLS (in which case it is terminated by ngrok with a valid certificate), or via a non-TLS endpoint, the browser will not complain about invalid certificates.

Download and install ngrok and then expose it via ngrok.io:

ngrok http https://localhost

ngrok will start up and provide you a host name which you can connect to, and all requests will be tunneled back to your local machine.

Upvotes: 95

nikane
nikane

Reputation: 85

Fix for Chrome on Windows.

First, you need to export the certificate.

  • Locate the URL in the browser. “https” segment of the URL will be crossed out with the red line and there will be a lock symbol to the left.
  • Right-click on the crossed-out "https" segment.
  • You will see an information window with various information
  • Click “details”.
  • Export the certificate, follow directions accept default settings.

To import

  • Go to Chrome Settings
  • Click on "advanced settings"
  • Under HTTPS/SSL click to "Manage Certificates"
  • Go to "Trusted Root Certificate Authorities"
  • Click to "Import"
  • There will be a pop up window that will ask you if you want to install this certificate. Click "yes".

Upvotes: 6

cscheltinga
cscheltinga

Reputation: 61

SSL / HTTPS localhost fix on the Mac / OS X:

  1. Click the red lock with the cross in your address bar when trying to open your HTTPS localhost environment. There'll open a window with some information about the certificate.

  2. Click on "Details" information window

  3. The Google Chrome Developer tools opens on the tab 'Security'. Click on View Certificate. The certificate image

  4. Add it to your 'System' keychain (not your 'login' keychain which is selected by default).

  5. Open your keychain (again) and find the certificate. Click on it and make sure you "Trust" all.

  6. Restart Chrome, and it should work.

Upvotes: 5

DejerNet
DejerNet

Reputation: 267

As someone has noted, you need to restart all of Chrome, not just the browser windows. The fastest way to do this is to open a tab to...

chrome://restart

Upvotes: 25

James Oravec
James Oravec

Reputation: 20381

I went down the process of using what bjnord suggested which was: Google Chrome, Mac OS X and self-signed SSL certificates

What is shown in the blog did not work.

However, one of the comments to the blog was gold:

sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain site.crt

You'll need to follow the blog on how to get the certificate file, after that you can use the command above and should be good to go.

Upvotes: 9

kenorb
kenorb

Reputation: 166795

Linux

If you're using Linux, you can also follow these official wiki pages:

Basically:

  • click the lock icon with an X,
  • choose Certificate Information
  • go to the Details tab
  • Click on Export... (save as a file)

Now, the following command will add the certificate (where YOUR_FILE is your exported file):

certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n YOUR_FILE -i YOUR_FILE

To list all your certificates, run the following command:

certutil -d sql:$HOME/.pki/nssdb -L

If it still doesn't work, you could be affected by this bug: Issue 55050: Ubuntu SSL error 8179

P.S. Please also make sure that you have libnss3-tools, before you can use above commands.

If you don't have, please install it by:

sudo apt-get install libnss3-tools # on Ubuntu
sudo yum install nss-tools # on Fedora, Red Hat, etc.

As a bonus, you can use the following handy scripts:

File add_cert.sh

certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n $1 -i $1

File list_cert.sh

certutil -d sql:$HOME/.pki/nssdb -L # add '-h all' to see all built-in certs

File download_cert.sh

echo QUIT | openssl s_client -connect $1:443 | sed -ne '/BEGIN CERT/,/END CERT/p'

Usage:

add_cert.sh [FILE]
list_cert.sh
download_cert.sh [DOMAIN]

Troubleshooting

  • Run Chrome with --auto-ssl-client-auth parameter

    google-chrome --auto-ssl-client-auth

Upvotes: 101

Ira Rainey
Ira Rainey

Reputation: 5209

Are you sure the address the site is being served up as is the same as the certificate? I had the same problems with Chrome and a self-signed certificate, but in the end I found it was just incredibly picky about the validation of the domain name on the certificate (as it should be).

Chrome doesn't have its own certificate store and uses Windows' own store. However, Chrome doesn't provide any way to import certificates into the store, so you should add them via Internet Explorer instead.

Installing certificates in Google Chrome

Installing certificates in Internet Explorer

Also take a look at this for a couple of different approaches to creating self-signed certificates (I'm assuming you're using IIS as you haven't mentioned it).

How to create a self-signed certificate in IIS 7

Upvotes: 15

Ariel
Ariel

Reputation: 2752

  1. Add the CA certificate in the trusted root CA Store.

  2. Go to Google Chrome and enable this flag!

    chrome://flags/#allow-insecure-localhost

    At last, simply use the *.me domain or any valid domains, like *.com and *.net and maintain them in the 'hosts' file. For my local development environments, I use *.me or *.com with a 'hosts' file maintained as follows:

  3. Add to host.

    File 'C:/windows/system32/drivers/etc/hosts':

    127.0.0.1 nextwebapp.me

    Note: If the browser is already opened when doing this, the error will keep on showing. So, please close the browser and start again. Better yet, go incognito or start a new session for immediate effect.

Upvotes: 17

Jellicle
Jellicle

Reputation: 30256

With only 5 openssl commands, you can accomplish this.

(Please don't change your browser security settings.)

With these commands, you can:

  1. Become your own CA
  2. Then sign your SSL certificate as a CA

Instructions:

  1. Copy the code snippet into a new file.
  2. Update the variable NAME (and optionally DNS.2 and IP.1) and save the file.
  3. Run the script (e.g. bash generate_certs.sh). This will generate myCA.pem, $NAME.crt, and $NAME.key for you.
  4. Then in your Chrome settings import the generated CA certificate (myCA.pem) as an "Authority" (not into "Your Certificates"): Settings > Manage certificates > Authorities > Import.
  5. Use the generated $NAME.crt and $NAME.key files in your server for SSL/TLS.

NB: For Windows, some reports say that openssl must be run with winpty to avoid a crash.

######################
# Become a Certificate Authority
######################

# Generate private key
openssl genrsa -des3 -out myCA.key 2048
# Generate root certificate
openssl req -x509 -new -nodes -key myCA.key -sha256 -days 825 -out myCA.pem

######################
# Create CA-signed certs
######################

NAME=mydomain.example # Use your own domain name
# Generate a private key
openssl genrsa -out $NAME.key 2048
# Create a certificate-signing request
openssl req -new -key $NAME.key -out $NAME.csr
# Create a config file for the extensions
>$NAME.ext cat <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = $NAME # Be sure to include the domain name here because Common Name is not so commonly honoured by itself
DNS.2 = bar.$NAME # Optionally, add additional domains (I've added a subdomain here)
IP.1 = 192.168.0.13 # Optionally, add an IP address (if the connection which you have planned requires it)
EOF
# Create the signed certificate
openssl x509 -req -in $NAME.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial \
-out $NAME.crt -days 825 -sha256 -extfile $NAME.ext

Recap

  1. Run the code snippet to (a) become a CA and (b) sign your certificate using your CA cert+key.
  2. Import myCA.pem as an "Authority" in your Chrome settings (Settings > Manage certificates > Authorities > Import).
  3. Use the $NAME.crt and $NAME.key files in your server.

You can check your work to ensure that the certificate is built correctly:

openssl verify -CAfile myCA.pem -verify_hostname bar.mydomain.example mydomain.example.crt

Extra steps for Mac

  1. Import the CA cert at "File > Import file", then also find it in the list, right click it, expand "> Trust", and select "Always"
  2. Add extendedKeyUsage=serverAuth,clientAuth below basicConstraints=CA:FALSE, and make sure you set the "CommonName" to the same as $NAME when it asks for setup.

Extra steps for Windows

  1. Convert the myCA.pem to myCA.pfx by doing:

    openssl pkcs12 -export -out myCA.pfx -inkey myCA.key -in myCA.pem
    
  2. Import the myCA.pfx into the Trusted Certificate Authorities of Windows by opening (double-click) the myCA.pfx file, selecting "Local Machine" and Next, Next again, enter the password and then Next, and select "Place all certificates int he following store:" and click on Browse and choose "Trusted Root Certification Authorities" and Next, and then Finish.

Now your CA certificate is trusted by Windows. When you import and use the $NAME certificate it will be automatically trusted by Windows and Chrome.

Upvotes: 506

Chris
Chris

Reputation: 18884

For localhost only (Chrome 119 and above)

  1. Simply visit this link in your Chrome:

    chrome://flags/#temporary-unexpire-flags-m118
    
  2. You should see highlighted text saying:

    Temporarily unexpire flags that expired as of M118. These flags will be removed soon. – Mac, Windows, Linux, ChromeOS, Android, Fuchsia, Lacros

  3. Click Enable Then relauch Chrome.

For localhost only (Chrome 118 and below)

  1. Simply visit this link in your Chrome:

    chrome://flags/#allow-insecure-localhost
    
  2. You should see highlighted text saying:

    Allow invalid certificates for resources loaded from localhost

  3. Click Enable.

Options for other sites

Upvotes: 1285

Sean
Sean

Reputation: 2667

I couldn't find any of these answers that did everything from start to finish, so here are the steps for windows (I'm using win 11) with IIS installed, using openSSL (I used chocolatey to install openssl, not covered here) and using only vanilla PowerShell script language (no bash), without changing any browser settings at all (like allow-insecure-localhost), and no need to bypass security errors (e.g. thisisunsafe, badidea, danger).

This process here is only for creating local testing SSL certificates for faked domains and their subdomains that you've inserted into the C:\Windows\System32\drivers\etc\hosts file. (e.g. 127.0.0.1 example.com). You will need a separate line entry in the hosts file for each and every subdomain as well (e.g. 127.0.0.1 sub.example.com) because there doesn't seem to be a *.example.com way to do this. Be sure to leave an empty line at the end of the hosts file or you will go on a murderous rampage.

Some of this content was borrowed and updated from https://github.com/BenMorel/dev-certificates.

The below powershell script creates the 10-year CA certificate and key. You only need to create and install these files once, but you'll have to do it again if you lose these files because you can't generate the SSL certificates without them.

openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -subj "/C=US/O=_Development CA/CN=Development certificates" -key ca.key -sha256 -days 3650 -out ca.crt

The resultant ca.crt file has to be imported using the "manage computer certificate" interface (search for this app in your windows start popup), entered into the "trusted root certification authorities/Certificates" leaf. Right-click on said Certificates leaf and choose All Tasks/import, then select the file.

The below powershell script is for generating individual domain SSL certificates. You first need to global replace example.com with the desired domain, then execute it in powershell.

# replace anywhere you see example.com text with your domain
openssl genrsa -out "example.com.key" 2048
openssl req -new -subj "/C=US/O=Local Development/CN=example.com" -key "example.com.key" -out "example.com.csr"
"authorityKeyIdentifier=keyid,issuer" | Out-File -encoding utf8 -FilePath "example.com.ext"
"basicConstraints=CA:FALSE" | Out-File -encoding utf8 -FilePath "example.com.ext" -Append
"keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment" | Out-File -encoding utf8 -FilePath "example.com.ext" -Append
"extendedKeyUsage = serverAuth, clientAuth" | Out-File -encoding utf8 -FilePath "example.com.ext" -Append
"subjectAltName = @alt_names" | Out-File -encoding utf8 -FilePath "example.com.ext" -Append
"[alt_names]" | Out-File -encoding utf8 -FilePath "example.com.ext" -Append
"DNS.1 = example.com" | Out-File -encoding utf8 -FilePath "example.com.ext" -Append
"DNS.2 = *.example.com" | Out-File -encoding utf8 -FilePath "example.com.ext" -Append
openssl x509 -req -in "example.com.csr" -extfile "example.com.ext" -CA ca.crt -CAkey ca.key -CAcreateserial -out "example.com.crt" -days 3650 -sha256
rm "example.com.csr"
rm "example.com.ext"
certutil -p password,password -mergepfx example.com.crt example.com.pfx

Next go into IIS manager, select the top node (server), and select Server Certificates. Import (top right), and select the pfx file that was created earlier (password is 'password' unless you changed it above), and 'personal' certificate store. Next, select your site, select bindings (right side), and add (or edit) an https type, set the host name to your domain (e.g. example.com), select Require Server Name Indication, and then choose the SSL certificate you just installed. Repeat, adding a second https binding, but this time with a host starting with *. (e.g. *.example.com, * is important to include subdomains). If it won't accept the *, then you'll need a separate entry for each subdomain. Should work with all browsers, at least all Chromium browsers. Test. Celebrate.

Upvotes: 1

flavio.donze
flavio.donze

Reputation: 8100

Windows: Single-File generate and self sign certificate

This is a "single-file" example to generate root and actual domain certificate on windows. Edit the first four variables, no further input from the CMD is required:

SET ROOT=my-root
SET NAME=demodomain
SET SUBJECT=/C=CH/O=My Demo Company
SET PASSWORD=ptGXHr3sudczSL9Q

:: Generate private key
openssl genrsa -des3 -out %ROOT%.key -passout pass:"%PASSWORD%" 2048
:: Generate root certificate 
openssl req -x509 -new -nodes -key %ROOT%.key -sha256 -days 3650 -out %ROOT%.crt -passin pass:"%PASSWORD%" -subj "%SUBJECT%"


openssl genrsa -out %NAME%.key 2048
openssl req -new -key %NAME%.key -subj "%SUBJECT%/CN=%NAME%" -out %NAME%.csr

(
echo authorityKeyIdentifier=keyid,issuer
echo basicConstraints=CA:FALSE
echo keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
echo subjectAltName = @alt_names
echo [alt_names]
echo DNS = %NAME%)>config.ext

openssl x509 -req -in %NAME%.csr -CA "%ROOT%.crt" -CAkey "%ROOT%.key" -CAcreateserial -out %NAME%.crt -days 1780 -sha256 -extfile config.ext -passin pass:"%PASSWORD%"

:: cleanup files used for certificate generation
del %NAME%.csr
del config.ext

If you want to have the complete chain in one file add the following to your bat file:

:: build chain in certificate-file
echo %ROOT%.crt >> %NAME%.crt
Type "%ROOT%.crt" >> %NAME%.crt

Append the following if you want to verify the certificate:

openssl verify -CAfile "%ROOT%.crt" -verify_hostname %NAME% %NAME%.crt

Open your root certificate my-root.crt and add it to the windows certificate store
(choose Trusted Root Certificate Authorities):

enter image description here enter image description here


Final result in Chrome:

enter image description here

Upvotes: 2

Ensai Tankado
Ensai Tankado

Reputation: 343

Here the Way i do:

For Ubuntu / other Linux (in my case "example.org" - please use your own host for the whole Example Code):

  1. Edit hosts File ("/etc/hosts") and put in the following:

    127.0.0.1    example.org
    
  2. Do the following command in the Console:

    sudo apt-get install wget libnss3-tools
    
  3. Then Do:

    sudo apt-get install -y ca-certificates
    
  4. After this - do the following (important for create certificate):

    wget https://github.com/FiloSottile/mkcert/releases/download/v1.4.3/mkcert-v1.4.3-linux-amd64
    
  5. Then do this command:

    sudo mv mkcert-v1.4.3-linux-amd64 /usr/bin/mkcert
    
  6. Then set this for the access rights:

    sudo chmod +x /usr/bin/mkcert
    

Now you set up the mkcert - now we can use it:

Do this Command in the Terminal

sudo mkcert -install example.org 127.0.0.1

Now the files:

example.org+1.pem

and

example.org+1-key.pem

are created - just copy them to the folder "/etc/ssl":

sudo cp example.org+1* /etc/ssl/
  

Now just install your webserver (apache for me):

sudo apt-get install apache2
  

Then set the ssl mod to the webserver:

sudo a2enmod ssl
  

Ok - now just use the following command (for the vhost config):

sudo nano /etc/apache2/sites-available/example.org.conf
 

Now put the following there:

# HTTP
 
<VirtualHost *:80>
 DocumentRoot /var/www/html
 ServerName example.org
 ServerAlias www.example.org
</VirtualHost>
 
# HTTPS
 
<VirtualHost *:443>
 DocumentRoot /var/www/html
 ServerName example.org
 ServerAlias www.example.org
 SSLEngine on
 SSLCertificateFile /etc/ssl/example.org+1.pem
 SSLCertificateKeyFile /etc/ssl/example.org+1-key.pem
</VirtualHost>

Save it and do the following command in the Terminal (for add the vhost config to the webserver) (apache for me):

sudo a2ensite example.org.conf

Now at last you have to reload the Webserver (here apache):

sudo systemctl reload apache2

Now you have it - try to open now your website with the "https://" prefix (here: https://example.org) - it should now be working without any security error.

Upvotes: 1

Brad Parks
Brad Parks

Reputation: 72221

On the Mac, you can create a certificate that's fully trusted by Chrome and Safari at the system level by doing the following:

# create a root authority cert
./create_root_cert_and_key.sh

# create a wildcard cert for mysite.com
./create_certificate_for_domain.sh mysite.com

# or create a cert for www.mysite.com, no wildcards
./create_certificate_for_domain.sh www.mysite.com www.mysite.com

The above uses the following scripts, and a supporting file v3.ext, to avoid subject alternative name missing errors

If you want to create a new self signed cert that's fully trusted using your own root authority, you can do it using these scripts.

create_root_cert_and_key.sh

#!/usr/bin/env bash
openssl genrsa -out rootCA.key 2048
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.pem

create_certificate_for_domain.sh

#!/usr/bin/env bash

if [ -z "$1" ]
then
  echo "Please supply a subdomain to create a certificate for";
  echo "e.g. www.mysite.com"
  exit;
fi

if [ ! -f rootCA.pem ]; then
  echo 'Please run "create_root_cert_and_key.sh" first, and try again!'
  exit;
fi
if [ ! -f v3.ext ]; then
  echo 'Please download the "v3.ext" file and try again!'
  exit;
fi

# Create a new private key if one doesnt exist, or use the xeisting one if it does
if [ -f device.key ]; then
  KEY_OPT="-key"
else
  KEY_OPT="-keyout"
fi

DOMAIN=$1
COMMON_NAME=${2:-*.$1}
SUBJECT="/C=CA/ST=None/L=NB/O=None/CN=$COMMON_NAME"
NUM_OF_DAYS=825
openssl req -new -newkey rsa:2048 -sha256 -nodes $KEY_OPT device.key -subj "$SUBJECT" -out device.csr
cat v3.ext | sed s/%%DOMAIN%%/"$COMMON_NAME"/g > /tmp/__v3.ext
openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days $NUM_OF_DAYS -sha256 -extfile /tmp/__v3.ext 

# move output files to final filenames
mv device.csr "$DOMAIN.csr"
cp device.crt "$DOMAIN.crt"

# remove temp file
rm -f device.crt;

echo 
echo "###########################################################################"
echo Done! 
echo "###########################################################################"
echo "To use these files on your server, simply copy both $DOMAIN.csr and"
echo "device.key to your webserver, and use like so (if Apache, for example)"
echo 
echo "    SSLCertificateFile    /path_to_your_files/$DOMAIN.crt"
echo "    SSLCertificateKeyFile /path_to_your_files/device.key"

v3.ext

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
    
[alt_names]
DNS.1 = %%DOMAIN%%

One more step - How to make the self signed certs fully trusted in Chrome/Safari

To allow the self signed certificates to be FULLY trusted in Chrome and Safari, you need to import a new certificate authority into your Mac. To do so follow these instructions, or the more detailed instructions on this general process on the mitmproxy website:

You can do this one of 2 ways, at the command line, using this command which will prompt you for your password:

$ sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain rootCA.pem

or by using the Keychain Access app:

  1. Open Keychain Access
  2. Choose "System" in the "Keychains" list
  3. Choose "Certificates" in the "Category" list
  4. Choose "File | Import Items..."
  5. Browse to the file created above, "rootCA.pem", select it, and click "Open"
  6. Select your newly imported certificate in the "Certificates" list.
  7. Click the "i" button, or right click on your certificate, and choose "Get Info"
  8. Expand the "Trust" option
  9. Change "When using this certificate" to "Always Trust"
  10. Close the dialog, and you'll be prompted for your password.
  11. Close and reopen any tabs that are using your target domain, and it'll be loaded securely!

and as a bonus, if you need java clients to trust the certificates, you can do so by importing your certs into the java keystore. Note this will remove the cert from the keystore if it already exists, as it needs to update it in case things change. It of course only does this for the certs being imported.

import_certs_in_current_folder_into_java_keystore.sh

KEYSTORE="$(/usr/libexec/java_home)/jre/lib/security/cacerts";

function running_as_root()
{
  if [ "$EUID" -ne 0 ]
    then echo "NO"
    exit
  fi

  echo "YES"
}

function import_certs_to_java_keystore
{
  for crt in *.crt; do 
    echo prepping $crt 
    keytool -delete -storepass changeit -alias alias__${crt} -keystore $KEYSTORE;
    keytool -import -file $crt -storepass changeit -noprompt --alias alias__${crt} -keystore $KEYSTORE
    echo 
  done
}

if [ "$(running_as_root)" == "YES" ]
then
  import_certs_to_java_keystore
else
  echo "This script needs to be run as root!"
fi

Upvotes: 142

Related Questions