Create your own Private Certificate Authority
If you don’t want all the nitty gritty technical detail, click here.
Introduction
For this walkthrough I am going to be using openssl specifically version 1.1.1f The documentation for which can be found here. I’ve primarily used this to create certificates for local development, but you can also generate your own certificates for securing communications for your own applications, and for many other purposes. The only down side is that any machine that does not have your public CA certificate on it will give you guff about not trusting the certificate, but thats what properly signed certificates are for. For a free alternative to typical paid ssl certificates for public applications take a look at Let’s Encrypt.
Step 1: Create our CA certificate
First we need a private key for our self signed CA certificate
openssl genrsa -des3 -out CA.key 2048
Because we passed the -des3 flag we will be asked to provide a password for our encrypted private key. Without an encryption specified your private key will not be encrypted.
Generating RSA private key, 2048 bit long modulus (2 primes)
.............................................+++++
.+++++
e is 65537 (0x010001)
Enter pass phrase for CA.key:
Verifying - Enter pass phrase for CA.key:
Now we have a private key and we can use that to generate our self signed CA certificate
openssl req -x509 -new -key CA.key -sha256 -days 1500 -out CA.pem
Tip: CA private key and certificate in one command
Generation of the private key and CA certificate can be done in a single command:
openssl req -x509 -new -nodes -newkey rsa:2048 -sha256 -days 1500 -out CA.pemNOTE: this command does not encrypt your private key due to the
-nodesparameter. I prefer to generate them separately
Here we will be prompted for info on our CA certificate
Enter pass phrase for CA.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:Georgia
Locality Name (eg, city) []:Forsyth
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Local
Organizational Unit Name (eg, section) []:Dev
Common Name (e.g. server FQDN or YOUR name) []:dev.local
Email Address []:notarealemail@emails.org
Tip: Inline subject cli flag
The questions here can be answered with data passed in the cli (
-subj) option:-subj "/CN={commonName}/emailAddress={emailAddress}/C={Country}/ST={State}/L={Locality}/O={Organization}/OU={OrganizationalUnit}"or via a configuration file for
reqcommands.To see the details of a certificate you can run:
openssl x509 -in CA.pem -text -noout
Step 2: Create a certificate signing request
Now that we have out CA certificate and private key we need to install the CA certificate on machines we want to trust the certificate we sign with the CA certificate and private key.
Once our CA certificate is installed on our target devices we can create certificates signed by our CA certificate for our applications to use.
First like above we will want to generate a private key for our certificate:
openssl genrsa -out dev.local.key 2048 # Feel free to specify an encryption if you want to encrypt this key. Ex: -des3
With our domain private key created we can now create a certificate signing request so we can have our certificate signed by our newly created CA certificate.
openssl req -new -key dev.local.key -out dev.local.csr
Tip: Additional inline subject note
As with the other
reqcommand we can specify the answers to the questions asked by this command with the-subjcommand or an configuration file. See example here.
The output from this command is as follows
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:Georgia
Locality Name (eg, city) []:Forsyth
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Local
Organizational Unit Name (eg, section) []:Dev
Common Name (e.g. server FQDN or YOUR name) []:local.dev
Email Address []:notarealemail@emails.org
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
You can leave the challenge password and optional company name blank for our local certificates. Now that we have a certificate signing request we are almost ready to create a signed certificate for our domain. First we need a ext file to define our subject alternative names of which we can have multiple if we need multiple domains or sub domains covered by one certificate.
authorityKeyIdentifier = keyid,issuer
basicConstraints = CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = dev.local
DNS.2 = sub.dev.local
DNS.3 = other.local
For my system I saved that data in a file called dev.local.ext
Now that we have our .ext file we can generate our CA signed certificate!
Step 3: Creating our self signed certificate
openssl x509 -req -in dev.local.csr -CA CA.pem -CAkey CA.key -CAcreateserial -out dev.local.crt -days 825 -sha256 -extfile dev.local.ext
Not we have our dev.local.crt and dev.local.key which we can supply to our app server and if the CA certificate is present on the device browsing the server using our signed cert it will be valid.
Command Details
I wanted to take a moment to give some detail on the commands and parameters / flags used in these commands and provide more context to them.
- genrsa is a tool to generate
RSAprivate keys. This command ends with a number that is the number of bits that is the size of the private key.-des3is used to encrypt the private key with the Triple DES Encryption Algorithm.-outis the output file name for the certificate. If its not provided the private key is output to stdout.
- req is a PKCS#10 certificate request and certificate generating utility.
-x509generates aself signed certificateinstead of acertificate signing request.-newindicates that this is a request for a newself signed certificateorcertificate signing request.-nodeswill leave any private key unencrypted if present.-keyspecified the private key to use for theself signed certificateorcertificate signing request.-keyoutsets the private key generated by thereqcommand if any is created.-sha256sets the digest “hash” of thecertificate signing request. This parameter can be any digestopenssl dgstcan understand for instance it could also be-sha512.openssl helpwill show you a list of available digests.-daysis the number of days the resulting certificate will be valid for.-outIs the output file name for theself signed certificateorcertificate signing requestdepending on if the-x509flag is present. If not provided the output to streamed to stdout.
- x509 is a tool we can use to sign our certificates with our certificate authority. We can also use it to see info about certificates.
-CAspecifies the CA certificate to use for signing the certificate.-CAkeyspecifies the private key used for signing the certificate.-CAcreateserialtells openssl to create a CA serial number file. each certificate signed by thisCA certificatehave its serial number come from this file and then the value in the file is incremented. In some cases a large random number might be used instead.-extfilespecifies the file that defines the certificate extensions to use for the new certificate.-daysis the number of days the certificate is valid for.-sha256is the digest used for our new certificate.-inspecifies the input file for the command.-outspecifies the output file for the command.-textprints the certificate out in text form.-nooutprevents the output of the encoded version of the certificate.
Glossary and additional info
Information on certificate file extensions here.
- Certificate Signing Request
.csris the file extension.- A payload used for having a CA sign a certificate
- Distinguished Encoding Rules
.derIs the file extension.- A specific binary encoding standard.
- Privacy-Enhanced Mail
.pemis the file extension.- At a basic level its Base64 encoded
.derdata, with a header and footer added to the file.
- PKCS
- Public Key Cryptography Standards
- RSA
- A public key cryptographic system where there is a public encryption key and a private decryption key. Technically the encryption / decryption is bi-directional between the keys. Content encrypted with the private key can be decrypted with the public key and vice versa, in the context of HTTPS the public key is used for encryption and the private key is used for decryption.
- X.509
- Is a standard that defines formatting of public key certificates.
- Subject Alternative Name
- Allows various information to be associated to certificates.
Extension file info
The extension file format for openssl v1.1.1x can be found here. The fields in the extension file we use are:
authorityKeyIdentifier=keyid,issuer- The
keyidoption indicates that the subject key identifier will be copied from the parent certificate. - The
issueroption means the issuer and serial number will be copied from the issuer certificate. This only happens if the copy of thekeyidfails or is not included.
- The
basicConstraints=CA:FALSE- Indicates that the certificate to be generated is not a CA certificate.
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment- Defines the valid usage of the certificate
subjectAltName = @alt_names- Defines alternate names this certificate applies to. These can be in several categories like
email,URI,DNS,RID,IPanddirName
- Defines alternate names this certificate applies to. These can be in several categories like
TLDR
Here is a script that will go through the whole process of generating a self signed CA certificate for as many domains as you provide the script.
To call this script you can save this script to a file and run as follows: ./produce_cert.sh domain.one domain.two you will have to provide a password for the CA private key, but other than that you can just hit enter to skip the questions except when its asking you for the CA password.
#!/bin/bash
if [ "$#" -lt 1 ]
then
echo "must provide domain(s) for certificate"
exit 1
fi
## Step 1 create self signed CA certificate
### Step 1.1 Create CA private key. WIll ask for password
openssl genrsa -des3 -out CA.key 2048
### Step 1.2 Create self signed CA certificate
openssl req -x509 -new -key CA.key -sha256 -days 1500 -out CA.pem
## Step 2 create certificate signing request
### Step 2.1 create ext file for self signed certificate
EXT_FILE_NAME="$1.ext"
rm -f $EXT_FILE_NAME 2> /dev/null # remove existing file if it exists.
echo "authorityKeyIdentifier = keyid,issuer" >> $EXT_FILE_NAME
echo "basicConstraints = CA:FALSE" >> $EXT_FILE_NAME
echo "keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment" >> $EXT_FILE_NAME
echo "subjectAltName = @alt_names" >> $EXT_FILE_NAME
echo "" >> $EXT_FILE_NAME
echo "[alt_names]" >> $EXT_FILE_NAME
INDEX=1
for var in "$@"
do
echo "DNS.$INDEX = $var" >> $EXT_FILE_NAME
((INDEX++))
done
### Step 2.2 certificate private key
openssl genrsa -out $1.key 2048
### Step 2.3 create .csr file
openssl req -new -key $1.key -out $1.csr
## Step 3 create certificate signed with self signed CA certificate
openssl x509 -req -in $1.csr -CA CA.pem -CAkey CA.key -CAcreateserial -out $1.crt -days 500 -sha256 -extfile $EXT_FILE_NAME