Lunanbay OpenSSL HowTo

OpenSSL is a powerful tool for manipulating SSL certificates. This document may go some way to improving the general understanding of it.

In this document are the instructions for creating a Root CA which will sign an SSL Server CA which will sign SSL server certificates.

Introduction

An SSL certificate is, in essence, the public key from a standard PKI key-pair in a particular format. The fun and games with SSL certificates is that the particular format requires that some entity has signed your public key to verify its authenticity. In practice, the entity that signs your certificate had in turn their certificate signed by another (higher) authority. The ultimate authority has a self-signed certificate and is occasionally called a Root CA.

The certificate format is called x509 and an entity doing the signing is usually called a Certificate Authority (CA).

CAs are no different to anyone else other than they are generally organisations who stake their reputation on being honest. The idea is that they will only sign your certificate if they think you are who you claim to be. In turn, if a user sees your certificate, rather than trying to authenticate you directly, they can rely on the signature of the trusted CA. That means that the user need only keep a copy of the (Root) CAs' certificates and use those to verify the CA signature.

Of course, this means that if your application demands it you can have an entirely self-contained SSL trusting network and needn't spend any money with a `proper' CA.

In general, however, you would create a private key. You can generate a Certificate Signing Request (CSR) from the private key which you would offer up to the CA to have a signed certificate returned to you.

The signed certificate and the original private key are the two bits of information you need to offer to your application (most probably your web server) to allow you to be an SSL client or server.

Tree of Trust

As described above there is a tree of trust between the Root CA and your SSL certificate. There are many possible schemes for utilising such a tree but when creating one bear in mind the following:

Generating Keys

Assuming you have built and installed OpenSSL, you can generate some private keys thus:

openssl genrsa -out ssl-certificate.key 1024

If you're a bit nervous about the security of your key then you should add an extra flag for encryption, one of -des, -des3 or -idea. You will be prompted for a passphrase which you should not forget as it cannot be recovered.

This generates an unencrypted key in the file ssl-certificate.key. In particular:

% openssl genrsa -out ssl-certificate.key 1024 warning, not much extra random data, consider using the -rand option Generating RSA private key, 1024 bit long modulus ..........++++++ ......................++++++ e is 65537 (0x10001) %

The complaint about randomness is a bit tricky. We need some randomness to help seed the prime number generation and we can supply it either by pointing at a number of files or by putting some randomness into ~/.rnd. This file is specified in the openssl.cnf configuration file. Something like:

dd bs=512 count=2 if=/dev/random of=~/.rnd

on a UNIX box should do the trick. Remember to change it every now and again!

Generating A CSR

With (private) key in hand you can generate a CSR:

openssl req -new -key ssl-certificate.key -out ssl-certificate.csr

You should be prompted for something like:

% openssl req -new -key ssl-certificate.key -out ssl-certificate.csr Using configuration from /usr/local/openssl-0.9.6c/ssl/openssl.cnf 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]:GB State or Province Name (full name) [Some-State]:Oxfordshire Locality Name (eg, city) []:Henley-on-Thames Organization Name (eg, company) [Internet Widgits Pty Ltd]:Lunanbay Limited Organizational Unit Name (eg, section) []: Common Name (eg, YOUR name) []:www.lunanbay.com Email Address []:webmaster lunanbay.com Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: %

What you enter for any of the fields is up to you but for a standard webserver SSL certificate the most important value is the common name which must match exactly the hostname for the URL you want to use for your SSL certificate. Not knowing the machinations of the global CAs it would probably be best if you answered the questions about your location truthfully and put in a meaning full email address.

To check your CSR you can do the following:

openssl req -in ssl-certificate.csr -noout -text

which should give you something along the following lines:

% openssl req -in ssl-certificate.csr -noout -text
Using configuration from /usr/local/openssl-0.9.6c/ssl/openssl.cnf
Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: C=GB, ST=Oxfordshire, L=Henley-on-Thames, O=Lunanbay Limited, 
CN=www.lunanbay.com/Email=webmaster lunanbay.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:b1:d2:9f:2d:d3:d5:62:b6:bc:e0:5b:85:b9:0f:
                    d2:00:df:15:fd:5c:48:ae:f3:28:03:85:4a:89:31:
                    99:a6:a1:ee:b5:4b:4c:ac:d9:7e:5e:c3:20:fd:f4:
                    83:b3:23:17:6d:a0:67:7b:9d:91:78:7c:fd:ac:a7:
                    ee:f0:ae:63:9b:98:2b:3e:af:85:44:8f:d6:7f:00:
                    80:58:a1:5f:6a:96:bd:79:b0:9a:1b:95:e3:d7:d0:
                    50:79:0b:1c:d5:4d:7c:82:94:13:f2:62:19:c0:06:
                    b9:b2:85:fc:55:8c:a0:25:0c:29:b5:91:e8:b9:d4:
                    6d:d4:99:cd:8a:c4:1c:7e:53
                Exponent: 65537 (0x10001)
        Attributes:
            a0:00
    Signature Algorithm: md5WithRSAEncryption
        68:da:de:7b:c9:3f:8b:38:2d:df:62:50:00:e0:cf:7f:5f:13:
        e6:1d:1b:46:eb:58:be:71:e0:61:7c:70:98:97:18:c0:16:32:
        eb:94:07:d5:2c:4c:ab:81:42:24:8f:07:48:43:1e:8b:88:9d:
        88:65:b7:df:c2:b8:b6:82:e4:71:cb:87:24:6e:de:f3:a9:03:
        5c:c2:2d:4d:3e:d7:39:3a:3f:09:9e:a9:b2:c5:67:4c:c1:08:
        9a:bf:c9:2a:27:d9:7e:9b:b2:0a:34:a7:4f:c5:a4:0e:d7:06:
        09:f4:f6:6f:69:bc:85:e4:6f:2e:fc:3f:4b:0f:73:cf:3c:12:
        ee:a7
%

Your output will be different as you have (hopefully!) different random data but you should see the Subject line be the same (assuming you used the same values): Subject: C=GB, ST=Oxfordshire, L=Henley-on-Thames, O=Lunanbay Limited, CN=www.lunanbay.com/Email=webmaster lunanbay.com

Generating A Self-Signed Certificate

You can generate your own self-signed certificate from your private key:

openssl req -x509 -new -key ssl-certificate.key -out ssl-certificate.crt

which will prompt you for the same information as before, this time you have a self-signed certificate in ssl-certificate.crt which you can check with:

openssl x509 -in ssl-certificate.crt -noout -text

for example:

% openssl x509 -in ssl-certificate.crt -noout -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 0 (0x0)
        Signature Algorithm: md5WithRSAEncryption
        Issuer: C=GB, ST=Oxfordshire, L=Henley-on-Thames, O=Lunanbay Limited, 
CN=www.lunanbay.com/Email=webmaster lunanbay.com
        Validity
            Not Before: Mar  1 23:21:53 2002 GMT
            Not After : Mar 31 23:21:53 2002 GMT
        Subject: C=GB, ST=Oxfordshire, L=Henley-on-Thames, O=Lunanbay Limited, 
CN=www.lunanbay.com/Email=webmaster lunanbay.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:b1:d2:9f:2d:d3:d5:62:b6:bc:e0:5b:85:b9:0f:
                    d2:00:df:15:fd:5c:48:ae:f3:28:03:85:4a:89:31:
                    99:a6:a1:ee:b5:4b:4c:ac:d9:7e:5e:c3:20:fd:f4:
                    83:b3:23:17:6d:a0:67:7b:9d:91:78:7c:fd:ac:a7:
                    ee:f0:ae:63:9b:98:2b:3e:af:85:44:8f:d6:7f:00:
                    80:58:a1:5f:6a:96:bd:79:b0:9a:1b:95:e3:d7:d0:
                    50:79:0b:1c:d5:4d:7c:82:94:13:f2:62:19:c0:06:
                    b9:b2:85:fc:55:8c:a0:25:0c:29:b5:91:e8:b9:d4:
                    6d:d4:99:cd:8a:c4:1c:7e:53
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                8D:DA:49:87:07:7F:B5:11:1C:E8:31:CE:3F:4E:CD:F7:79:99:74:F9
            X509v3 Authority Key Identifier:
                keyid:8D:DA:49:87:07:7F:B5:11:1C:E8:31:CE:3F:4E:CD:F7:79:99:74:F9
                DirName:/C=GB/ST=Oxfordshire/L=Henley-on-Thames/O=Lunanbay 
Limited/CN=www.lunanbay.com/Email=webmaster lunanbay.com
                serial:00

            X509v3 Basic Constraints:
                CA:TRUE
    Signature Algorithm: md5WithRSAEncryption
        ad:f4:75:cc:3e:3e:4b:e2:49:57:01:79:da:fe:79:d0:c4:71:
        db:e6:d3:e5:a9:09:65:a7:de:49:d2:36:64:3b:9c:72:bb:15:
        23:0d:16:22:a8:9b:47:f1:28:20:1c:8f:29:c0:89:1f:5a:e4:
        77:2e:3e:0b:a3:fc:d9:f5:25:04:59:ee:e7:a6:89:7b:16:e9:
        9b:99:60:cb:f6:93:67:51:6e:9a:6e:47:95:3b:60:f0:ac:f3:
        3c:6d:21:1e:2b:1f:cc:4b:2b:53:da:1e:52:9a:98:fb:1f:ee:
        e0:de:69:df:9f:83:59:21:8c:f9:41:af:93:66:67:84:a5:0a:
        ce:63
%

Note that here the Issuer and the Subject are the same entity. When someone else signs your certificate they will appear as the Issuer.

Your self-signed certificate is a fully fledged CA and SSL server certificate (even if your browser doesn't automatically trust it). You can check this with:

openssl x509 -in ssl-certificate.crt -noout -purpose

which should give output something like:

% openssl x509 -in ssl-certificate.crt -noout -purpose Certificate purposes: SSL client : Yes SSL client CA : Yes SSL server : Yes SSL server CA : Yes Netscape SSL server : Yes Netscape SSL server CA : Yes S/MIME signing : Yes S/MIME signing CA : Yes S/MIME encryption : Yes S/MIME encryption CA : Yes CRL signing : Yes CRL signing CA : Yes Any Purpose : Yes Any Purpose CA : Yes %

Note the lines starting SSL server. Rather unfortunately, a self-signed certificate can do what it wants so it's a bit hard to tell that you've achieved something...

If you're feeling particularly keen you can generate the (private) key at the same time:

openssl req -x509 -newkey rsa:1024 -keyout server-key.pem -out server-req.pem

Note that you'll be forcibly asked for a pass phrase for your key.

The OpenSSL Configuration File

This is a black art if ever there were one.

The default configuration file distributed with OpenSSL 0.9.6c looks like this.

Note the reference to $ENV::HOME/.rnd mentioned previously.

Creating a Root CA

This is where things get a bit more interesting as we start playing with the bits inside the configuration file. However, for a Root CA, this is no different to generating a self-signed certificate.

The default configuration file for OpenSSL is quite hard to follow, however you can reduce it down to something more palatable and in this case attuned for a Root CA:

[ req ] prompt = no distinguished_name = req_distinguished_name x509_extensions = v3_ca [ req_distinguished_name ] C = GB ST = Oxfordshire L = Henley-on-Thames O = Lunanbay Limited CN = Lunanbay Limited Root CA emailAddress = webmaster lunanbay.com [ v3_ca ] subjectKeyIdentifier=hash authorityKeyIdentifier=keyid:always,issuer:always #basicConstraints = critical,CA:true basicConstraints = CA:true

The req sub-command in OpenSSL will look for the req section in the configuration file or fallback to the default section (the first, un-named, section).

Notable parts are:

To create the Root CA we use the all-in-one request and certificate form that we used to create a self-signed certificate:

openssl genrsa -out root-ca.key openssl req -new -x509 -key root-ca.key -out root-ca.crt -config root-ca.cnf

Where root-ca.cnf is a file containing the above configuration commands

Finally, text the certificate to see what we've got:

% openssl x509 -noout -in root-ca.crt -text -purpose
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 0 (0x0)
        Signature Algorithm: md5WithRSAEncryption
        Issuer: C=GB, ST=Oxfordshire, L=Henley-on-Thames, O=Lunanbay Limited, 
CN=Lunanbay Limited Root CA/Email=webmaster lunanbay.com
        Validity
            Not Before: Mar  4 20:58:24 2002 GMT
            Not After : Apr  3 20:58:24 2002 GMT
        Subject: C=GB, ST=Oxfordshire, L=Henley-on-Thames, O=Lunanbay Limited, 
CN=Lunanbay Limited Root CA/Email=webmaster lunanbay.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (512 bit)
                Modulus (512 bit):
                    [...]
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                [...]
            X509v3 Authority Key Identifier: 
                keyid:[...]
                DirName:/C=GB/ST=Oxfordshire/L=Henley-on-Thames/O=Lunanbay Limited/
CN=Lunanbay Limited Root CA/Email=webmaster lunanbay.com
                serial:00

            X509v3 Basic Constraints: 
                CA:TRUE
    Signature Algorithm: md5WithRSAEncryption
        [...]
Certificate purposes:
SSL client : Yes
SSL client CA : Yes
SSL server : Yes
SSL server CA : Yes
Netscape SSL server : Yes
Netscape SSL server CA : Yes
S/MIME signing : Yes
S/MIME signing CA : Yes
S/MIME encryption : Yes
S/MIME encryption CA : Yes
CRL signing : Yes
CRL signing CA : Yes
Any Purpose : Yes
Any Purpose CA : Yes

Note that the Issuer and the Subject are the same and that the certificate can be used for any purpose.

Creating an SSL Server CA

An SSL Server CA will be similar to the above only we want to do two things:

  1. restrict it to just being an SSL Server CA
  2. sign it with the Root CA

In fact both actions are performed at the same time.

The configuration for the SSL Server CA is virtually identical bar changing the commonName (or CN) attribute to something more appropriate, say, Lunanbay Limited SSL Server CA in this case.

openssl genrsa -out ssl-server-ca.key openssl req -new -key ssl-server-ca.key -out ssl-server-ca.req -config ssl-server-ca.cfg

Note that we are only creating a Certificate Request so we've dropped the -x509 argument and made the output file extension .req (outfile file extensions have no meaning for OpenSSL but it does help keep track of what's going on).

Next we need to sign the certificate and set its attributes.

First we need to define the attributes we're going to give the SSL Server CA.

Note that a bug in OpenSSL means that the extensions put into the SSL Server CA's request are lost on transfer to a certificate so we have to redefine them.

Defining these attributes in a named section allows us to use this file for other signing purposes:

[ ssl_server_ca ] subjectKeyIdentifier=hash authorityKeyIdentifier=keyid:always,issuer:always #basicConstraints = critical,CA:true basicConstraints = CA:true keyUsage = keyCertSign

We repeat the basicConstraints attribute to make the certificate a CA and add the keyUsage attribute where the value keyCertSign reduces the scope of the CA to just being an SSL Server CA.

However, before we do we sign anything we need to setup a serial number file for the Root CA so that every certificate it signs can have a unique serial number. The serial number file is a simple text file with an ASCII number in it.

echo 00 > root-ca.srl

The next command will take the SSL Server CA's signing request and sign it with the Root CA's private key:

openssl x509 -req -in ssl-server-ca.req -out ssl-server-ca.crt \ -extfile root-ca-sign.cfg -extensions ssl_server_ca \ -CA root-ca.crt -CAkey root-ca.key -CAserial root-ca.srl

The -extfile openssl.cnf-root-ca-sign -extensions ssl_server_ca arguments are taking the attributes for the certificate from the ssl_server_ca section of the file root-ca-sign.cfg (our example above).

Check the certificate:

% openssl x509 -noout -in ssl-server-ca.crt -text -purpose
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 0 (0x0)
        Signature Algorithm: md5WithRSAEncryption
        Issuer: C=GB, ST=Oxfordshire, L=Henley-on-Thames, O=Lunanbay Limited, 
CN=Lunanbay Limited Root CA/Email=webmaster lunanbay.com
        Validity
            Not Before: Mar  4 20:58:25 2002 GMT
            Not After : Apr  3 20:58:25 2002 GMT
        Subject: C=GB, ST=Oxfordshire, L=Henley-on-Thames, O=Lunanbay Limited, 
CN=Lunanbay Limited SSL Server CA/Email=webmaster lunanbay.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (512 bit)
                Modulus (512 bit):
                    [...]
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                [...]
            X509v3 Authority Key Identifier: 
                keyid:[...]
                DirName:/C=GB/ST=Oxfordshire/L=Henley-on-Thames/O=Lunanbay Limited/
CN=Lunanbay Limited Root CA/Email=webmaster lunanbay.com
                serial:00

            X509v3 Basic Constraints: 
                CA:TRUE
            X509v3 Key Usage: 
                Certificate Sign
    Signature Algorithm: md5WithRSAEncryption
        [...]
Certificate purposes:
SSL client : No
SSL client CA : Yes
SSL server : No
SSL server CA : Yes
Netscape SSL server : No
Netscape SSL server CA : Yes
S/MIME signing : No
S/MIME signing CA : Yes
S/MIME encryption : No
S/MIME encryption CA : Yes
CRL signing : No
CRL signing CA : Yes
Any Purpose : Yes
Any Purpose CA : Yes

Note here that the Issuer is the Root CA and that the certificate has had its full CA purpose restricted to, amongst others, an SSL Server CA.

Creating an SSL Server Certificate

This is the final part and is useful if you want to create a certificate request (CSR) to be signed by a commercial CA.

As usual create a request. In this case the commonName (or CN) attribute should reflect the hostname of the URL you want to use the certificate for. If it does not match then your users will get a warning about the site name not matching the certificate.

Note also the restriction on web server imposed by the SSL protocol that each (virtual) web site using an SSL certificate must have its own unique IP address.

Using the following configuration information:

[ req ] prompt = no distinguished_name = req_distinguished_name [ req_distinguished_name ] C = GB ST = Oxfordshire L = Henley-on-Thames O = Lunanbay Limited CN = www.lunanbay.com emailAddress = webmaster lunanbay.com

Create the request in the usual way:

openssl genrsa -out ssl-certificate.key openssl req -new -key ssl-certificate.key -out ssl-certificate.req -config ssl-certificate.cfg

At this point you could send your request (CSR) off to a commercial CA to be signed or you could sign it with your own SSL Server CA:

openssl x509 -req -in ssl-certificate.req -out ssl-certificate.crt \ -CA ssl-server-ca.crt -CAkey ssl-server-ca.key -CAserial ssl-server-ca.srl

Note that we don't need to add any extensions (and don't forget to create the SSL Server CA's serial file).

Looking at the certificate reveals the following:

% openssl x509 -noout -in ssl-certificate.crt -text -purpose
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number: 0 (0x0)
        Signature Algorithm: md5WithRSAEncryption
        Issuer: C=GB, ST=Oxfordshire, L=Henley-on-Thames, O=Lunanbay Limited, 
CN=Lunanbay Limited SSL Server CA/Email=webmaster lunanbay.com
        Validity
            Not Before: Mar  4 20:58:25 2002 GMT
            Not After : Apr  3 20:58:25 2002 GMT
        Subject: C=GB, ST=Oxfordshire, L=Henley-on-Thames, O=Lunanbay Limited, 
CN=www.lunanbay.com/Email=webmaster lunanbay.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (512 bit)
                Modulus (512 bit):
                    [...]
                Exponent: 65537 (0x10001)
    Signature Algorithm: md5WithRSAEncryption
        [...]
Certificate purposes:
SSL client : Yes
SSL client CA : No
SSL server : Yes
SSL server CA : No
Netscape SSL server : Yes
Netscape SSL server CA : No
S/MIME signing : Yes
S/MIME signing CA : No
S/MIME encryption : Yes
S/MIME encryption CA : No
CRL signing : Yes
CRL signing CA : No
Any Purpose : Yes
Any Purpose CA : Yes

Note that the Issuer is the SSL Server CA and that the certificate's purpose is limited to just that of an SSL Server or SSL Client (amongst others) ie. it cannot be used as a CA.

Were you to create another SSL Server Certificate using the SSL Server CA the serial number should increment to 1 (one).

Verifying the Tree of Trust

You'll probably want to make sure that everything is in order with your Tree of Trust for which you could laboriously output the certificates in text form checking that issuers and subject match up. OpenSSL saves you the effort with a couple of neat commands.

c_rehash . openssl verify -CApath . *.pem

c_rehash takes a directory name as an argument and generates special symlinks to each of the *.pem files it finds in those directories.

Using the Certificates

Finally, you'll want to use your certificates. You'll want to do two things:

  1. install your SSL Server Certificate within your web server -- this is left as an exercise for the reader
  2. trust it

If you don't trust it then your browser should prompt you with a warning that the certificate being presented has an unrecognised issuer.