Be Your Own Certificate Authority

2013/04/21

How to create a Certificate Authority and use it to generate SSL certificates.

There are many reasons why you may need to create your own CA. Although you are advised to sign internet facing services with a certificate from a trusted root entity you have much more freedom when it comes to your intranet or vpn infrastructure. The other use cases may include a WPA2 enterprise access point or an https connection to a private wiki page.

This ariticle describes ubuntu 12.10 and OpenSSL 1.0.1c

To generate a self-signed certificate using OpenSSL on Ubuntu is fairly easy, even though cryptography behind it is not. You can use this post a step by step tutorial. Firstly we will create a CA, then we will use it to sign certificate requests which will be turned into self-signed SSL certificates.

Please note that this is not an introduction to public-key cryptography.

Set up

OpenSSL should be installed by default on ubuntu. You may want to verify that with:

$ which openssl
/usr/bin/openssl

In case it's not (and your output is empty) type:

$ sudo apt-get install openssl

Directories

OpenSSL requires a certain directory structure. I will assume here that the root directory is named my-ca. We can create the structure as follows:

$ mkdir -p my-ca/{certs,crl,newcerts,private}

Files

Additionally we want to create a certificate database: index.txt, a file that stores a serial number to be generated for a certificate: serial and a configuration file openssl.cnf. In case of the latter we will simply copy the default one (/etc/ssl/openssl.cnf in Ubuntu).

$ cd my-ca
(my-ca)$ cp /etc/ssl/openssl.cnf .
(my-ca)$ touch index.txt
(my-ca)$ echo '01' > serial

When we are done we should see the following:

.
├── certs/
├── crl/
├── newcerts/
├── private/
├── index.txt
├── openssl.cnf
└── serial

Config file

Now we need to customize the configuration file to match the my-ca directory structure. Edit openssl.cnf with your favourite editor.

[ CA_default ]

dir             = .                         # <-- Change this
certs           = $dir/certs
crl_dir         = $dir/crl
database        = $dir/index.txt
#unique_subject = no

new_certs_dir   = $dir/newcerts

certificate     = $dir/certs/my-ca.crt    # <-- Change this
serial          = $dir/serial
crlnumber       = $dir/crlnumber

crl             = $dir/crl.pem
private_key     = $dir/private/my-ca.key  # <-- Change this
RANDFILE        = $dir/private/.rand

Diff should look like this:

(my-ca)$ diff /etc/ssl/openssl.cnf openssl.cnf 
42c42
< dir           = ./demoCA              # Where everything is kept
---
> dir           = .             # Where everything is kept
50c50
< certificate   = $dir/cacert.pem       # The CA certificate
---
> certificate   = $dir/certs/my-ca.pem  # The CA certificate
55c55
< private_key   = $dir/private/cakey.pem# The private key
---
> private_key   = $dir/private/my-ca.key # The private key

Extensions

For a reference, we encounter following extensions on the key files.

File extension Meaning
KEY A private key, should not be distributed to public.
CSR A certificate request - this is generated by us or anyone who whats us to sign his or her certificate. After a certificate is generated this can be deleted.
CRT A certificate, which can be publicly distributed.
CRL A certificate revocation list, which can and should be publicly distributed.
PEM Some servers need a single file containing concatenated KEY and CRT. PEM files can be used for that purpose.

Keys

Since we have the infrastructure in place we can start generating the keys.

CA key

Firstly, we need to generate the CA key. You will need to provide a pass-phrase and the details of your organization.

(my-ca)$ openssl req -config openssl.cnf -new -x509 -extensions v3_ca -keyout private/my-ca.key -out certs/my-ca.crt -days 1825
Generating a 2048 bit RSA private key
....................+++
...........................................................................+++
writing new private key to 'private/my-ca.key'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
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]:PL
State or Province Name (full name) [Some-State]:Wielkopolska
Locality Name (eg, city) []:Poznan
Organization Name (eg, company) [Internet Widgits Pty Ltd]:AcmeLTD
Organizational Unit Name (eg, section) []:InternetOps
Common Name (e.g. server FQDN or YOUR name) []:acme.pl
Email Address []:cert@acme.pl
req
PKCS#10 X.509 Certificate Signing Request (CSR) Management
-config openssl.cnf
Use customized OpenSSL config
-new
Generate new certificate request and prompt the user for field values (like Country Name, etc).
-x509
Output self-signed certificate instead of a certificate request.
-extensions v3_ca
This is a CA certificate.
-keyout private/my-ca.key -out certs/my-ca.crt
Where the certificate and its key should be generated.
-days 1825
The certificate is valid roughly five years.

Please note that by default the organization details are interpreted as ASCII strings. You may want to use -utf8 to change it.

We have our own CA now! We are ready to sign any incoming certificate requests.

Import the root CA certificate on your intranet machines.

If you do not want to see these warnings that connection is untasted and you should be take out from there, import the CA certificate to a browser/operating system key store. You can follow the steps outlined here:

You should import the my-ca.crt file for this purpose.

Server certificate request

We will start with a private key for the webserver.

(my-ca)$ openssl genrsa -out private/my-domain.key 2048

It is generated without a password, so if you restart a webserver the certificate needs not to be decrypted by entering a password.

Now we can start with the request.

(my-ca)$ openssl req -new -key private/my-domain.key -out my-domain.csr

You will be prompted for the organization details, so consider using also the -utf8 option. Please bear in mind that the Common Name field is very important, as it indicates your domain, e.g. my-domain.com. You may also want to use *.my-domain.com for certificates valid also for subdomains.

Finally, we can sign it.

(my-ca)$ openssl ca -config openssl.cnf -policy policy_anything -out certs/my-domain.crt -infiles my-domain.csr

policy_anything is defined in the openssl.cnf.

This creates two files:

certs/my-domain.crt
Signed certificate
newcerts/01.pem
The same with certificate serial id (not needed).

The key (my-domain.key) and the certificate (my-domain.crt) can be used to configure https connection to a web server. The certificate request (my-domain.csr) can be safely deleted.

Verify the certificate

You can see the certificate’s info with the following:

(my-ca)$ openssl x509 -subject -issuer -enddate -noout -in certs/my-domain.crt

Or the following:

(my-ca)$ openssl x509 -in certs/my-domain.crt -noout -text

And verify that the certificate is valid for server authentication with the following:

(my-ca)$ openssl verify -purpose sslserver -CAfile certs/myca.crt certs/my-domain.crt

Sources

Hope this post is useful for you. I used the following sources when preparing it:

>> Home