In order to avoid warning messages about self-signed certificates when developing web applications on a local machine you can create your own devlopment Root Certificate Authority
.
By trusting this Root CA
you then implicitly trust any certificates that it has signed, so you don’t need to keep adding certificates to your local store as long as they were signed by the Root CA
.
NB
This post assumes you are using Powershell
.
Installation
You can check to see if you have openssl
installed by running the following at a command line
openssl version
If you get a version back it’s already installed. If not you can use chocolatey.
choco install openssl
You’ll now need to close and re-open your PowerShell
window to ensure that you get the updated path. (I find refreshenv
does not work reliably for me.)
Generating the Root CA
You may find it helpful to create a folder to work in. I’m working on my secondary HDD on D:\
. Adjust your path accordingly
md \certificates
cd certificates
First of all we need to create a private key for our CA
.
Since we are going to implicitly trust any certificates signed by this CA
it makes sense to password protect it for safety’s sake
openssl genrsa -aes256 -out root-ca.key 4096
You will be prompted to enter a pass phrase. Make sure you choose a strong one.
As mentioned above if a bad actor can get a hold of your CA
and use it to sign something, you will implicitly trust it.
You should now have a private key in the file root-ca.key
.
We’ll now create the Root CA
. We’ll tell openssl
to create a new key valid for 3650 days using our root-ca.key
and output that to root-ca.crt
For our purposes we can use the default configuration, but if you really want to lock down the creation of the Certificate Authority, you can use a configuration file. This page has a great guide Note that I have also skipped creating an
Intermediate CA
. See here for details as to the difference.
openssl req -new -x509 -days 3650 -key root-ca.key -out root-ca.crt
You’ll be prompted to enter the pass phrase you created above, then some details for the CA
key.
Country Name (2 letter code) [AU]:GB
State or Province Name (full name) [Some-State]:England
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:PaxDev
Organizational Unit Name (eg, section) []:PaxDev
Common Name (e.g. server FQDN or YOUR name) []:PaxDev
We can now import the CA
to the LocalMachine\Root
(Local Computer\Trusted Root Certification Authorities
in the Certificates MMC snap-in).
From an elevated PowerShell
prompt:
Import-Certificate root-ca.crt -CertStoreLocation Cert:\LocalMachine\Root\ -Verbose
Create a new SSL Certificate to use on a website
First of all we need to create a signing request. We’ll pass in the configuration in a file.
Create a new file. The name is unimportant, but I’ll go with ssl.conf
[req]
default_bits = 4096
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = v3_req
[dn]
C = GB
ST = England
O = PaxDev
CN = localhost-dev
[v3_req]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @subjectAltNames
[subjectAltNames]
DNS.1 = localhost
DNS.2 = *.test-domain.com
IP.1 = 10.0.0.22
The first section sets up the key size and mode, then sets the distinguished name to be in the section [dn]
and instructs openssl
that we are using the V3 X.509
extensions and names the section they are in.
This allows us, in particular to
- State that this is not
CA
certificate - i.e. it cannot be used to sign other certificates - Use
Subject Alt Names
to define multiple addresses and wildcards that this certificate will authenticate.
The subjectAltNames
section is a list of the URLs and/or IP Addresses that this certificate will be used for
We now generate a private key for the SSL certificate
openssl genrsa -aes256 -out localhost-dev.key 4096
You’ll be prompted for a passphrase again.
Now create a Certificate Signing Request
or CSR
openssl req -new -key localhost-dev.key -config ssl.conf -out localhost-dev.csr
You’ll be prompted for the pass phrase you created in the previous step (not the CA
pass phrase).
In this case we are signing with the ‘SSL
Key’ to validate that it came from us.
Now we need our Root CA
to create the certificate.
Firstly we need to duplicate the V3 X.509
extensions data from the above config file. I created a file called localhost-dev.v3.ext
:
[v3_req]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @subjectAltNames
[subjectAltNames]
DNS.1 = localhost
DNS.2 = *.test-domain.com
IP.1 = 10.0.0.22
openssl x509 -req -in localhost-dev.csr `
-CA root-ca.crt `
-extfile localhost-dev.v3.ext `
-CAkey root-ca.key `
-CAcreateserial `
-out localhost-dev.crt `
-days 365 `
-extensions v3_req
You will be prompted for the Root CA
pass phrase.
(The Root CA
signs the certificate and because we trusted it earlier we automatically trust any certificates signed by it.)
We need to combine the new Certificate
with the SSL
Key we created just now.
openssl pkcs12 -export -out localhost-dev.pfx -inkey localhost-dev.key -in localhost-dev.crt
You will be asked to confirm the SSL
Key pass phrase. Leave the export password blank.
Finally we need to import the certificate to the LocalMachine\My
(Local Computer\Personal
in the Certificates MMC snap-in) store
Import-PfxCertificate localhost-dev.pfx -CertStoreLocation Cert:\LocalMachine\My\ -Verbose
You can now select your certificate in IIS Manager
for the HTTPS
binding.
NB You will still need to manually add exceptions for the site in Firefox but you do only need to do that once.