• Home
  • documentation
  • Creating and Maintaining Your Own Certification Authority (incomplete)

Creating and Maintaining Your Own Certification Authority (incomplete)

Vincent Danen

March 25, 2008

Face it. Do you really want to spend $200USD to secure POP3 access for a year that only you and your family uses? Probably not. Yet, if you want to secure POP3 access, you need to create a SSL certificate, and these things need to be signed by someone. You can easily generate a self-signed certificate to get around this, or you can create your own personal Certification Authority so you can create, update, and sign your own certificates, for any service you like, with impunity.

This has distinct advantages. A number of services take advantage of SSL that even if all you do is run your own LAN with an external server or two, creating your own CA will be worth the time spent to do so (and it isn't much). Better that then shelling out a few thousand dollars to secure every service you want to wrap in SSL. Services such as HTTP, LDAP, POP3, IMAP, and more can all take advantage of SSL, and it would be to your advantage to make use of that support. Protecting services in SSL is a good thing.

The only real requirement to creating your own CA is to have OpenSSL installed on your system, and pretty much every BSD, Linux, and other UNIX distribution will come with OpenSSL. If they don't, you can easily obtain it from www.openssl.org and compile your own copy.

There are two ways of managing your CA: Manually, or with the help of an extremely useful tool called TinyCA. The latter is recommended, and requires Perl/TK as it is a GUI interface to managing your CA.

Using TinyCA

Many Linux distributions come with Perl/TK and it can usually be installed from your installation CDs. Mac OS X, however, is a little different and you will need to take a few extra steps in order for it to work properly. You will have to build Perl/TK from source and update your version of Perl (for 10.2) and will additionally have to hack things a little bit (for 10.1). Other BSD implementations and UNIX variants should be able to build Perl/TK from source with little to no issues.

For Mac OS X, there is a good walk-through on installing Perl/TK available at www.lehigh.edu/~sol0/ Macintosh/X/ptk/.

Download and install TinyCA; the current version as of this writing is 0.4.4. The configuration of TinyCA is extremely simple. Untar the file wherever you like; /usr/local might be an appropriate directory, or if you plan on being the only person to manage the CA, untar it in your home directory.

Once you've unpacked it, edit the tinyca script itself. Three things need to change:

BEGIN { push(@INC, './lib'); } # put here the location of the modules

Change this to the full path of the lib/ directory (ie. /usr/local/TinyCA/lib) so that you can call tinyca from anywhere.

# location of openssl
$init->{'opensslbin'} = "/usr/bin/openssl";

Change this to the location of the =openssl= binary on your system. On most systems, this will suffice, but on some you may need to use /usr/local/bin/openssl or, in if you installed OpenSSL using Fink on OS X, /sw/bin/openssl. Executing which openssl on the command line will tell you where your openssl program is.

# directory with the templates
$init->{'templatedir'} = "./templates";

This is where your template files for your CA will reside. Change this to the full path (ie. /usr/local/TinyCA/templates).

Once you have made these changes, you're ready to fire up TinyCA for the first time. Execute tinyca on the command line and you'll be greated with an empty screen. The first step is to click on the CA pulldown menu and create a new CA.

Here you will be asked for some information to generate your CA: A password to protect the private key, your two letter country code, state or province, locality (city) name, Organization Name and Organizational Unit Name, Common Name, Email Address, and how long the key should be valid for. You'll also be asked to select the keylength: 4096, 2048 (default), or 1024 bits. Unfortunately, while the Organizational Unit Name is generally optional, TinyCA insists that you include it. You will also be asked for a name of the CA, which is used only to create the directory the data is stored in. This can be useful if you intend to have more than a single CA.

Once you have done this, proceed and create the certificate. You'll be given a chance to modify options used for creating the CA certificate and also for server and client certs; unless you really know what you're doing, leave these at their defaults. When the CA cert is created, TinyCA will inform you and you can begin to work with certificates immediately.

The idea behind TinyCA is to allow you to take CSR (Certificate Signing Requests), sign them with your CA key, and export the signed certificates for use with individual servers and services. Because of this, TinyCA provides you with a four-tabbed view of managing your CA: The CA itself (which shows the active CA data), Certificates (which shows what certs have been signed), Keys (which shows what client keys have been signed) and Requests (which shows what CSR's are in the system).

If you generate, or receive, a CSR, go to the Requests tab and click "Import Request". You will be given the chance to input the filename or use the browser to find it. Note that TinyCA looks for PEM, DER, or Request (*.req) files, so if you are like me and generally create *.csr files, you'll need to change the file type to "all files". When you've selected your file, you'll be shown the details of the request so you can confirm whether or not to actually import the CSR. Once you've imported it, you can sign it by clicking on the "Sign Request" button.

You'll be asked for the type of certificate to generate (server or client), for your CA password, and for how long the cert will be valid for. Once it's signed, you'll be asked if you want to delete it. Technically, once the CSR has been signed, you no longer need it, so feel free to remove it now, or wait until you're sure the cert was generated properly. Now if you go to the Certificates tab, you'll see your signed cert, which you can then export, revoke, or delete.

While using TinyCA has the advantage that it's somewhat easy to follow and has a decent GUI, I found that I didn't have the kind of flexibility that I wanted, so I prefer to create my own CA from scratch and do things a little manually. TinyCA is a good enough program, but I believe it needs a little more polish and it doesn't seem to have the ability to import data from a previous CA database (or, if it does, I missed it), which throws my serial numbers off. I also could not make it run under OS X, so it was of limited use to me already.

Creating a CA "The Old Fashioned Way"

The real old-fashioned way to handle your own CA is to do everything manually. This is actually the method that I prefer the most as it gives you the greatest control over what you intend to accomplish. The process is very similar to what is covered in the book Network Security with OpenSSL published by O'Reilly. If you want to learn a lot more about OpenSSL than just Certification Authorities, or even if you want to learn a lot of the details of what you are doing with creating your own CA, this book is a recommended read. For our purposes, we will only cover the steps to setup the CA, and not all the theory and detail behind what we are doing.

The first thing that needs to be done is the directory structure and environment for you CA must be created. I keep my CA environment on an encrypted DMG file that is stored on a removable USB disk. This offers a few levels of protection: The USB disk must be physically present in order to mount what is essentially an encrypted loopback filesystem, protected by a strong passphrase. You may not require this same level of protection, but since I had my SSH and GPG keys on the same filesystem, putting the CA there also made sense. So for this example, we will use the directory /Volumes/encrypted/ssl as our directory for the CA files.

In this directory you need to create two subdirectories: certs/ and private/. The certs/ directory is where the certificates that we have issued will be stored. The second directory, private/ stores the CA private key. This directory must be protected to ensure that no one else has read access to the directory or the key stored in it. Remember, if you take the steps I have taken, if the filesystem is mounted and someone obtains access to the system (ie. remote access), they can access the files on the encrypted filesystem if they have sufficient privilege to do so. To that end, standard UNIX permissions are still a factor. To accomplish these steps, execute:

$ mkdir -p /Volumes/encrypted/ssl/{certs,private}
$ cd /Volumes/encrypted/ssl
$ chmod 700 private

Next, we have to create two files: serial and index.txt. The serial file is used to keep track of the last serial number we used to issue a certificate. Each new certificate will have it's serial number incremented by one, so we need to keep track of this. The serial file does this for us. We need to initialize this file with the number "01". The number must be two digits, which is why we pad the number with a leading "0". Finally, the index.txt is like a database that keeps track of the certificates we have issued. OpenSSL requires that this file exists, so we'll just make an empty file:

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

The OpenSSL Configuration File

The next step is to create a configuration file for OpenSSL. This will ease creating and signing certificates because we won't have to pass as much information to openssl on the command line. This file will be stored in our CA directory (/Volumes/encrypted/ssl) and will be called openssl.cnf. Use your favourite text editor to create the file, which would look something like this:

[ ca ]
default_ca = myca

[ myca ]
dir               = /Volumes/encrypted/ssl
certificate       = $dir/cacert.pem
database          = $dir/index.txt
new_certs_dir     = $dir/certs
private_key       = $dir/private/cakey.pem
serial            = $dir/serial

default_crl_days  = 7
default_days      = 365
default_md        = md5

policy            = myca_policy
x509_extensions   = certificate_extensions

[ myca_policy ]
commonName             = supplied
stateOrProvinceName    = supplied
countryName            = supplied
emailAddress           = supplied
organizationName       = supplied
organizationalUnitName = optional

[ certificate_extensions ]
basicConstraints = CA:false

Let's explore the configuration file in a little more depth. The first section "[ ca ]" deals with identifying the default CA we are using. In this case, we define the default CA to be "myca". We then create a new section specifically for this CA which we give the same name as our default CA, in this case "[ myca ]". As you can see here, you can configure multiple CA's and use one as a default and provide commandline overrides to use other CA's when appropriate. If you do create other CA sections, you can override the default_ca by using the name option.

For our CA section, we have to define a number of keywords. The first is the directory where the CA files will be stored. We created /Volumes/encrypted/ssl for this purpose so that is the value we use for the dir keyword. The rest of the keywords in this section simply detail the locations of the certificate file for the CA, the database, directory to place new certificates, the CA's private key, and the location of the file containing the serial numbers.

The next section, still for our CA, details certain defaults for our CA. The default_crl_days keyword specifies the number of days between CRLs (Certificate Revocation Lists). The default_days keyword defines the number of days for which a new certificate will be valid (in our case, the 365 days, or the equivalent of one year). The default_md keyword defines the default message digest algorithm to use when signing CRLs, which can be either "md5", "sha1", or "mdc2".

Finally, we define the default policy for our CA with the policy keyword, in our case the default policy section is "[ myca_policy ]". This policy, which is defined in the section of the same name, determines what information we require in a certificate. Each keyword corresponds to an entry in the certificate, such as commonName or countryName. You can define whether the keyword must match what you specifiy, whether it can be whatever the certificate creator likes (but must be present), or whether the keyword can be optional; it may either be there or not. Use the values match, supplied, or optional respectively.

The final keyword, x509_extension specifies the name of the section that contains the extensions to be added to each certificate the CA issues. If the keyword is omitted, OpenSSL creates an X.509v1 certificate. If the keyword is present, it creates an X.509v3 certificate (even if the keyword is empty). In this example, we set the section to [ certificate_extensions ], where we have further defined that any certificate created cannot be used to create additional CA's.

At this point, OpenSSL needs to know where to find our default configuration file. You can do this by using the -config option passed to openssl or you can set an environment variable (ie. in your ~/.bashrc or somewhere similar) the sets the OPENSSL_CONF environment variable to the location of your configuration file. ie:

$ echo "OPENSSL_CONF=/Volumes/encrypted/ssl/openssl.cnf" >> ~/.bashrc

Creating the Root Certificate

Before you can create any certificates with your CA, you need to generate a certifcate for the CA that is used to sign the certificates it will issue, and also any CRLs it may issue. To do this, you need a certificate signed by another CA, or a self-signed root certificate.


Exporting your CA Certificate

At the end of the day, having your own CA is pretty worthless unless you trust certificates signed by it. To do this, you will need to export your CA root certificate to your clients so that certificates you have signed with your CA can be validated by them. Usually the format required by clients for this purpose is a DER format file (or .crt file). This can be done by executing:

$ openssl x509 -in demoCA/cacert.pem -outform der -out cacert.crt

This will create the DER format file. This file should be transmitted securely to your clients so that they can import it in their web browser or whatever application will be interacting with the secured service. If it is HTTP traffic you are wrapping in SSL, the CA certificate can be imported into the browser simply by viewing it; most browsers can do this (Galeon, Mozilla, and IE for the Mac, although Safari simply downloaded the file).