Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save drmason13/efa09668492ef0e978a0c79794b7ee29 to your computer and use it in GitHub Desktop.
Save drmason13/efa09668492ef0e978a0c79794b7ee29 to your computer and use it in GitHub Desktop.
Self Signed Certificate with Custom Root CA

Create Root CA (Done once)

Attention: rootCA.key is the key used to sign the certificate requests, anyone holding this can sign certificates on your behalf. So keep it in a safe place! You should encrypt it with a password

In one line

openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 -keyout rootCA.key -out rootCA.cert

If you want a non-password protected key just add the -nodes option:

openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 -keyout rootCA.key -out rootCA.cert
#                                           ^^^^^^^

that's nodes as in "no DES" as in "no encryption"

Here we used our root key to create the root certificate that needs to be distributed in all the computers that have to trust us.

Create a Certificate (Done for each server)

This procedure needs to be followed for each server/appliance that needs a trusted certificate from our CA

Create the Certificate Signing Request (csr)

The certificate signing request is where you specify the details for the certificate you want to generate. This request will be processed by the owner of the Root key (you in this case since you create it earlier) to generate the certificate.

Important: Please mind that while creating the signign request is important to specify the Common Name providing the IP address or domain name for the service, otherwise the certificate cannot be verified.

If you need to pass additional config put that in the config file, for example to add alternative names (SANs) to the certificate (recommended).

In one line, with a config

First make the config file, it should look something like this:

certificate.conf

[req]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn

[dn]
C = UK
ST = London
L = London
O = ACME
OU = ACME Inc
emailAddress = [email protected]
CN = example.com

[req_ext]
subjectAltName = @alt_names

[alt_names]
DNS.1 = example.com

Then make a CSR (and the required key) using this one-liner

openssl req -new -newkey rsa:2048 -keyout mydomain.com.key -out mydomain.com.csr -config certificate.conf

Again, if you don't want a password, just add -nodes:

openssl req -new -newkey rsa:2048 -nodes -keyout mydomain.com.key -out mydomain.com.csr -config certificate.conf
#                                 ^^^^^^^

Verify the csr's content

openssl req -in mydomain.com.csr -noout -text

Generate the certificate using the mydomain csr and key along with the CA Root key

openssl x509 -req -in mydomain.com.csr -CA rootCA.cert -CAkey rootCA.key -CAcreateserial -out mydomain.com.cert -days 500 -sha256 -extfile certificate.conf -extensions req_ext

This includes signing req_ext so that the SANs you added to the CSR are actually signed and added to the certificate.

Verify the certificate's content

openssl x509 -in mydomain.com.cert -text -noout

FAQ

Why .cert instead of .crt?

I wanted a good reason to prefer one over the other and vscode gave me one. It recognises .cert and gives a nice padlock icon to the file, but doesn't recognise .crt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment