My Technical Notes

Monday, 11 November 2013

OpenSSL Information: Creating a Root CA, Server and Client Certificates

OpenSSL is a command-line application that can be used to create certificates. I am using OpenSSL through Cygwin. The below steps are to (1) setup a root certification authority (2) sign a server certificate and (3) sign a client certificate. The initial folder structure will be:

  • openssl
    • rootCA
    • server
    • client

openssl will contain three subfolders; rootCA, which will contain files for the root certificate authority; and likewise for the server and client subfolders:

mkdir openssl openssl/rootCA openssl/server openssl/client

Creating the Root CA

First cd (change directory) to openssl/rootCA:

cd openssl/rootCA

An RSA private key can be optionally password protected. We will create a file rootCApass.txt to hold our password.

echo r00tCA > rootCApass.txt

Then we generate a 2048 bit long private key using using this password file as input:

openssl genrsa -des3 -passout file:rootCApass.txt -out rootCA.key 2048

After creating the private key rootCA.key, we move onto creating the self-signed root certificate. A certificate must contain (among other things) a Distinguished Name which identifies the subject of the certificate. I will store these details in a separate file rootCA.dn. (The file extension .dn is used to make us aware that the file contains the distinguished name):

# rootCA.dn
prompt             = no
distinguished_name = req_dn

countryName             = GB
stateOrProvinceName     = Leicestershire
localityName            = Leicester
organizationName        = MyCompany Inc.
organizationalUnitName  = MyCompany Trust Network
commonName              = MyCompany Root CA
The following table summarises the meaning of each of the keys:

key meaning
countryName ISO Country Code of your company. These are standardised. See this country code listing.
stateOrProvinceName State of your company. For UK, you could enter your county name.
localityName City of your company.
organizationName Organisation name. Most certificates seem to have "Inc." tacked onto the end of it e.g. Verisign .Inc, Amazon Inc. etc.
organizationalUnitName Organisational Unit. Could be anything, or dropped altogether. I've called mine "MyCompany Trust Network" to imitate VeriSign.
commonName Common Name. If it is a server certificate, you should enter the fully qualified hostname. If it is a client certificate, then enter something meaningful, such as the person's name or repeat the organizationName field value.

Now we have a key file (rootCA.key) and its passphrase (in rootCApass.txt) and the distinguished name (rootCA.dn). We have all the requisites, and now we will create the self-signed root certificate using the req command:

openssl req -config rootCA.dn -new -x509 -days 365 -key rootCA.key -passin file:rootCApass.txt -out rootCA.crt

Our last task is to set up files and directories necessary for signing other certificates using our root CA certificate. First add a file called rootCA.cnf to the rootCA directory with the following content:

default_ca      = CA_default

dir             = .
database        = $dir/index.txt
serial          = $dir/serial
new_certs_dir   = $dir/newcerts

certificate     = $dir/rootCA.crt
private_key     = $dir/rootCA.key

default_days    = 365
default_md      = md5
policy          = policy_any

countryName            = supplied
stateOrProvinceName    = optional
organizationName       = optional
organizationalUnitName = optional
commonName             = supplied
emailAddress           = optional

The rootCA.cnf is used when signing new certificate requests. It takes the pain out of signing because all the details of the root CA are stored in this centralised file. The below table explains what each key is:

key meaning
dir A variable used to define other keys (e.g database is defined as $dir/index.txt which uses $dir)
database A 'database' text file. Each time a certificate is signed, a record of it is kept in this 'database'.
serial A file containing the next serial number. A bit like an auto-incrementing integer primary key.
new_certs_dir Where new certificate files will be copied to.
certificate path to the certificate file; in our case rootCA.crt.
private_key path to the private key file; in our case rootCA.key.
default_days How long the certificate (to be signed) will last.
default_md The default md algorithm. TBH, I don't know what this does, but by default it is md5.
policy The policy governs what fields are mandatory and optional in the certificate request. The policy specified above policy_any, says that only countryName and commonName are required.

As needed by the rootCA.cnf config file; we create the index.txt file, initialise the serial file with "01", and create the newcerts directory:

$ touch index.txt
$ echo "01" > serial
$ mkdir newcerts

This concludes the first step, which is to create the root CA.

Creating a Server Certificate

Change directory to openssl/server:

cd ../server
Create a serverPass.txt file containing our chosen key password:

echo "s3Rv3r" > serverPass.txt
Create our RSA key, passing in the passphrase file defined above:

openssl genrsa -des3 -passout file:serverPass.txt -out server.key 2048
Create a server.dn file containing the distinguished name for the server. Note that the commonName must the fully qualified host name of the server.

# server.dn
prompt             = no
distinguished_name = req_dn

countryName             = GB
stateOrProvinceName     = Leicestershire
localityName            = Leicester
organizationName        = Server Inc.
commonName              =
Create the certification request, passing in the key, passphrase and distinguished name defined above. (The extension .csr stands for certificate signing request).

openssl req -config server.dn -new -key server.key -passin file:serverPass.txt -out server.csr 

Now that we have our certificate signing request, we signed it with the root CA. Go back to the rootCA directory:

cd ../rootCA
Now we sign the request. In order to do so, we need to specify the root CA configuration file to use - rootCA.cnf; the certification request to sign - server.csr; and the passphrase of the root CA - rootCApass.txt (which cannot be stored in the configuration file for security reasons):

$ openssl ca -config rootCA.cnf -in ../server/server.csr -passin file:rootCApass.txt
The folder newcerts now contains a file 01.pem which is our signed server certificate. Copy this file to the server directory as server.crt:

cp newcerts/01.pem ../server/server.crt
Instead you could change directory to newcerts and copy the latest file:

$ cd newcerts
$ cp $(ls -t1 | head -1) ../../server/server.crt
Finally, we export the certificate to PKCS (p12) format, if required. First change directory to that of the server:

cd ../server
Export the certificate using the pkcs12 command. Just like our .key files, .p12 files can also be password encrypted. I am going to copy the serverPass.txt file to serverPassP12.txt so I have the same password for both the key and p12 file:

cp serverPass.txt serverPassP12.txt
Now we are ready to export it to p12 format. We specify the certificate file server.crt, the key server.key, the password for the key serverPass.txt, the new password serverPassP12.txt (same as the old one), the root CA certificate rootCA.crt, and finally where we want to resulting p12 file to be written:

openssl pkcs12 -export -in server.crt -inkey server.key -passin file:serverPass.txt -passout file:serverPassP12.txt -certfile ../rootCA/rootCA.crt -out server.p12

We made a copy of the passphrase file (serverPass.txt) because OpenSSL does not allow the same passphrase file for both -passin and -passout arguments.


So we have covered a few topics - how to setup a root CA; how to generate a certificate request and have it signed by the root CA; and finally how to export our certificate to p12 format. Using these techniques it is quite simple to issue server and client certificates.

The best place to get information about OpenSSL is the official OpenSSL website.


No comments: