Create Trusted Self Signed Certificates

Create Trusted Self Signed Certificates

By properly creating a self signed certificate, we can get rid of the nagging browser errors for good.

Create the `.certs/` Directory.

To get started we'll need a directory to store all of our certificates and private keys.

I have chosen a ~/.certs/ directory, but it can be whatever and wherever you want.


You can do this from the command line with the following.

bash
1# Create the ~/.certs directory.
2
3$ mkdir ~/.certs
4

Generate and Trust the Root Private Key, and Certificate.

Now we’ll generate the root private key, and certifcate. Then you'll instruct your OS to trust this certificate.

Trust is Key

The secret to producing trusted self signed certificates, is configuring the operating system to to trust the certificate that signed it. As long as the signing certificate is trusted, any certificates it signs will also be trusted.


Generate the Root Private Key

First we'll need a private key. 2048 bits is perfect. Change the -out directory as needed.

bash
1# Generate a private key.
2
3$ openssl genrsa \
4 -out ~/.certs/root.key \
5 2048
6

Generate the Root Certificate

Next, we'll generate a self signed certificate that will serve as our development certificate authority.

Again change the -out directory as needed.

bash
1# Generate a self signed certificate that will serve as the Certificate Authority.
2
3$ openssl req \
4 -x509 -new -nodes \
5 -key ~/.certs/root.key \
6 -sha256 \
7 -days 1825 \
8 -out ~/.certs/root.pem \
9 -subj "/CN=Local CA"
10

Configure Mac OS to trust the Certificate

Now that we have our self signed certificate, lets tell Mac OS that it should be trusted.

bash
1# Tell Mac OS to add the certificate to it's keychain.
2
3$ sudo security add-trusted-cert -d -r trustRoot -k "/Library/Keychains/System.keychain" ~/.certs/root.pem
4

Generate Self Signed Development Certificates

Great! Now, we’re ready to generate the self signed certificates for your development sites.

I like to place everything in a ~/.certs/ directory, however you may prefer to place the certificates with their associated projects. It's up to you.


Generate Private Key for Development Domain

First we'll create a new directory within ~/.certs/ for a hypothetical project called test.local. And then we create the private key.

You can do this is one step with the following.

bash
1# Creates a new directory, and a private key within it.
2
3$ mkdir ~/.certs/test.local \
4 && openssl genrsa -out ~/.certs/test.local/test.local.key 2048
5

Generate a Code Signing Request

You can think of a Code Signing Request as an order form that you send the root certificate. The root certificate recieves the code signing request and fulfills the order.

Note the CN=test.local part of the following command. CN stands for Common Name and its the url that you use to access your site. If it's localhost, be sure to add the port number.

bash
1# Create a Code Signing Request.
2
3$ openssl req -new \
4 -key ~/.certs/test.local/test.local.key \
5 -out ~/.certs/test.local/test.local.csr \
6 -subj "/CN=test.local"
7

Generate Extension File

A relatively recent requirement for SSL certificates is that they provide a Subject Alternative Name. Without one, Chrome will load the website, however it will display with the familiar red lock, and give an untrusted site warning.

No worries we can add the Subject Alternative Name to our Code Signing Request with an extension file.

bash
1# Create an extension file.
2
3$ echo "\nDNS.1 = test.local" >> ~/.certs/test.local/.extfile
4

Generate the self signed certificate

Finally we can generate our trusted self signed certificate by sending our code signing request to the root certificate.

bash
1# Generate a trusted self signed certificate by sending a CSR to the trusted certificate.
2
3$ openssl x509 -req \
4 -in ~/.certs/test.local/test.local.csr \
5 -CA ~/.certs/root.pem \
6 -CAkey ~/.certs/root.key \
7 -CAcreateserial \
8 -out ~/.certs/test.local/test.local.crt \
9 -days 365 \
10 -sha256 \
11 -extfile ~/.certs/test.local.extfile
12

Verify the Certificate is Trusted

To prove that the certificate is trusted, here's one last command.

bash
1# Verify the certificate is trusted.
2
3$ openssl x509 -noout -text -in ~/.certs/test.local/test.local.crt
4

Command Reference

Heres a quick reference on all the commands I provided above.

bash
1# Generate a private key.
2$ openssl genrsa -out example.org.key 2048*
3
4# Generate an untrusted self signed certificate.
5$ openssl req -x509 -new -nodes -key $PATH_TO_PRIVATE_KEY -sha256 -days 1825 -out $PATH_TO_SAVE_CERT -subj "/CN=Local CA"
6
7# Tell Mac OS to trust a certificate to sign certificates.
8$ sudo security add-trusted-cert -d -r trustRoot -k "/Library/Keychains/System.keychain" $PATH_TO_CERT
9
10# Generate a Code Signing Request
11$ openssl req -new -key $PATH_TO_PRIVATE_KEY -out $PATH_TO_SAVE_CSR -subj "/CN=$SITE_DOMAIN_NAME"
12
13# Create a Code Signing Request extension to add a Subject Alternative Name.
14$ echo "\nDNS.1 = $DOMAIN_NAME" >> $PATH_TO_SAVE_EXT_FILE
15
16# Generate a Certificate from a Code Signing Request
17$ openssl x509 -req -in $PATH_TO_CSR -CA $PATH_TO_ROOT_CERTIFICATE -CAkey $PATH_TO_ROOT_PRIVATE_KEY -CAcreateserial -out $PATH_TO_CREATE_CERTIFICATE -days 365 -sha256 -extfile $PATH_TO_EXTENSION_FILE
18

- Comments -