Building a Security Infrastructure

December 9, 2003

Rich Salz

In my previous column I offered a rationale for XKMS as an important web service, and I looked at reducing the problem of implementing such a service to a reasonable size. This time we'll build the infrastructure necessary to develop and deploy an XKMS registration server that can issue certificates and which is intended for use within an enterprise.

Our server will need an SSL certificate and private key. Since it will be signing certificates for others, it will also need a CA certificate and private key; that is, a certificate that says it is allowed to create certificates. We could follow the standard process and just buy our SSL certificate from the reigning monopoly, or we could create a quick "snake-oil" certificate for demonstration purposes. It turns out that it only takes a modest effort to do something real, however; doing that will be the focus this month.

Public Key Infrastructure and Hierarchy

In this exercise we're going to build an enterprise-quality public key infrastructure. We'll then use one of the certificates to create a server that uses SSL. Our hierarchy will look like this:



      +-- Level 1 CA


             +-- SSL Certificate(s)


             +-- XKMS Server CA

The root will sign the Level 1 CA and then be taken offline. Anyone who wants to validate any identity within our organization only needs to have our root certificate. If the enterprise merges or joins a commercial PKI (such as Identrus), then we only need to get the root certificate signed by our new "super root".

We'll only create one Level 1 (L1) CA, although for a large organization we might want to create one for each division or geographic boundary. The L1 CA's are used to issue certificates to our application servers and to the SSL certificates which they use. If the applications are being used outside the enterprise, then we might want to have a commercial SSL CA sign those SSL certs.

Each of the three CA's follow the same directory structure:


      +-- .rand

      +-- serial

      +-- index.txt

      +-- certreq.pem

      +-- cert.pem

      +-- key.pem

      +-- certs

            +-- 01.pem, 02.pem, ...

      +-- crl.pem

      +-- crls

            +-- old CRL's ...

The .rand, serial, and index.txt files are used by OpenSSL to maintain state when generating keys and issue certificates; each cert will be copied to the certs directory, with a filename generated from the serial number. The actual cert is in cert.pem, and the private key is in key.pem; we'll discuss the risks of that later. In order to make it easy to get our CA's recertified, we'll keep a copy of the original request in certreq.pem.

For naming, we'll use the Country, organizationName, organizationUnit, and commonName components (or, rather, "C", "O", "OU", and "CN"). If there's an emailAddress, we'll move it to the subjectAltName extension, and not put it in our DN. We'll require that everything have the same C and O components. We'll also require that the certificates our XKMS Server generates must have an emailAddress.

The OpenSSL configuration file for this hierarchy can be found in xkms.conf. A script to create the directory tree can be found in setup-pki-part0. The script can be run with a single argument, --restart, to remove an old configuration. It will also ask for the country and organization names, and it will build a certificate request template used by the other scripts. After running setup-pki-part0, you can edit the req.conf file it generates.

If you want to build the service in a directory other than /opt/xkms, you'll have to edit both files. Both that directory and the /opt/xkms/openssl directory must exist (with appropriate permissions) before doing anything else. Copy both files to the /opt/xkms/openssl directory.

Creating the PKI

The next step is to create the root CA keypair and use the key to create a self-signed certificate. Following that, we'll create a Level 1 CA and have the root sign the L1 certificate. This is done with the setup-pki-part1 script.

Most items are protected by one safeguard. For example, a private key is protected by a password. From the security viewpoint, if we can double that, we have accomplished a great deal. I encourage you to actually try the steps described below, to get a feel for good security practice.

To create the first two CA's, you'll need at least three volunteers and the administrator of the Level 1 CA. Two volunteers will be used to prevent the root private key from being compromised, and the third watches the behavior of the first two. We'll protect the root key with a password; one volunteer will get the password, and the other will get the key. (In my organization, the password was kept in a sealed envelope with other confidential Personnel files, and the key was written to a CD which was sent to our lawyer. We then scrubbed the disk.)

In addition to protecting the company, this type of two-part safeguard also protects you. No matter what happens, it's impossible for you to falsely issue certificates. You don't have the key, you don't have the password, and the third volunteer watched to make sure that the other two put their items into safe escrow.

Running the ``part 1'' script, you see output like the following:




    Generating a 2048 bit RSA private key



    writing new private key to '/opt/xkms/openssl/root-ca/key.pem'

    Enter PEM pass phrase:

Have the first volunteer type a password, they will then have to verify it. They need to write it down on a piece of paper, fold it, and hold onto it. Next you should enter the fields for the root CA name:

    Country Code [US]:

    Organization Name [XKMS Service]:

    Organizational Unit (eg, department) []:

    Common Name (i.e., name of person or server) []:

    Email Address []:

Now the root will sign its own certificate. Have the first volunteer enter the password again.

Now we generate the Level 1 CA. Whoever is in charge of that should enter the password. You should then enter the name:

    Country Code [US]:

    Organization Name [XKMS Service]:

    Organizational Unit (eg, department) []:          

    Common Name (i.e., name of person or server) []:Level 1 CA

    Email Address []

Now the first volunteer will have to enter the root password, look at the certificate, and decide to sign and commit it. At this point, we no longer need the root. Give the key, /opt/xkms/openssl/root-ca/key.pem, to the second volunteer. Have the third volunteer walk the first one to the storage place, and watch them seal the envelope and put the password away. The third volunteer then repeats the process with the second volunteer and the private key.

More from Rich Salz

SOA Made Real

SOA Made Simple

The xml:id Conundrum

Freeze the Core

WSDL 2: Just Say No

You can see why this is called a key signing ceremony. In order to sign a new certificate, it's necessary for each volunteer to bring their piece to the signing machine, watch the operation, and take their parts away. This shows one of the paradoxes about PKI: the more valuable the certificates, the harder it is to sign things. The paradox is that if the CA has to issue a revocation list (CRL), it's a lot of work and long time can pass. XKMS (among other mechanisms) address this.

We'll skip the details of running setup-pki-part2. This ceremony is much less inolved: it requires only those running the Level 1 CA and the XKMS Server to be present. Just remember that the common name should be the name of the server host for the SSL and XKMS certificates. implements a small Python server that listens on local port 9999 using the SSL certificate we just created. Use a browser to connect to a URL like https://localhost:9999/foo. You can then walk-through the security and certificate settings, seeing references to the PKI you just created.

Next month we'll begin implementing the web service.