August 24, 2004

Securing Web services: Be your own CA

Author: Jeffrey L. Vagle

In this article we continue our discussion of some of the foundations of public key infrastructure (PKI) that we began in an earlier article, where we discussed the role of keys, certificates, and trust. While discussing the importance of distributed (or transitive) trust in PKI design, we outlined the job of the certificate authority (CA) in PKI, giving the general idea of its role in certificate issuance and management. Here, we'll explore the how and when one might wish to establish one's own CA when incorporating a PKI into an enterprise design.

We'll expand the discussion of CA implementation and use by giving practical examples using two widely available tools, OpenSSL and keytool.
Bear in mind that many of the topics that we'll touch on require a deeper background than is practical to present within the scope if this article. Where applicable, we'll provide pointers to useful references.

Why do I need a CA?

As discussed in our earlier article, the CA is a crucial component of any PKI, as it provides public-key certificate issuance, management, and revocation services to PKI users, thus enabling distributed trust relationships. In general, the CA is usually not a singular entity, but a hierarchical collection of authorities, with a root CA at the top of the structure acting as the most trusted (and most authoritative) entity in the organization (see Figure 1).

Figure 1: CA Hierarchy

In this example, Server A -- the root CA -- is the most trusted
authority, and therefore should be the most protected. All trust
within this system hinges on the integrity of the private key and
public key certificate belonging to Server A. To spread the load
a bit in our example, Server A has granted subordinate CA status to
Servers B, C, and D by signing their respective certificates, enabling
users to have their public-key certificates issued by one of the
subordinate CAs, rather than flooding the root CA with certificate
management duties (see Figure 2).

Figure 2: Use of hierarchical CAs

Distributed trust is still maintained in this hierarchical organization
through explicit trust of the root CA. Following our example,
Server A (our root CA) signed Server B's (a subordinate CA) public key
certificate. In turn, Server B signed User 1's certificate (see
Figure 3).

Figure 3: Certificate Chains

Thus, using transitive trust, since Server A is trusted by everyone
in our system, all certificates signed by Server A are also
trusted. Since Server B is a subordinate CA, all certificates
signed by it (e.g., User 1's) are trusted by all who trust Server B. The
trust path is thus complete, since trust in PKIs works transitively:
Server A is trusted; Server A trusts Server B, so Server B is trusted;
Server B trusts User 1, so User 1 is trusted. We can accomplish
all of this through the explicit trust of one entity, the root CA. You
can see how this hierarchical distributed trust approach is necessary for
all but the most trivial of organizations requiring PKI.

When do I need a CA?

Let's say you wanted to set up a private enterprise system to be used
strictly within your organization. If your organization is made
up of only a few users and servers acting as peers, then the need for a
CA (or CA hierarchy) is probably not a strong one. In this simple
case, users could simply exchange self-signed public-key
certificates with one another (including, of course the servers)
without too much trouble. Since the group is very small,
certificate management, including revocation, could take place on an
ad-hoc basis.

If, however, your organization grows much beyond a handful of entities,
the infrastructure required by efficient and effective distributed
trust implies the need for CAs. Of course there are many
commercial organizations (Verisign, Thawte, et al.) that provide, for a
fee, CA services to end users, obviating the need for organizations to
maintain their own CA infrastructure. However, this expense may
not be necessary for small organizations, especially those
who do not have a need for distributed trust beyond their organization

In these cases, it is certainly possible to build and maintain your own
private CA infrastructure. There are many tools and applications
out there for accomplishing this, and depending on your needs and
budget, odds are you'll have many to choose from. However, in
order to illustrate some of the principles outlined above, our examples
will be using two readily accessible applications: OpenSSL and the Java
keytool. There's nothing lightweight about these tools
-- it's just as possible to build a strong CA infrastructure with these
apps as it is with other, more expensive, options.

Setting up a certificate authority

We will use OpenSSL's command-line tool to set up our CA by creating a
private key and self-signed certificate that will be used to administer
certificates within our own little PKI universe. Bearing in mind
that we will be creating the instruments of what is supposed to be the
trusted authority in our system, we first need to establish a private
repository for these files. You can do so by creating a directory
somewhere, and limiting permissions on the directory to prevent
unwanted snooping:

% mkdir My_New_CA
% chmod 0700 My_New_CA
% cd My_New_CA

The default OpenSSL configuration expects certain files, such as the CA
private key and CA certificate, to be in predefined locations for some
of its operations. Stick with the default file structure,
which can be set up as follows (these commands assume that you are in
the My_New_CA directory):

% mkdir demoCA
% mkdir demoCA/private

You can change these defaults, along with other configuration
parameters, by modifying the OpenSSL configuration file, usually
located in /usr/local/ssl/lib/openssl.conf.

Now create an RSA keypair for the CA using OpenSSL:

% openssl genrsa -des3 -out demoCA/private/CA_key.pem 2048

This command generates a private key
with length 2,048 bits. By using the -des3 switch,
we specified that we wish to protect our private key with a password,
which is highly recommended considering the role this private key will
play in our overall PKI scheme. You can also use either the -des
or -idea switch, depending on your algorithm preference
for encrypting your private key.

If you wish to create a DSA keypair, use the following OpenSSL commands:

% openssl dsaparam -out dsa_params 2048
% openssl gendsa -des3 -out demoCA/private/CA_key.pem dsa_params

The first command sets up the DSA parameter file using a 2,048-bit-long prime. The second command uses the subsequent parameter file to generate a DSA private key, protected with a DES3 password.

This private key file should be considered highly sensitive, and should
protected as such -- keep this file in a safe place, back it up,
but never let anyone else see this file. If your CA's private key
is compromised, then your entire notion of trust should be considered
suspect. Cleaning up from a mess like this involves
generating a new CA key and public-key certificate, along with the
re-signing of all user certificates -- a scenario you want to avoid.

Next, create, from the private key, the public-key
certificate for your CA, a key (no pun intended) component of the
PKI. To generate this self-signed certificate, use the
following command:

% openssl req -new -key demoCA/private/CA_key.pem -x509 -days 365 -out demoCA/CA_cert.cer

This creates a public-key certificate from the private key you generated earlier. The -x509 switch indicates that we wish to generate this X.509 certificate, and the -days switch gives our generated certificate an expiration date. Since we are generating this public-key certificate for the first time, the command asks a number of questions, intended to populate the necessary X.500 information:

% openssl req -new -key demoCA/private/CA_key.pem -x509 -days 365 -out demoCA/CA_cert.cer
Enter pass phrase for demoCA/private/CA_key.pem:
You are about to be asked to enter information that will be

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]:US
State or Province Name (full name) [Some-State]:MA
Locality Name (eg, city) []:Boston
Organization Name (eg, company) [Internet Widgits Pty Ltd]:My

Organizational Unit Name (eg, section) []:PKI
Common Name (eg, YOUR name) []:My CA
Email Address []:

Of course, the information particular to your organization will differ
from this example. Again I emphasize that the
public-key certificate should be the only file from the two that you
just generated that you should share with anyone.

We now have the necessary instruments to begin our CA duties: issuing,
revoking, and managing certificates.

Certificate signing and issuance

The job of the CA in a PKI is to enable distributed trust. You
can do this with your new CA by issuing and revoking user certificates
within your system. To illustrate how this is done, start
with the setup of an SSL-enabled Tomcat servlet container. As
part of the Tomcat SSL initial configuration, you need to generate a new
keypair for the server. You can do this using OpenSSL using the following commands.

First, you need to generate an RSA private key for the new server:

% openssl genrsa -des3 -out tomcat.pem 2048

Just as in the CA example above, this command generates a new RSA
private key protected by a DES3 password. Also, just as before,
you can generate DSA keys instead, if you wish.

Since you want your CA to issue the public-key certificate, enabling
distributed trust by other members of the PKI, you now need to generate
a certificate signing request (CSR) from your private key. Using
OpenSSL, you can do so with the following command:

% openssl req -new -key tomcat.pem -out tomcat_request.csr

It is this CSR file that you can now submit to the CA for public-key
certificate issuance.

You can, if you wish, generate a private key and CSR using the Java
keytool application. To generate an RSA keypair using
keytool, use the following command:

% keytool -genkey -v -alias tomcat -keyalg RSA -keysize 2048 -keystore my_keystore.jks

This command generates an RSA keypair of size 2,048 bits, following the OpenSSL example above. However, keytool will, at the same time, also generate a Java keystore (JKS) format keystore file in which the keypair, along with a self-signed public-key certificate, is placed, giving it a shorter alias of "tomcat." Since keytool creates the X.509 certificate in this step, it asks the user for the necessary X.500 information:

% keytool -genkey
-v -alias tomcat -keyalg RSA -keysize 2048 -keystore my_keystore.jks
Enter keystore password: password
What is your first and last name?
[Unknown]: My Tomcat Servlet Container
What is the name of your organizational unit?
[Unknown]: PKI
What is the name of your organization?
[Unknown]: My Organization
What is the name of your City or Locality?
[Unknown]: Boston
What is the name of your State or Province?
[Unknown]: MA
What is the two-letter country code for this unit?
[Unknown]: US
Is CN=My Tomcat Servlet Container, OU=PKI, O=My Organization, L=Boston,
ST=MA, C=US correct?
[no]: yes

Generating 2,048 bit RSA key pair and self-signed certificate (MD5WithRSA)
for: CN=My Tomcat Servlet Container, OU=PKI, O=My Organization, L=Boston, ST=MA, C=US
Enter key password for <tomcat>
(RETURN if same as keystore password):
[Saving my_keystore.jks]

Your information will vary, of course, and it's probably a bad idea to use (as I did) "password" as your password. You can also generate DSA keypairs using keytool; see the Java keytool
for more information.

To generate the CSR from our new keypair using keytool, you can use the
following command:

% keytool -certreq -v -alias
tomcat -keystore my_keystore.jks -file tomcat_request.csr

You can now submit the resulting file to the CA for certificate

You can, upon receipt of the CSR file, go
through whatever steps you deem necessary to verify the entity
requesting the certificate. Assuming that all goes well in the
vetting process, you are ready to generate a public-key certificate.

Using the private key/public-key certificate you generated earlier for
the CA, you can sign the certificate contained in the CSR using OpenSSL:

% openssl x509 -req -days 365 -in tomcat_request.csr -CA demoCA/CA_cert.cer -CAkey
demoCA/private/CA_key.pem -CAcreateserial -out tomcat.cer

This command issues a new certificate, signed by your CA, with a
validity period of one year. The use of the -CAcreateserial
switch enables the unique assignment of serial numbers to our issued
certificates. Since this is the first certificate issued by your
CA, a new file is created (demoCA/ containing
the number "02," which is the next serial number to be used when the
next certificate is issued (serial number "01" was used by the first
certificate). Thus, when issuing subsequent certificates, you
would use the following command:

% openssl x509 -req -days 365 -in new_request.csr -CA demoCA/CA_cert.cer -CAkey demoCA/private/CA_key.pem -CAserial demoDA/ -out new_certificate.cer

Once your CA has issued the certificate, you can send it back to the
requester for use. It's also important to keep a copy of the
certificate around, just in case you need to revoke it later.

Certificate revocation

There may be occasions when, due to a user's compromised private key or
a change in an entity's status within the PKI, it is necessary for a CA
to revoke a previously issued certificate before its original
expiration date. The results of certificate revocation go in a
publicly available certificate revocation list (CRL), which users
should check on a regular basis to verify certificate validity.

When you need to revoke a certificate, begin by creating a CRL for your CA using OpenSSL.
First create an empty index file in the demoCA directory:

% touch demoCA/index.txt

Now put the CRL into a special format, signing it with your
CA private key at the same time:

% openssl ca -gencrl -crldays 90 -keyfile demoCA/private/CA_key.pem -cert demoCA/CA_cert.cer -out demoCA/my_crl.pem

This command creates the initial (empty) CRL for your CA, valid for 90
days. Once this CRL expires, you can simply create a new one using
the same command as above.

Now that you have your CRL set up properly, you can revoke
certificates. We'll illustrate this concept by revoking the
certificate you just created above, using the following OpenSSL command:

% openssl ca -revoke tomcat.cer
-keyfile demoCA/private/CA_key.pem -cert demoCA/CA_cert.cer

This command updates your local database of revoked certificates, which
is just this one at this point. You now need to publish this
information via your CRL, using the same command as before:

% openssl ca -gencrl -crldays 90 -keyfile demoCA/private/CA_key.pem -cert demoCA/CA_cert.cer -out demoCA/my_crl.pem

You can view the list of revoked certificates in a CRL using the
following command:

% openssl crl -in my_crl.pem
-text -noout

Certificate Revocation List (CRL):
Version 1 (0x0)
Signature Algorithm:

/C=US/ST=MA/L=Boston/O=My Organization/OU=PKI/CN=My CA

Last Update: Aug
2 22:23:14 2004 GMT

Next Update: Sep
1 22:23:14 2004 GMT

Revoked Certificates:
Serial Number: 01
Revocation Date:
Aug 2 22:21:03 2004 GMT

Signature Algorithm: md5WithRSAEncryption

The CA can now publish this CRL file for your PKI users. CRL usage
configuration will vary depending on your applications -- see the
respective documentation for more information.


  • Security
Click Here!