Creating your own CA – The Miracles of OpenSSL

Currently I’m digging myself into the world of administrating servers. I started with webservers but by now I’m administrating multiple servers that run services like DNS, HTTP, Mail, SVN, MySQL, PostgreSQL and a couple more. My last thing was DNS. I’ve read through the reference book from O’Reilly: DNS & Bind and set up two authoritative and one public DNS server.

Now that I’ve set up all this stuff I need to dig into the next thing. I wanted my fellow students and the professors at my university to use secure connections when they would log into their mail accounts, weblogs and wikis. Therefor I would have to deploy certificates. Since the administrators of my university were unable to create proper certificates I decided to create a CA on my own. So I started reading a bunch of tutorials about HTTPS and OpenSSL. None of these were really satisfying as they would only go for a quick fix. »Create a CA, create certificates, configure apache, don’t care about the details.« – That is what most of the tutorials were like. If I would go as far as creating my own CA for our faculty I wanted to make it as good as I possibly could. Therefor I started reading even more tutorials and howtos just to find out that almost everybody is doing it differently. There wasn’t the definitive guide I was hoping for. Then I got the Secure Networking with OpenSSL book from O’Reilly which had yet another approach. Even a friend of mine, who is earning tons of money deploying PKI for large corporations, couldn’t answer all my questions. In the end I came up with my own solution which is a mixture of the OpenSSL book and the expertise of my friend.

It goes like this:

First of all, if you really want to save you a lot of pain, create your own custom openssl.cnf. If it is setup properly you’ll save you a lot of typing and get a lot more consistency automatically. The book, in contrast to most tutorials, starts by creating a directory for all your certificates and keys.

> mkdir /usr/local/etc/ssl
> cd /usr/local/etc/ssl
> mkdir crl				#for cert revocation lists
> mkdir	certs				#this is where new certs go
> mkdir private				#this is where the key go
> touch index.txt			#file to keep track of your certs
> echo 01 > serial			#file to keep track of the serials

Thats gives you the basic structure. Of course you should set the proper permissions to prevent access from others. Your private CA key should be really private. Once obtained you can start all over again and worry about your security nightmares becoming true.

Now lets get to the openssl.cnf file. On FreeBSD edit vi /etc/ssl/openssl.cnf.
The default openssl.cnf is very long and not that easy to understand when you look at it for the first time. I won’t explain everything to you, instead this is a guide for people who want to create their own CA and are willing to read through the book, the man pages or the tutorials which I will also post at the end.

The most important part to understand the openssl.cnf is probably the [ foo ] syntax. It works like this:

default_ca = CA_default

In this case you’re saying the default_ca is defined beneath the secttion CA_default.
The section itself is defined beneath [ CA_default ] and it goes until the next [ section ] definition

# To use this configuration file with the "-extfile" option of the
# "openssl x509" utility, name here the section containing the
# X.509v3 extensions to use:
extensions              = certificate_extensions

####################################################################
[ ca ]
default_ca      = CA_default            # The default ca section

####################################################################

[ CA_default ]

dir             = /usr/local/etc/ssl    # Where everything is kept
certs           = $dir/certs            # Where the issued certs are kept
crl_dir         = $dir/crl              # Where the issued crl are kept
database        = $dir/index.txt        # database index file.
#unique_subject = no                    # Set to 'no' to allow creation of
                                        # several ctificates with same subject.
new_certs_dir   = $dir/certs            # default place for new certs.

certificate     = $dir/cacert.crt	# The CA certificate
serial          = $dir/serial           # The current serial number
crlnumber       = $dir/crlnumber        # the current crl number
                                        # must be commented out to leave a V1 CRL
crl             = $dir/crl.pem          # The current CRL
private_key     = $dir/private/cacert.key# The private key
RANDFILE        = $dir/private/.rand    # private random number file

x509_extensions = certificate_extensions# The extentions to add to the cert

default_days    = 720                   # how long to certify for
default_crl_days= 10                    # how long before next CRL
default_md      = sha1                  # which md to use.
preserve        = no                    # keep passed DN ordering

policy          = policy_match

# For the CA policy
[ policy_match ]
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = supplied
commonName              = supplied
emailAddress            = optional

This part defines the location auf the ssl directory and all the other files. It also defines the section for the x509 extensions. In my configuration they look like this:

[ certificate_extensions ]

# These extensions are added when 'ca' signs a request.

basicConstraints=CA:FALSE

# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

# Copy subject details
issuerAltName			= issuer:copy

keyUsage                        = digitalSignature,keyEncipherment

extendedKeyUsage                = serverAuth,clientAuth

crlDistributionPoints           = URI:http://yourdomain.com/crl

nsCaPolicyUrl                   = URI:http://yourdomain.com/policy

This is actually the part where my friend helped me out. Most of the quick fix tutorials leave out the x509 extensions which are crucial for a serious CA and certificates as they give the the potential clients further information about the key usage, the policy and the revocation lists. It doesn’t provide more security but more seriousness and it is a lot better than a certificate which has no real information at all (e.g. Some Organization, Some City, Some Stat).

You can view the rest of my openssl.conf by clicking on this link. Take a look at the x509 extensions in particular as some of them are not in the default config file.

After you set up your openssl.cnf its time to get started creating your CA.
Issue the following command. This will create a CA key/cert pair. Also note that the CA certificate belongs into ssl/cacert.crt. You can change this in you openssl.cnf though.

Step 1:

openssl req -new -x509 -keyout private/cakey.pem -out cacert.pem

Enter all the details you want to have in your certificates. Thats it, you have now a self signed CA. Now continue by creating a new key and a certificate signing request by tying:

Step 2:

openssl req -newkey rsa:1024 -keyout testkey.key -keyform PEM -out testreq.csr

Note that the bitlength of 1024 is recommended for HTTPS as many clients / browsers do not support higher values. I don’t know if this is still valid. If you tried out or know by fact that all current browsers support higher values, let me know! Since this certificate is for a browser and you want it to work with older browsers too you specify 1024 bit. Now you can sign this certificate signing request with your CA certificate.

Step 3:

openssl ca -in testreq.csr

You will now be promted with the certificate request information and the question whether to sign it. After confirming the request a new serial is written to the ssl/serial file and the hash of the new cert will be appended to index.txt. Your new cert is created in ssl/certs/.

Now you can continue creating new certificates under your new CA by repeating step 2 and 3.

To complete this post I’m going to list all the webpages I consulted for help and that had indeed useful information (I’m skipping the quickfix ones):

So in the end this seems like a quick fix tutorial as well. It is indeed but I think this one works really well and provides you with a proper openssl.cnf as well as some useful links. Again – read the book and manpages as you will probably discover some more details about PKI in general. I hope this post was any help for you.

7 thoughts on "Creating your own CA – The Miracles of OpenSSL"

  1. required says:

    The HTTPS and Apache Tutorial Link is broken.

  2. tester says:

    What do you think of using a Makefile to create various certs on FreeBSD? Such a thing should be in BASE in a nicely prepared /etc/ssl/ … copying this idea from the Linux distro Fedora which has /etc/pki/ and to create the various certs etc one needs for TLS/SSL enabled applications one does:

    cd /etc/pki/tls/certs
    make slapd.pem

    etc… check out /etc/pki/tls/certs/Makefile on a Fedora install or look here:

    http://cvs.fedora.redhat.com/viewvc/devel/openssl/Makefile.certificate?revision=1.4

  3. Jason Boxman says:

    I urge the usage of RSA 4096 in place of the weak 1024.

  4. Vivek says:

    This link was very helpful for a newbie liek me to start on OPENSSL. Helped me a lot. Thanks.

  5. Steffen says:

    Looks like the link to your full config file is broken.
    Nevertheless, many thanks for your tutorial!

  6. hey says:

    The link to your openssl.cnf is broken

Leave a Reply

Your email address will not be published. Required fields are marked *