Chapter 3. Public Key Infrastructure (PKI)

In Chapter 1, we described a scenario known as a man-in-the-middle attack, in which an attacker could intercept and even manipulate communications secured with public key cryptography. The attack is possible because public key cryptography provides no means of establishing trust when used on its own. Public Key Infrastructure (PKI) provides the means to establish trust by binding public keys and identities, thus giving reasonable assurance that we’re communicating securely with who we think we are.

Using public key cryptography, we can be sure that only the encrypted data can be decrypted with the corresponding private key. If we combine this with the use of a message digest algorithm to compute a signature, we can be sure that the encrypted data has not been tampered with. What’s missing is some means of ensuring that the party we’re communicating with is actually who they say they are. In other words, trust has not been established. This is where PKI fits in.

In the real world, we often have no way of knowing firsthand who a public key belongs to, and that’s a big problem. Unfortunately, there is no sure-fire way to know that we’re communicating with who we think we are. The best we can do is extend our trust to a third party to certify that a public key belongs to the party that is claiming ownership of it.

Our intention in this chapter is to give you a basis for understanding how PKI fits into the big picture. PKI is important to using public key cryptography effectively, and is essential to understanding and using the SSL protocol. A comprehensive discussion of PKI is beyond the scope of this book. For much more in-depth discussion, we recommend the book Planning for PKI: Best Practices Guide for Deploying Public Key Infrastructure by Russ Housley and Tim Polk ( John Wiley & Sons).

In this chapter, we’ll look at how PKI functions. We start by examining the various components that comprise such an infrastructure. Then we demonstrate how to become a part of a public infrastructure so that others wishing to communicate securely with us can do so. Finally, we look at how to use the OpenSSL command-line tool to set up our own private infrastructure.

Certificates

At the heart of PKI is something called a certificate . In simple terms, a certificate binds a public key with a distinguished name . A distinguished name is simply the name of the person or entity that owns the public key to which it’s bound. Perhaps a certificate can be best compared to a passport, which binds a picture with a name, thus solidifying a person’s identity. A passport is issued by a trusted third party (the government) and contains information about the person to whom it has been issued (the subject) as well as information about the government that issued it (the issuer). Similarly, a certificate is also issued by a trusted third party, contains information about the subject, and contains information about the third party that issued it.

Not unlike a passport, which contains a watermark used to verify its authenticity, a certificate also contains safeguards intended to allow the authenticity of the certificate to be verified, and aid in the detection of forgery or tampering. Also similar to a passport, a certificate is valid only for a defined period. Once it has expired, a new certificate must be issued, and the old one should no longer be trusted.

A certificate is signed with the issuer’s private key, and it contains almost all of the information necessary to verify its validity. It contains information about the subject, the issuer, and the period for which it is valid. The key component that is missing is the issuer’s certificate. The issuer’s certificate is the key component for verifying the validity of a certificate because it contains the issuer’s public key, which is necessary for verifying the signature on the subject’s certificate.

By signing a certificate with the issuer’s private key, anyone that has the issuer’s public key can verify its authenticity. The signature serves as a safeguard to prevent tampering. By signing the subject’s certificate, the issuer asserts that it has verified the authenticity of the public key that the certificate contains and states that it may be trusted. As long as the issuer is trusted, the certificates that it issues can also be trusted.

It’s important to note that the issuer’s certificate or public key may be contained in an issued certificate. It’s more important to note that this information cannot be trusted to authenticate the certificate. If it was trusted, the element of trust established from a third party is effectively eliminated. Anyone could create another key pair to use in signing a certificate and place that public key in the certificate.

Certificates are also created with a serial number embedded in them. The serial number is unique only to the issuer of the certificate. No two certificates issued by the same issuer should ever be assigned the same serial number. The certificate’s serial number is often used to identify a certificate quickly.

Certification Authorities

A Certification Authority (CA) is an organization or company that issues certificates. By its very nature, a CA has a huge responsibility to ensure that the certificates it issues are legitimate. That is, the CA must ensure beyond all reasonable doubt that every certificate it issues contains a public key that was issued by the party that claims to have issued it. It must be able to produce acceptable proof for any certificate that it issues on demand. Otherwise, how can the CA itself be trusted?

There are two basic types of CAs. A private CA has the responsibility of issuing certificates only for members of its own organization, and is likewise trusted only by members of its own organization. A public CA, such as VeriSign or Thawte, has the responsibility of issuing certificates for any member of the public, and must be trusted by the public. The burden of proof varies depending on the type of CA that has issued a certificate and the type of certificate that is issued.

A CA must be trusted, and so for that trust to be extended, its certificate containing its public key must be widely distributed. For public CAs, their certificates are generally published so that anyone can obtain them. More commonly, the software that makes use of them, such as a web browser, is shipped containing them. Most often, the software allows certificates from other CAs to be added to its list of trusted certificates, thus facilitating the use of private CAs with off-the-shelf software.

Private Certification Authorities

A private CA is often ideal for use in a corporate setting. For example, a company could set up its own CA for email, using S/MIME as the standard for encrypting and authenticating email messages. The company’s CA would issue certificates to each employee, and each employee would configure their S/MIME-capable email clients to recognize the company’s CA as being trusted.

For a private CA, verifying the identity of a subject is often a reasonably simple and straightforward matter. When used in a corporate environment, for example, employees are known, and their identities can be easily identified using information obtained from the company’s human resources department. In such a scenario, the human resources department is said to be acting as a Registration Authority (RA).

Public Certification Authorities

A public CA commonly issues certificates for public web sites requiring encryption and/or authentication, often for e-commerce in which customer information must be transmitted securely to place an order. For such operations, it’s essential that the customers transmit their information to the site that is supposed to be receiving it without worrying about someone else obtaining the information.

For a public CA, verifying the identity of a subject[1] is considerably more difficult than it is for a private CA. The information required from the subject to prove its identity to the CA varies depending on whether the subject is an individual or a business. For an individual, the proof required could be as simple as a photocopy of a government-issued ID, such a driver’s license or passport. For a business or other organization, similar government documentation proving your right to use the name will also likely be required.

It’s important to note that most public CAs provide their services to make money, and not to simply benefit the public. They still have a responsibility to verify a subject’s identity, but not actually guarantee anything—the liability is too great to provide an absolute guarantee. Certainly, it is in the CA’s best interests to verify a subject’s identity to the best of its ability, however. If a CA gains the reputation of issuing certificates to anyone who asks (and pays them enough money), they’re not going to remain in business for very long because nobody will trust them.

Certificate Hierarchies

A certificate that is issued by a CA can be used to issue and sign another certificate, if the issued certificate is created with the appropriate permissions to do so. In this way, certificates can be chained. At the root of the chain is the root CA’s certificate. Because it is at the root of the chain and there is no other authority to sign its certificate, the root CA signs its own certificate. Such a certificate is known as a self-signed certificate .

There is no way to digitally verify the authenticity of a self-signed certificate because the issuer and the subject are the same, which is why it has become a common practice to provide them with the software that uses them. When they’re included with an application, they are generally obtained by the software author through some physical means. For example, Thawte provides its root certificates on its web site, free and clear, but strongly advises anyone making use of them to confirm the certificate fingerprints with Thawte via telephone before using or distributing them.

To verify the authenticity and validity of a given certificate, each certificate in the chain must also be verified, from the certificate in question’s issuer all the way up to the root certificate. If any certificate in the chain is invalid, each certificate below it in the chain must also be considered invalid. Invalid certificates typically have either expired or been revoked (perhaps due to certificate theft). A certificate is also considered invalid if it has been tampered with and the signatures on the certificate don’t match with the ones that should have been used to sign it.

The decision whether to employ a certificate hierarchy more complex than a single root CA depends on many factors. These factors and their trade-offs are well beyond the scope of this book. Entire books have been devoted to PKI, and we strongly recommend that you consult one or more of them to assist you in making an informed decision. Again, we strongly recommend Planning for PKI by Russ Housley and Tim Polk.

Certificate Extensions

The most widely accepted format for certificates is the X.509 format, first introduced in 1988. There are three versions of the format, known as X.509v1, X.509v2, and X.509v3. The most recent revision of the standard was introduced in 1996, and most, if not all, modern software now supports it. A large number of changes were made between X.509v1 and X.509v3, but perhaps one of the most significant features introduced in the X.509v3 standard is its support of extensions.

Version 3 extensions allow a certificate to contain additional fields beyond those defined by previous versions of the X.509 standard. The additional fields may be standard in X.509v3, such as the basicConstraints or keyUsage fields, or they may be completely nonstandard, perhaps recognized only by a single application. Each extension has a name for its field, a designation indicating whether the extension is critical , and a value to be associated with the extension field. When an extension is designated as critical, software that does not recognize the extension must reject the certificate as being invalid. If the extension is noncritical, it may be ignored.

The X.509v3 standard defines 14 extensions in an effort to consolidate the most common extensions implemented by third parties. One example is the permissible uses for a certificate—for instance, whether a certificate is allowed to sign another certificate, or is usable in an SSL Server. If each application were to create its own disparate extensions, the information in those extensions would be either unusable by other applications or significantly complicate the process of validating a certificate because it would need to recognize a virtually unlimited number of different extensions that all essentially mean the same thing.

Of the 14 standard extensions defined by X.509v3, only 4 are well-supported and in widespread use. Only one of them must be designated critical according to the standard, while the other three may or may not be. Since the majority of the standard extensions are not well supported, we won’t discuss them here. Later in this chapter, when we setup our own CA, we’ll be making use of some of the better-supported extensions, as appropriate.

The basicConstraints extension is a sequence that may contain two possible components: cA and pathLenConstraint. Without getting into the technical details of an X.509 certificate, a sequence can best be thought of as a container, which contains other components; it has no value of its own. The cA component is a boolean indicating whether the certificate may be used as a CA’s certificate. If the cA component is absent, OpenSSL will check the keyUsage extension to determine whether to allow the certificate to be used as a CA certificate. If the keyUsage extension is present and the keyCertSign bit is not set, the certificate may not be used as a CA certificate. The optional pathLenConstraint component is an integer that specifies the maximum number of certificates in the chain that may be used below this certificate. If the value is less than the number of certificates in the chain that have already been validated, this certificate must be rejected.

The keyUsage extension is a bit string that defines how a certificate can be used, and may or may not be designated critical. If the extension is present in the certificate, it should be marked critical. If it is designated critical, the information that it contains will always be used to determine valid usage. If the extension is absent or designated noncritical, the certificate should be treated as though all bits are set. Rather than individually explain what each bit means, it’s more useful to show which bits should be set for each of the common uses for a certificate, which we do in Table 3-1.

Table 3-1. Common bit settings for the keyUsage extension

Purpose of certificate

Bit settings to use

Certification Authority Certificate

keyCertSign and cRLSign

Certificate Signing

keyCertSign

Object Signing

digitalSignature

S/MIME Encryption

keyEncipherment

S/MIME Signing

digitalSignature

SSL Client

digitalSignature

SSL Server

keyEncipherment

The extKeyUsage extension is a sequence of object identifiers that further defines which uses of the certificate are permissible, and may or may not be designated critical. As with the keyUsage extension, if this extension is present, it should be designated critical. If it is designated critical, the certificate must be used for one of the purposes defined by the extension. If it is designated noncritical, the information is advisory only and may be ignored. There are eight possible purposes defined for use with this extension, as summarized in Table 3-2.

Table 3-2. Purposes defined for the extKeyUsage extension

Purpose of certificate

Object identifier (OID)

Server Authentication

1.3.6.1.5.5.7.3.1

Client Authentication

1.3.6.1.5.5.7.3.2

Code Signing

1.3.6.1.5.5.7.3.3

Email

1.3.6.1.5.5.7.3.4

IPSec End System

1.3.6.1.5.5.7.3.5

IPSec Tunnel

1.3.6.1.5.5.7.3.6

IPSec User

1.3.6.1.5.5.7.3.7

Timestamping

1.3.6.1.5.5.7.3.8

It’s worth noting that neither the keyUsage nor the extKeyUsage extension is well-defined, and as such, their usage is subject to wide interpretation. In particular, how to treat the critical flag on either extension is not well-defined, but it would seem that in many existing software products, the extensions are largely ignored. In addition, various profiles (guidelines that dictate what certificates should contain) specify their usage differently. For instance, PKIX (the IETF Public Key Infrastructure working group) has obsoleted the three IPSec-related OIDs that may be present in an extKeyUsage sequence. Additionally, they are not implemented consistently across vendors. As a result of these problems, these two extensions are mostly useless. If you do use them, be sure that you are using them in a consistent manner with any existing software with which you’ll be interoperating.

The cRLDistributionPoints extension is a sequence that is used to communicate how the CA that issued the certificate makes its CRLs available. The standard indicates that this extension should be designated noncritical; however, it does advise CAs to include the information. Providing the location of the CRL that would contain this certificate’s serial number if it is revoked inside the certificate itself is perhaps the best possible way for software validating a certificate to obtain the information.

Certificate Revocation Lists

Once a certificate has been issued, it is generally put into production, where it will be distributed to many clients. If an attacker compromises the associated private key, he now has the ability to use the certificate even though it doesn’t belong to him. Assuming the proper owner is aware of the compromise, a new certificate with a new key pair should be obtained and put into use. In this situation there are two certificates for the same entity—both are technically valid, but one should not be trusted. The compromised certificate will eventually expire, but in the meantime, how will the world at large know not to trust it?

The answer lies in something called a certificate revocation list (CRL). A CRL contains a list of all of the revoked certificates a CA has issued that have yet to expire. When a certificate is revoked, the CA declares that the certificate should no longer be trusted.

Bandwidth is a significant concern when distributing CRLs, since clients need to have reasonably current revocation information in order to properly validate a certificate. In an ideal world, the client would get up-to-date revocation information as soon as the CA gets the information. Unfortunately, many CAs distribute CRLs only as a huge list. Downloading a huge list before validating each certificate could easily add unacceptable latency and place an undue load on the server when there are a lot of clients. As a result, CAs tend to update their CRLs regularly, but not immediately after they learn about key compromises. Included in the revocation list is the date and time that the next update will be published, so once an application has downloaded the list, it doesn’t need to do so again until the one it has expires. Clients are encouraged to cache the information (which can be infeasible if the client has limited storage space).

This scheme leaves a window of vulnerability in which the CA knows about a revoked certificate, yet the client does not find out about it immediately. If a CA publishes the list too frequently, it will require massive amounts of bandwidth in order to sustain the frequent demand for the list. On the other hand, if a CA publishes the list too infrequently, certificates that need to be revoked will still be considered valid until the next list is published. Each CA needs to strike a balance with the community that it’s serving to determine how frequently to publish its list.

One solution to this problem is for the CA to break up its CRLs into segments. To do this, the CA specifies ranges of certificate serial numbers that each CRL contains. For example, the CA could create a different CRL for each 1,000 serial numbers. Therefore, the first CRL would be for serial numbers 1 through 1,000; the second would be for serial numbers 1,001 through 2,000, and so on. This solution does require forethought and planning on the part of the CA, but it reduces the size of the CRLs that the CA issues. Another option is to use " delta CRLs,” where a CA periodically publishes incremental changes to its CRL list. Delta CRLs still require the client to cache CRL information or download everything anew each time a certificate needs to be validated.

Another problem with CRLs is that while there is a standard means to publish them formally, specified in RFC 2459, that mechanism is optional, and many of the more common public CAs, such as VeriSign, do not distribute their CRLs this way. There are also other standard methods for distributing CRLs, but the overall problem is that there isn’t just one, and so many software applications do not actually make use of CRLs. Of the various methods of distribution, LDAP is most commonly used as a repository for CRLs. Additionally, multiple applications on the same machine, or even on the local network, could be interested in the same data and require that it be queried from the CA multiple times within a short period.

The problems with the distribution of CRLs currently make them difficult to manage, and what’s worse, few applications even make the attempt. This essentially makes CRLs useless and leaves no way for a CA to revoke a certificate effectively once it’s been issued. Ideally, CAs need to standardize a method for CRL distribution, and both CAs and applications need to start making use of it.

Another potentially serious problem that has not been addressed is what happens when a root CA’s certificate needs to be revoked. A CRL is not suited to handle this, and neither are applications. The reason for this is that CRLs are issued by a parent (a CA) for its children, but a root CA has no parent. It is possible for a CA to revoke its own certificate as long as it still has its private key. For the purposes of signing a CRL containing its own certificate, the CA’s compromised key can still be trusted. Unfortunately, given the poor state of CRL handling in existing software in general, it’s not likely that this situation is handled very well, if at all.

A classic example demonstrating that CRLs are poorly supported is what happened in early 2001 when VeriSign issued two class 3 code-signing certificates to Microsoft Corporation. The problem was that Microsoft never requested these certificates—someone claiming to represent Microsoft did. VeriSign handled the situation in the appropriate manner and published the serial numbers of the certificates in a new CRL. What really demonstrated the flaws with CRLs was how Microsoft handled the situation. It quickly became clear that Microsoft’s software, while distributing VeriSign’s root certificates and using their services, did not check VeriSign’s CRLs. Microsoft issued a patch to deal with the problem of the revoked certificates, but the patch did nothing to fix the problem of their software not utilizing the CRLs at all. Had Microsoft’s software made proper use (or, arguably, any use at all) of CRLs, no patch would have been necessary, and the problem would have ended with VeriSign’s publication of its CRL (minus the inherent window of vulnerability).

It could be argued that if a major software company like Microsoft can’t handle CRLs properly, how can smaller software companies and individual software developers be expected to handle them properly? While the argument may very well be faulty in a number of respects, it is still a question worth asking, and in truth, the answer, at least for right now, is not one that we would all like to hear. PKI is still relatively immature, and much work needs to be done to remedy not only the issues that we’ve discussed here, but others that we leave as an exercise for the reader to explore as well. While CRLs may not be the ultimate answer to revoking a certificate, for the time being, they are the most widely implemented means by which to do so. It’s worth taking the time to ensure that your software is capable of dealing with the technology and provides for a reasonably safe and pleasant experience for your users.

To complicate matters more, the standard CRL specification has changed over time, and both the old format (Version 1) and the new format (Version 2) are actively used. OpenSSL supports both Version 1 and Version 2 CRLs, but there is much software still in common use that does not yet support Version 2, and certainly old legacy applications that are no longer being developed or supported never will, even though they continue to be used. The major addition that Version 2 offers is extensions. The standard defines four extensions that are used primarily to indicate when a certificate was revoked, why a certificate was revoked, and how to handle a certificate that has been revoked.

The fourth standard extension is used in indirect CRLs. An indirect CRL is one that is not necessarily issued by a CA, but instead by a third party. Such a CRL can contain certificates from multiple CAs. The extension, then, is used to indicate which CA issued the certificate that has been revoked. Currently, indirect CRLs are not very common, because CRLs in Version 2 format are not widely supported.

Online Certificate Status Protocol

The Online Certificate Status Protocol (OCSP), formally specified in RFC 2560, is a relatively new addition to PKI. Its primary aim is to address some of the distribution problems that have traditionally plagued CRLs.

Using OCSP, an application makes a connection to an OCSP responder and requests the status of a certificate by passing the certificate’s serial number. The responder replies “good,” “revoked,” or “unknown.” A “good” response indicates that the certificate is valid, so far as the responder knows. This does not necessarily mean that the certificate was ever issued, just that is hasn’t been revoked. A “revoked” response indicates that the certificate has been issued and that it has indeed been revoked. An “unknown” response indicates that the responder doesn’t know anything about the certificate. A typical reason for this response could be that the certificate was issued by a CA that is unknown to the responder.

An OCSP responder is typically operated by a CA or by a trusted third party that is authorized by the CAs for which it provides information. The client must trust the OCSP responder in a manner similar to a root CA. More importantly, there is only one way to revoke an OCSP’s trusted status, and it’s not pretty. If an OCSP responder is compromised, every client that makes use of that responder must be reconfigured manually either not to trust it or to use a new certificate that can be trusted.

A client’s request includes information about the issuer of the certificate it is requesting status information for, so it is possible for a single OCSP responder to provide certificate revocation information for more than a single CA. Unfortunately, one of the problems of OCSP responders when run by a third party is that the information they’re serving can become stale. At the very least, a delay often occurs between the time when a CA revokes a certificate and when the responder receives the information from the CA, particularly if the responder is relying on CRLs published by its serviceable CAs to supply its information.

Currently, OCSP is not nearly as widely recognized or implemented as CRLs are, so unless you know that all your users will have an OCSP server available, it is generally best to use the technology to supplement CRLs rather than replace them completely.

Three of the more significant problems that OCSP introduces are the potential for denial of service, replay, and man-in-the-middle attacks. Most servers are vulnerable to denial of service attacks to some extent, but the nature of the service, the amount of information transferred, and the way requests are handled help determine just how vulnerable a given server is to such an attack. The details of denial of service attacks are beyond the scope of this book; however, OCSP responders are typically more susceptible to them than other common services such as HTTP.

The OCSP Version 1 specification allows responders to pre-produce signed responses in an effort to reduce the load on the responder required by signing definitive responses. Allowing for pre-produced signed responses opens the door for replay attacks. Man-in-the-middle attacks are possible because error responses are not signed, although this type of attack could more accurately be considered a denial of service attack. Perhaps what’s most disturbing about the aforementioned vulnerabilities is the fact that each one is noted in the RFC, yet nothing was done when formalizing the standard to prevent them.

There are only a handful of public OCSP responders available at the time of this writing, as listed by www.OpenValidation.org . The small number of responders is a clear indication that OCSP is not widely deployed. While OCSP is an attempt at resolving the problems of CRLs, we feel that the additional problems it creates, at least in its current state, outweigh the problems that it solves. Certainly, it cannot be reasonably considered as a replacement for CRLs. In its defense, there was an IETF draft submitted in March of 2001 for Version 2 of the protocol, which addresses some of the issues, but this has not yet completed the standards process.

Obtaining a Certificate

Before obtaining a certificate, you first need to determine what purpose the certificate will serve. There are many different types of certificates offered by a variety of CAs, both public and private. For the purposes of this discussion, we will investigate what is necessary to obtain three different types of certificates from a public CA. While it is certainly not the only public CA, we’ve chosen VeriSign as the CA that we’ll obtain a certificate from because it is perhaps the most established public CA and offers the widest variety of certificates for a variety of uses.

As we mentioned, there are many different types of certificates, each used for different purposes. VeriSign’s offerings range from personal certificates for use with S/MIME to enterprise solutions that are more sophisticated. We’ll find out how to get a personal certificate for S/MIME, a code-signing certificate for signing your software so that users can verify that it came from you, and a certificate for securing your web site for applications such as e-commerce.

Personal Certificates

S/MIME email relies on personal certificates (as opposed to certificates granted to an organization), which VeriSign calls a Class 1 Digital ID . It is the easiest kind of certificate to obtain, and is available for a modest price, but it is limited to email security only. You can get a Class 1 Digital ID that works with Netscape Messenger, or you can get one intended to work with Microsoft Outlook express. If you use a different application to read and write your email, you should consult with that application’s vendor to find out whether it interoperates with either of these certificate types.

The first step in obtaining a personal certificate is to visit VeriSign’s web site at http://www.verisign.com/ and follow the links from the main page to “Secure E-Mail”, which is listed under “Home & Home Office” products, to the Digital ID enrollment form. We won’t outline all of the links here, not only because they’re subject to change, but because there’s a wealth of information on the site that is well worth reading, including information on how to make use of the certificate once it has been issued. Once you have filled out and submitted the enrollment form, VeriSign will send an automated email to the address you provided with instructions on how to “pick up” the certificate.

The first set of questions on the enrollment form is self-explanatory. The first and last name that you enter will be how your Digital ID is listed in VeriSign’s directory service. The email address that you enter should be the one that you will be using with the Digital ID. It becomes the certificate’s distinguished name. It is also listed alongside your first and last name in the directory. VeriSign will also use the address to verify its validity by sending an automated email to that address with instructions on how to retrieve the certificate that has been issued.

Next, VeriSign will request a challenge phrase, which will be used to protect the certificate. The phrase will be available to you and VeriSign. You should not share it with anyone else! VeriSign will use the phrase to verify that you are the owner of the certificate when you request that it be revoked, renewed, or replaced. Be sure to choose a phrase that you’ll be able to remember, but one that will not be easily guessed by someone that knows you well.

VeriSign chooses a default key length for the certificate and issues it to you based upon the information from your browser. You shouldn’t need to change the key length that is selected for you unless you’re using something other than Netscape or Microsoft products to access your email, in which case the documentation for your email software or the vendor of the software should have advised you on the proper setting to choose.

If you’re using Microsoft Internet Explorer, your certificate will be unprotected by default. That is, once you install it in your email software, you will not be required to enter any password or passphrase to gain access to it. If you opt to keep your certificate unprotected in this manner, you must make every assurance that the private key for your certificate is not compromised. It is generally not a good idea to leave your certificate unprotected, so VeriSign offers two methods of protecting it. One step up from the default of low security is medium security, which requires your approval each time the private key is accessed. With medium security, you still are not required to enter a password or passphrase to unlock the private key. High security requires you to enter a password or passphrase to unlock the key each time it is accessed.

Remember that anybody gaining access to your private key will be able to use your certificate to masquerade as you. When an email is signed with your private key, people are going to trust it, and this can have disastrous effects if your key is compromised. Anyone with access to your private key will also be able to decrypt email that has been encrypted with your public key. Sure, your certificate can be revoked, but as we discussed earlier, revoking a certificate doesn’t have any effect if its revocation status is not being checked. With this in mind, particularly for mobile users, we strongly recommend that you choose high security.

Finally, you must read and accept VeriSign’s subscriber agreement and privacy policy. If you’re using Microsoft Internet Explorer and you checked the checkbox for securing your certificate, a dialog will be presented to you to select the security level that you wish to apply to the certificate. Within an hour or so, you will receive an email from VeriSign at the address that you entered into the enrollment form containing instructions on how to “pick up” your certificate from VeriSign. Included in the email are a URL and a PIN, both of which will be required to get the certificate from VeriSign. You should use the same machine and browser to retrieve the certificate as you did to request it.

That’s all there is to it! Once you’ve retrieved your certificate from VeriSign, follow the directions presented on VeriSign’s site to use the certificate in either Netscape or Microsoft Internet Explorer. Again, if you’re using other software to access your email, follow the vender’s directions to enable the certificate. Now you’re ready to start sending and receiving secure email!

Code-Signing Certificates

VeriSign offers code-signing certificates for use by software developers and software vendors. The purpose of such a certificate is to sign code that users download off the Internet. By signing your code, users can be assured that the code has not been tampered with or corrupted since it was digitally signed with your certificate. In the online world where people are not only becoming increasingly aware of security issues, but also worry about viruses and worms, signing your code provides a certain assurance to your users that they are getting the software that they’re expecting to get.

Obtaining a code-signing certificate is not nearly as quick and easy as obtaining a personal certificate. They are also considerably more expensive, but then again, they’re not really intended for everyday individual users. At the time that this text was written, VeriSign offered six different types of code-signing certificates for various types of programs. You must be sure to get the proper certificate for the code that you wish to sign because the different types of certificates may not work properly with other types of code. For example, Microsoft Authenticode certificates only work for Microsoft’s Internet Explorer browser. For Netscape browsers, you need to get a Netscape Object Signing certificate. The available types of code-signing certificates are listed as part of the process of obtaining a code-signing certificate. Choosing a type is the first step in obtaining a code-signing certificate.

The type of code-signing certificate determines the specific requirements for making the request to VeriSign to obtain it. For a Microsoft Authenticode Digital ID, for example, much of the work is automated through Microsoft’s Internet Explorer, while a Sun Java Signing Digital ID requires you to generate a certificate request using Sun’s Java tools to be submitted along with the request. For each type of certificate, VeriSign supplies full instructions on what code-signing-certificate-dependent information is needed and how to go about obtaining and supplying it to VeriSign.

While each type of code-signing certificate has its own specific requirements for making the request, there are common requirements that must be met as well. Most of the requirements are self-explanatory, such as contact and payment information. Each certificate must also have information about who owns the certificate. Such information includes the name of the company or organization and the location from which it does business. For example, a company doing business from the United States would be required to supply the city and state in which it is located.

There is, of course, also the very important need for the CA, VeriSign in this case, to verify that they’d be issuing the certificate to someone who should legitimately have it. The quickest and easiest way for VeriSign to verify this information is with a Dun & Bradstreet D-U-N-S number. Supplying this information is optional, but the alternatives require more time and effort both on your part and VeriSign’s. If you do not have or do not want to use a D-U-N-S number, you can optionally mail or fax copies of your business license, articles of incorporation, or partnership papers along with your request for a code-signing certificate.

Once your request, including any appropriate documentation, has been submitted, VeriSign takes it under review. If everything is in order, a code-signing certificate is issued and instructions on how to retrieve the certificate so that you may distribute and use it are provided. Unlike a personal certificate, the request for a code-signing certificate is reviewed and verified by an actual living human being, and so is not made immediately available. Depending on VeriSign’s workload, it may take several days for the certificate to be issued, although VeriSign expedites requests for an additional fee.

Web Site Certificates

The process of obtaining a certificate for use in securing a web site, which VeriSign calls a secure server certificate, is similar to the process for obtaining a certificate for a code-signing certificate. Much of the same information is required, although there are some differences worth noting. Obviously, one of the primary differences is in the types of certificates offered. While code-signing certificates differ based on the type of code that will be signed (Netscape plug-ins versus Java applets, for example), secure server certificates are one of either 40-bit or 128-bit SSL certificates. That is, web site certificates explicitly restrict the size of the symmetric keys that should be used with the certificate. We recommend you stick with 128-bit certificates, since 40-bit symmetric keys are widely regarded as unacceptably weak.

No matter which server software you plan to use, you must follow its instructions on how to generate a Certificate Signing Request (CSR). Due to the wide variety of servers available today, it is not practical for us to provide instructions on how to do this here. VeriSign has instructions for many of the more popular servers available on its web site. The CSR you generate will also generate a key pair. While you must submit the CSR to VeriSign to have the certificate issued, you should keep the private key to yourself. It should not be sent to VeriSign or to anybody else.

As with code-signing certificates, you must also provide acceptable proof to VeriSign that you have a right to the certificate you are requesting. The options for providing this proof are the same—provide either a D-U-N-S number or a copy of one of the aforementioned acceptable documents. Additionally, a secure server certificate is bound to a domain name. VeriSign will issue certificates only to the registered owner of a domain. This means that if the domain is owned by a corporate entity, you must be an employee of that company.

Once your request, including any appropriate documentation, has been submitted, VeriSign takes it under review. If everything is in order, a secure server certificate is issued and the certificate is emailed to the technical contact that was provided when the request was submitted. As with code-signing certificates, an actual living human being reviews the information, so it may take several days for the certificate to be issued, depending on VeriSign’s workload. Expedited processing is also available for an additional fee.

Setting Up a Certification Authority

Setting up a CA can seem like a daunting task, but it doesn’t have to be. There are a number of free and commercial CA packages available. The OpenSSL command-line tool even provides all of the functionality required to set up a minimal CA that can be used in a small organization. The OpenSSL command-line tool’s CA functionality was originally intended as an example only, but two of the more popular freely available CA packages, OpenCA and pyCA, use it as their foundation. As of this writing, these tools are still fairly immature, and offer very little that the OpenSSL command-line tool doesn’t have (LDAP storage is the notable exception).

In this section, we’ll go through the necessary steps to set up a CA using OpenSSL’s command-line tools. We’ll show you how to create a self-signed root certificate for use by your CA, how to build a configuration file that OpenSSL can use for your CA, and how to issue certificates and CRLs with your CA. Since OpenSSL’s command-line CA functionality was intended primarily as an example of how to use OpenSSL to build a CA, we don’t recommend that you attempt to use it in a large production environment. Instead, it should be used primarily as a tool to learn how PKI works and as a starting point for building a real CA with tools designed specifically for use in a production environment.

Creating an Environment for Your Certification Authority

The first step in setting up a CA with the OpenSSL command-line tool is creating an environment for it to run in. Several files and directories must be created. The easiest way to set everything up is from the command line, using your favorite text editor to create the necessary files. For our example CA, we’ll be using the bash shell on a Unix system. Whether the system is Linux or FreeBSD or some other variety of Unix doesn’t matter; the instructions will be the same. There will be some variation for Windows-based systems.

First, we must choose a location for all of our CA’s files to reside. For our example, we use /opt/exampleca as the root directory for our CA, but you may choose any location you like on your system. All of our CA’s files, including issued certificates and CRLs, will be contained within this directory. Keeping the files together makes it easier to find any of the files used by our CA and to set up multiple CAs.

Within the CA’s root directory, we need to create two subdirectories. We’ll name them certs and private . The subdirectory certs will be used to keep copies of all of the certificates that we issue with our CA. The subdirectory private will be used to keep a copy of the CA certificate’s private key. For the most part, the majority of the files that the CA uses are visible to anyone on the system. In fact, many of the files are supposed to be distributed to the public, or at least to anyone who makes any use of the certificates issued by our CA. The one notable exception is the CA certificate’s private key. The private key should never be disclosed to anyone not authorized to issue a certificate or CRL from our CA.

A good CA needs to protect its private key as best it can. 2,048 bits are the bare minimum length for a CA key. The private key should be stored in hardware, or at least on a machine that is never put on a network (CSRs would arrive via the sneaker net).

Besides key generation, we will create three files that our CA infrastructure will need. The first file is used to keep track of the last serial number that was used to issue a certificate. It’s important that no two certificates ever be issued with the same serial number from the same CA. We’ll call this file serial and initialize it to contain the number 1. OpenSSL is somewhat quirky about how it handles this file. It expects the value to be in hex, and it must contain at least two digits, so we must pad the value by prepending a zero to it. The second file is a database of sorts that keeps track of the certificates that have been issued by the CA. Since no certificates have been issued at this point and OpenSSL requires that the file exist, we’ll simply create an empty file. We’ll call this file index.txt (see Example 3-1).

Example 3-1. Creating the CA’s environment
# mkdir /opt/exampleca
# cd /opt/exampleca
# mkdir certs private
# chmod g-rwx,o-rwx private
# echo '01' > serial
# touch index.txt

Building an OpenSSL Configuration File

One more file still needs to be created, but it is significantly more complex than the first two files that we’ve already created. It is a configuration file that will be used by the OpenSSL command-line tool to obtain information about how to issue certificates. We could conceivably skip creating this file and use the OpenSSL defaults, which are actually quite sane, but by using a configuration file, we save ourselves some work in issuing commands to OpenSSL. We briefly discussed configuration files and their use with the command-line tool in the Chapter 2. Now it’s time to actually create a configuration file of our own and put it to use.

The OpenSSL command for the CA functions is aptly named ca , and so the first section that we’re interested in is named ca. For our purposes, this section is quite simple, containing only a single key: default_ca . The value is the name of a section containing the configuration for the default CA. OpenSSL allows for multiple CA configurations in the same configuration file. If the name of a configuration to use is not specified, OpenSSL uses the name paired with the default_ca key. The default can be overridden on the command line with the name option.

Example 3-2 shows the configuration file for our CA. We’ve already explained what the files and directories we’ve created are for, so the first set of keys in the example should be clear; we’re simply telling OpenSSL where we’ve decided to place the files and directories that it needs to use. The three keys, default_crl_days , default_days , and default_md , correspond to the command-line crldays, days, and md options, and may be overridden by using them.

The default_crl_days key specifies the number of days between CRLs. You may wish to use default_crl_hours instead if you plan to publish CRLs more than once a day. This setting computes the nextUpdate field of the CRL when it is generated. The default_days key specifies the number of days an issued certificate will be valid. The default_md specifies the message digest algorithm that will be used to sign issued certificates and CRLs. Possible legal values for this key include md5, sha1, and mdc2.

The policy key specifies the name of a section that will be used for the default policy. It may be overridden on the command line with the policy option. A policy definition is a set of keys with the same name as the fields in a certificate’s distinguished name. For each key or field, there are three legal values: match, supplied, or optional. A value of match means that the field by that name in a certificate request must match the same field in the CA’s certificate. A value of supplied means that the certificate request must contain the field. A value of optional means that the field is not required in the certificate request.

By default, when a certificate is issued, OpenSSL orders the DN (distinguished name) fields in the same order as they appear in the policy definition being used. Any fields that are present in the certificate request but not present in the policy definition are omitted from the issued certificate. This behavior can be changed by using the preserveDN option or by setting the preserve key to yes in the CA definition section. When this option is set, all of the fields in the certificate request are included in the issued certificate, and they remain in the same order as they were in the certificate request. Ordinarily, you should not need to enable this option unless you’re dealing with older versions of Microsoft Internet Explorer, which require the fields in the issued certificate to match the certificate request. If you’re dealing with very old versions of Microsoft Internet Explorer, you may also need to enable the “MSIE hack” either by using the msie_hack option or by setting the msie_hack key to yes in the CA definition section.

The x509_extensions key specifies the name of a section that will contain the extensions to be added to each certificate issued by our CA. If this key is absent, OpenSSL creates an X.509v1 certificate, but if it is present, even if it is empty, an X.509v3 certificate is created. The only extension that we’ve included in our example is the basicConstraints extension, and we’ve set its cA component to false so that the certificates issued by our CA, in turn, may not be used as CA certificates. The certificate chain stops with certificates that we issue. Example 3-2 shows the configuration file.

Example 3-2. A simple CA configuration definition
 [ ca ]
default_ca = exampleca
 
[ exampleca ]
dir              = /opt/exampleca
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           = exampleca_policy
x509_extensions  = certificate_extensions
 
[ exampleca_policy ]
commonName             = supplied
stateOrProvinceName    = supplied
countryName            = supplied
emailAddress           = supplied
organizationName       = supplied
organizationalUnitName = optional
 
[ certificate_extensions ]
basicConstraints = CA:false

Now that we’ve created a configuration file, we need to tell OpenSSL where to find it. By default, OpenSSL uses a system-wide configuration file. Its location is determined by your particular installation, but common locations are /usr/local/ssl/lib/openssl.cnf or /usr/share/ssl/openssl.cnf. Since we’ve created our own configuration file solely for the use of our CA, we do not want to use the system-wide configuration file. There are two ways to tell OpenSSL where to find our configuration file: using the environment variable OPENSSL_CONF, or specifying the filename with the config option on the command line. Since we will issue a sizable number of commands that should make use of our configuration file, the easiest way for us to tell OpenSSL about it is through the environment (see Example 3-3).

Example 3-3. Telling OpenSSL where to find our configuration file
# OPENSSL_CONF=/opt/exampleca/openssl.cnf
# export OPENSSL_CONF

Creating a Self-Signed Root Certificate

Before we can begin issuing certificates with our CA, it needs a certificate of its own with which to sign the certificates that it issues. This certificate will also be used to sign any CRLs that are published. Any certificate that has the authority to sign certificates and CRLs will do. By this definition, a certificate from another CA or a self-signed root certificate will work. For our purposes, we should create our own self-signed root certificate to do the job.

The first thing that we need to do is add some more information to our configuration file. Example 3-4 shows the newly added information. Note that we’ll be using the command-line tool’s req command, so we’ll start by adding a new section by the same name. Since we will use only this configuration file for our CA, and since we will use only the command-line tool’s req command this one time, we’ll put all of the necessary information that OpenSSL allows in the configuration file rather than typing it out on the command line. It’s a little more work to do it this way, but it is the only way to specify X.509v3 extensions, and it also allows us to keep a record of how the self-signed root certificate was created.

Example 3-4. Configuration file additions for generating a self-signed root certificate
 [ req ]
default_bits       = 2048
default_keyfile    = /opt/exampleca/private/cakey.pem
default_md         = md5
 
prompt             = no
distinguished_name = root_ca_distinguished_name
 
x509_extensions    = root_ca_extensions
 
 [ root_ca_distinguished_name ]
commonName          = Example CA
stateOrProvinceName = Virginia
countryName         = US
emailAddress        = ca@exampleca.org
organizationName    = Root Certification Authority
 
[ root_ca_extensions ]
basicConstraints = CA:true

The default_bits key in the req section tells OpenSSL to generate a private key for the certificate with a length of 2,048 bits. If we don’t specify this, the default is to use 512 bits. A key length of 2,048 bits provides significantly more protection than 512, and for a self-signed root certificate, it’s best to use all of the protection afforded to us. With the vast computing power that is affordable today, the speed penalty for using a 2,048-bit key over a 512-bit key is well worth the trade-off in protection, since the security of this one key directly impacts the security of all keys issued by our CA.

The default_keyfile key in the req section tells OpenSSL where to write the newly generated private key. Note that we’re specifying the same directory for output as we specified earlier in the ca section as the location of the private key for the certificate. We can’t use the $dir “macro” here because the dir key is private to the ca section, so we need to type out the full path again.

The default_md key in the req section tells OpenSSL which message digest algorithm to use to sign the key. Since we specified MD5 as the algorithm to use when signing new certificates and CRLs, we’ll use the same algorithm here for consistency. The SHA1 algorithm is actually a stronger algorithm and would be preferable, but for the sake of this example, we’ve chosen MD5 because it is more widely used and all but guaranteed to be supported by any software that could possibly be using our certificates. If you will be using only software that you know supports SHA1 with your certificates, we recommend that you use SHA1 instead of MD5.

The prompt and distinguished_name keys determine how OpenSSL gets the information it needs to fill in the certificate’s distinguished name. By setting prompt to no, we’re telling OpenSSL that it should get the information from the section named by the distinguished_name key. The default is to prompt for the information, so we must explicitly turn prompting off here. The keys in the distinguished_name section that we’ve defined by the name of root_ca_distinguished_name are the names of the fields making up the distinguished name, and the values are the values that we want placed in the certificate for each field. We’ve included only the distinguished name fields that we previously configured as required and omitted the one optional field.

Finally, the x509_extensions key specifies the name of a section that contains the extensions that we want included in the certificate. The keys in the section we’ve named root_ca_extensions are the names of the extension fields that we want filled in, and the values are the values we want them filled in with. We discussed the basicConstraints key earlier in this chapter. We’ve set the cA component of the extension to true, indicating that this certificate is permitted to act as a CA to sign both certificates and CRLs.

Now that we have the configuration set up for generating our self-signed root certificate, it’s time to actually create the certificate and generate a new key pair to go along with it. The options required on the command line are minimal because we’ve specified most of the options that we want in the configuration file. From the root directory of the CA, /opt/exampleca, or whatever you’ve used on your system, execute the following command. Make sure that you’ve set the OPENSSL_CONF environment variable first so that OpenSSL can find your configuration file!

# openssl req -x509 -newkey rsa -out cacert.pem -outform PEM

When you run the command, OpenSSL prompts you twice to enter a passphrase to encrypt your private key. Remember that this private key is a very important key, so choose your passphrase accordingly. If this key is compromised, the integrity of your CA is compromised, which essentially means that any certificates issued, whether they were issued before the key was compromised or after, can no longer be trusted. The key will be encrypted with 3DES, using a key derived from your passphrase. Example 3-5 shows the results of the command we just generated followed by a textual dump of the resulting certificate. Although your certificate will be different because your public and private key will be different from ours, your output should look similar.

Example 3-5. Output from generating a self-signed root certificate
# openssl req -x509 -newkey rsa -out cacert.pem -outform PEM
 
Using configuration from /opt/exampleca/openssl.cnf
Generating a 1024 bit RSA private key
..................................................++++++
.........++++++
writing new private key to '/opt/exampleca/private/cakey.pem'
Enter PEM pass phrase:
Verifying password - Enter PEM pass phrase:
-----
# openssl x509 -in cacert.pem -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 0 (0x0)
        Signature Algorithm: md5WithRSAEncryption
        Issuer: CN=Example CA, ST=Virginia, C=US/Email=ca@exampleca.org, 
O=Root 
Certificate Authority
        Validity
            Not Before: Jan 13 10:24:19 2002 GMT
            Not After : Jan 13 10:24:19 2003 GMT
        Subject: CN=Example CA, ST=Virginia, C=US/Email=ca@exampleca.org, 
O=Root 
Certificate Authority
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:cb:4f:55:6c:a4:2c:8a:f4:21:44:ec:fc:ca:9f:
                    ca:c7:43:2f:14:7d:07:1a:05:e7:3f:08:6c:ee:88:
                    30:ef:5b:24:6c:90:59:a2:81:af:99:bc:f6:94:96:
                    ab:48:53:98:b3:13:b2:42:aa:01:31:7d:59:0d:9a:
                    99:dc:95:b8:c2:0a:fc:b5:d0:d1:7a:5c:db:87:a3:
                    e0:db:8a:3f:c3:10:40:b5:d5:e9:5f:58:8d:fd:f1:
                    06:65:e2:73:7a:17:7f:98:ac:6f:b5:be:56:e1:5f:
                    16:2b:43:02:60:d8:80:b7:7e:0e:d4:48:3e:6a:c9:
                    2d:a6:02:3d:b0:e1:ac:fc:3d
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:TRUE
    Signature Algorithm: md5WithRSAEncryption
        2e:54:2c:cf:d8:1a:d0:bc:bb:9d:eb:3e:2f:fa:8b:7b:21:ef:
        4f:30:0e:93:6c:85:26:8d:c2:62:69:49:7b:55:26:09:6a:ea:
        00:bc:a0:03:ab:5b:45:8a:71:eb:39:46:6c:50:29:4b:00:ff:
        19:a1:e8:a2:4a:75:07:79:50:f0:38:6d:d2:20:09:63:48:75:
        67:6b:59:41:74:ae:63:69:13:4e:27:6b:5d:7e:55:6a:7b:3c:
        86:c8:b2:c5:15:01:e3:68:08:ec:3c:8a:00:68:43:ce:43:f0:
        76:e2:e2:97:ad:88:08:bf:87:ec:ba:d1:db:fa:c4:91:fb:b6:
        33:95

You’ll notice in Example 3-5’s output that when OpenSSL displays a DN in a shortened form, it uses a nonstandard representation that can be somewhat confusing. In this example, we see C=US/Email=ca@exampleca.org as an example of this representation. What’s confusing here is the slash separating the two fields. The reason for this is that the Email and O fields are nonstandard in a DN. OpenSSL lists the standard fields first and the nonstandard fields second, separating them with a slash.

Issuing Certificates

Everything is now set up for our CA, and it’s time to take it out for a test drive by issuing a certificate. To do that, we need a certificate request. It’s also a good idea to know how to create a certificate request that your CA will be able to use. Unless you plan to create both the certificate requests and certificates for anybody you’ll be issuing a certificate to, you’ll probably need to be able to tell someone how to give you a certificate request that you can use. Either way, you’ll still need to know how to do it yourself.

To create a certificate request, start with a clean shell without the OPENSSL_CONF environment variable set so that the default configuration file is used. We don’t want to use our custom configuration file to do this, as that configuration file is intended for use only by the CA, and generating a certificate request is not at all a function of a CA.

The command to generate a certificate request is similar to the command we used to create our self-signed root certificate. We use the command-line tool’s req command, but we’ll need to specify some extra parameters. The operation will be much more interactive, prompting for information to fill in the certificate request’s distinguished name. Example 3-6 shows the output from generating a certificate request.

Example 3-6. Generating a certificate request
# openssl req -newkey rsa:1024 -keyout testkey.pem -keyform PEM
 -out testreq.pem -outform PEM
Using configuration from /usr/share/ssl/openssl.cnf
Generating a 1024 bit RSA private key
.........++++++
.........++++++
writing new private key to 'testkey.pem'
Enter PEM pass phrase:
Verifying password - Enter PEM pass phrase:
-----
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]:US
State or Province Name (full name) [Some-State]:Virginia
Locality Name (eg, city) []:Manassas
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Test Request     
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:www.exampleca.org
Email Address []:ca@exampleca.org   
 
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:cloud noon sundry presto madrid baker
An optional company name []:Examples-R-Us, Inc.

The result of this command is the creation of two files: testreq.pem and testkey.pem. The former, testreq.pem, contains the certificate request as shown in Example 3-7, and testkey.pem contains the private key that matches the public key embedded in the certificate request. As part of the process to generate a certificate request, a new key pair was also generated. The first passphrase that is prompted for is the passphrase used to encrypt the private key. The challenge phrase is stored in the certificate request, and is otherwise ignored by OpenSSL. Some CAs may make use of it, however.

Example 3-7. The resulting certificate request
# openssl req -in testreq.pem -text -noout
Using configuration from /usr/share/ssl/openssl.cnf
Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: C=US, ST=Virginia, L=Manassas, O=Test Request, 
CN=www.exampleca.org/Email=ca@exampleca.org
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:d8:a5:1b:c6:b6:e4:75:bf:f3:e3:ce:29:1d:ab:
                    e2:5b:0d:bb:2e:94:de:52:a1:20:51:b1:77:d9:42:
                    a3:6c:26:1f:c3:3e:58:8f:91:b1:b3:ed:bd:7c:62:
                    1c:71:05:3b:47:ff:1a:de:98:f3:b4:a6:91:fd:91:
                    26:db:41:76:85:b5:10:3f:c2:10:04:26:4f:bc:03:
                    39:ff:b9:42:d0:d3:2a:89:db:91:8e:75:6d:f5:71:
                    ec:96:e8:d6:03:29:8e:fe:20:3f:5d:d8:cb:14:5e:
                    e5:64:fc:be:fa:d1:27:42:b6:72:eb:b4:16:16:71:
                    77:d3:0e:8c:cc:87:16:fc:41
                Exponent: 65537 (0x10001)
        Attributes:
            unstructuredName         :drowssap egnellahc
            challengePassword        :drowssap egnellahc
    Signature Algorithm: md5WithRSAEncryption
        25:aa:ca:78:64:fa:29:46:cf:dc:df:d9:95:dd:48:24:bf:4f:
        7b:7e:f4:09:76:96:c4:c5:b1:10:9b:64:95:19:30:8d:cd:d0:
        da:ac:b2:21:5e:34:e6:be:7b:41:52:2c:b3:e7:d4:dc:99:e5:
        a0:c2:46:12:9f:ef:99:0e:03:89:c1:f9:db:0d:0d:21:1b:e2:
        da:4e:23:ef:c1:aa:1b:24:b5:ce:53:a1:05:08:6e:4a:85:78:
        6e:71:ef:bc:36:48:5c:3e:ee:b1:bb:28:f4:31:df:23:a9:89:
        96:35:1b:b4:01:f9:63:4d:46:b4:ed:5d:be:1d:28:50:1c:86:
        43:5e

With a certificate request now in hand, we can use our CA to issue a certificate. For the sake of convenience in this example, the certificate request that we’ll be using, testreq.pem, which we just created, should be in the CA’s root directory. Make sure that the OPENSSL_CONF variable is set to the CA’s configuration file, and issue the command to generate a certificate, as shown in Example 3-8.

Example 3-8. Issuing a certificate from a certificate request
# openssl ca -in testreq.pem
Using configuration from /opt/exampleca/openssl.cnf
Enter PEM pass phrase:
Check that the request matches the signature
Signature ok
The Subjects Distinguished Name is as follows
countryName           :PRINTABLE:'US'
stateOrProvinceName   :PRINTABLE:'Virginia'
localityName          :PRINTABLE:'Manassas'
organizationName      :PRINTABLE:'Test Request'
commonName            :PRINTABLE:'www.exampleca.org'
emailAddress          :IA5STRING:'ca@exampleca.org'
Certificate is to be certified until Jan 14 04:31:25 2003 GMT (365 days)
Sign the certificate? [y/n]:y
 
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)
        Signature Algorithm: md5WithRSAEncryption
        Issuer: CN=Example CA, ST=Virginia, C=US/Email=ca@exampleca.org, 
O=Root 
Certificate Authority
        Validity
            Not Before: Jan 14 04:58:29 2002 GMT
            Not After : Jan 14 04:58:29 2003 GMT
        Subject: CN=www.exampleca.org, ST=Virginia, 
C=US/Email=ca@exampleca.org, O=Test Request
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:d8:a5:1b:c6:b6:e4:75:bf:f3:e3:ce:29:1d:ab:
                    e2:5b:0d:bb:2e:94:de:52:a1:20:51:b1:77:d9:42:
                    a3:6c:26:1f:c3:3e:58:8f:91:b1:b3:ed:bd:7c:62:
                    1c:71:05:3b:47:ff:1a:de:98:f3:b4:a6:91:fd:91:
                    26:db:41:76:85:b5:10:3f:c2:10:04:26:4f:bc:03:
                    39:ff:b9:42:d0:d3:2a:89:db:91:8e:75:6d:f5:71:
                    ec:96:e8:d6:03:29:8e:fe:20:3f:5d:d8:cb:14:5e:
                    e5:64:fc:be:fa:d1:27:42:b6:72:eb:b4:16:16:71:
                    77:d3:0e:8c:cc:87:16:fc:41
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
    Signature Algorithm: md5WithRSAEncryption
        13:33:75:8e:a4:05:9b:76:de:0b:d0:98:b8:86:2a:95:5a:13:
        0b:14:c7:48:83:f3:95:0e:3e:bf:76:04:f7:ab:ae:cc:cd:76:
        ae:32:77:ea:8c:96:60:28:52:4e:89:c5:ed:85:68:47:68:95:
        74:53:9f:dc:64:95:62:1a:b0:21:09:76:75:14:25:d4:fd:17:
        de:f9:87:7f:d5:dc:e4:41:1e:ad:f6:7b:2d:bf:a6:8a:cd:65:
        60:3b:71:74:bc:4d:0d:94:5a:22:c4:35:de:b0:19:46:f3:c1:
        bb:c5:e0:d4:f7:a2:92:65:ec:40:4c:cc:d4:b7:a3:84:bd:a9:
        b0:86
-----BEGIN CERTIFICATE-----
MIICcjCCAdugAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MRMwEQYDVQQDEwpFeGFt
cGxlIENBMREwDwYDVQQIEwhWaXJnaW5pYTELMAkGA1UEBhMCVVMxHzAdBgkqhkiG
9w0BCQEWEGNhQGV4YW1wbGVjYS5vcmcxIzAhBgNVBAoTGlJvb3QgQ2VydGlmaWNh
dGUgQXV0aG9yaXR5MB4XDTAyMDExNDA0NTgyOVoXDTAzMDExNDA0NTgyOVowdDEa
MBgGA1UEAxMRd3d3LmV4YW1wbGVjYS5vcmcxETAPBgNVBAgTCFZpcmdpbmlhMQsw
CQYDVQQGEwJVUzEfMB0GCSqGSIb3DQEJARYQY2FAZXhhbXBsZWNhLm9yZzEVMBMG
A1UEChMMVGVzdCBSZXF1ZXN0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDY
pRvGtuR1v/Pjzikdq+JbDbsulN5SoSBRsXfZQqNsJh/DPliPkbGz7b18YhxxBTtH
/xremPO0ppH9kSbbQXaFtRA/whAEJk+8Azn/uULQ0yqJ25GOdW31ceyW6NYDKY7+
ID9d2MsUXuVk/L760SdCtnLrtBYWcXfTDozMhxb8QQIDAQABow0wCzAJBgNVHRME
AjAAMA0GCSqGSIb3DQEBBAUAA4GBABMzdY6kBZt23gvQmLiGKpVaEwsUx0iD85UO
Pr92BPerrszNdq4yd+qMlmAoUk6Jxe2FaEdolXRTn9xklWIasCEJdnUUJdT9F975
h3/V3ORBHq32ey2/porNZWA7cXS8TQ2UWiLENd6wGUbzwbvF4NT3opJl7EBMzNS3
o4S9qbCG
-----END CERTIFICATE-----
Data Base Updated

The first thing that happens is OpenSSL asks for a passphrase. The passphrase that it is looking for is not the passphrase for the certificate request, but the passphrase for the CA’s private key. The private key will be used to sign the new certificate. After displaying the subject’s distinguished name, OpenSSL prompts you for confirmation to sign the certificate. Since certificate requests are likely to come from people needing certificates from you, you should check to be sure that the information they’ve provided in their certificate requests is correct before issuing the certificate. The next and final prompt is to confirm whether the certificates should be committed to the CA’s database. Finally, the new certificate will be written to stdout, and the command is finished.

The confirmation prompts that are issued can be suppressed and automatically answered in the affirmative by adding the batch option. This is useful if you’re building a wrapper around the OpenSSL command-line tool, or if you’ve already manually verified the information in the request and you don’t want to be prompted. It’s also possible to issue multiple certificates for multiple certificate requests all with one command. For example, suppose you have three certificate requests that need to have certificates issued. The infiles option can be used instead of the in option; the list of files to be processed follows immediately after it. If you use the infiles option, be aware that it must be the last option specified; everything after it is treated as an input filename.

The resulting certificate is also written to the directory that we specified in our configuration file with the new_certs_dir key. It’s written out in PEM format and given a filename composed of the certificate’s serial number and an extension of .pem. The output of the certificate to stdout when it is created can be suppressed by using the notext option. Using the out option, the name of a file to write the certificate to can be specified. We recommend that you also use the notext option if you use the out option. The result will be a file containing a certificate that is identical to the one written to the new_certs_dir directory, /opt/exampleca/certs in our example. If you use the out option, it’ll save you having to search through all of the certificates that you’ve issued and pick the highest numbered among them to pass on to their owners.

After the command has completed and the certificate has been issued, you should see a new file in the subdirectory certs that we created. This file is the certificate that was issued. You should also be able to see that information was added to the file index.txt, OpenSSL’s CA database. Finally, you should be able to see that the serial number in the file serial was incremented. When you look at the text dump of the certificate that was created, you’ll notice that it was assigned a serial number of “1”, the number that we used to seed the serial number file.

Revoking Certificates

The first certificate that we issued with our CA was simply a test certificate to make sure that the CA is working properly. We can see that the certificate was issued properly, but it’s a certificate that we don’t actually want anybody to be able to use, so we will need to revoke the certificate. This provides us with an excellent opportunity to find out how certificate revocation works using OpenSSL’s CA command.

Revoking a certificate is a simple process. All you need is a copy of the certificate to be revoked. Even if you don’t keep a copy of all of the certificates that you’ve issued, the CA infrastructure we created does. We can obtain a copy of the certificate that way, but it’s much easier to keep a copy of your own and name the file something meaningful since the CA simply names the file containing the certificates it issues with each certificate’s serial number. Using the command in the example from the last section to create the test certificate, we didn’t keep a copy for ourselves, but we issued only a single certificate, so it’s quite easy to get a copy of the certificate file. We’ll make a copy of that certificate file in the CA’s root directory and call it testcert.pem. Then we’ll use that file as the certificate required by the revoke option to the ca command (see Example 3-9).

Example 3-9. Revoking a certificate
# cp certs/01.pem testcert.pem
# openssl ca -revoke testcert.pem
Using configuration from /opt/exampleca/openssl.cnf
Enter PEM pass phrase:
Revoking Certificate 01.
Data Base Updated

Once again, the command-line tool prompts us for a passphrase. The passphrase it is looking for is the passphrase that protects the CA’s private key. Although the key is not actually used for any signing as part of the certificate revocation process, it is required to validate the certificate as the CA’s own and as a security measure to ensure that only someone authorized to use the CA can revoke a certificate that it has issued.

No change is made to the certificate at all. In fact, the only noticeable change is to the CA’s database to indicate that the certificate has been revoked. Remember that once a certificate has been issued, it cannot be modified. It’s presumably out in the wild and there’s no way to ensure that every copy of the certificate in existence can be updated. This is where CRLs become relevant. We’ve revoked the first certificate that we issued with our CA, but the only entity that is aware of the revocation is the CA itself. By itself, this doesn’t do anybody any good. Anybody that might be using the certificate also needs to know that the certificate has been revoked, so we need to issue a CRL.

When we issue our first CRL, we set the initial policy for how frequently we’ll be issuing CRLs. In our configuration, we’ve indicated that we’ll issue them once a week. When a CRL is made available, it contains a field that indicates the next time a new one will be published. In other words, each CRL is given an expiration date, and a new one must be obtained once the current one expires. Whether there are any new certificate revocations, a new CRL should be generated when the old one expires.

While CRLs should be published on a regularly scheduled periodic basis, it is also possible to generate and publish CRLs when a new one is needed. In fact, it’s good practice to do so. Consider that not all software may cache the CRLs that it retrieves, particularly if they’re retrieved automatically. It’s also possible that the current CRL was most likely not retrieved by everyone that may be using certificates issued by your CA. Therefore, it’s best to make the information as current as possible rather than waiting until the current CRL expires, especially if the period between issuance is large.

Issuing a CRL before a new one is due means there are possibly two or more CRLs from your CA in distribution, but that’s fine. CRLs usually have only data added to them, and any time data is removed, it’s because the revoked certificate has expired, and thus its revocation status is irrelevant. Some CAs may opt to keep even expired certificates in their CRLs. While this may not be a bad idea for a short period of time after a certificate expires, it’s generally not a good idea to keep the information indefinitely; otherwise, the CRL could grow to be quite large and make distribution of it more costly in terms of both time and bandwidth.

Without any further ado, let’s issue our first CRL. This is done by issuing a simple ca command using the gencrl option, along with an out option to specify the name of the file to write the resultant CRL to (see Example 3-10). OpenSSL prompts us for the passphrase protecting the CA’s private key, which it will use to sign the CRL that it generates.

The command completes without writing anything to stdout indicating success, but if there is a problem, an appropriate error message will be written. We can see that the command completed successfully by noting that the file we specified with the -out option has been written. With that file, we can use the command-line tool’s crl command to investigate the details of the CRL that we just generated.

Example 3-10. A certificate revocation list
# openssl ca -gencrl -out exampleca.crl
Using configuration from /opt/exampleca/openssl.cnf
Enter PEM pass phrase:
# openssl crl -in exampleca.crl -text -noout
Certificate Revocation List (CRL):
        Version 1 (0x0)
        Signature Algorithm: md5WithRSAEncryption
        Issuer: /CN=Example CA/ST=Virginia/C=US/Email=ca@exampleca.org/O=Root 
Certificate Authority
        Last Update: Jan 14 05:42:08 2002 GMT
        Next Update: Jan 21 05:42:08 2002 GMT
Revoked Certificates:
    Serial Number: 01
        Revocation Date: Jan 14 05:16:43 2002 GMT
    Signature Algorithm: md5WithRSAEncryption
        32:73:3b:e5:b4:f6:2d:57:58:15:e8:87:05:23:27:c3:5d:e5:
        10:a0:5d:1d:09:68:27:b8:8c:70:5c:5d:4a:0d:07:ff:63:09:
        2d:df:61:13:7b:ea:5a:49:74:3b:0a:e9:2b:2d:92:3e:4d:c6:
        f4:4f:18:fa:c9:9e:f7:bb:92:b5:ed:46:14:a1:c2:25:5d:3f:
        9d:5a:b4:c9:63:5f:06:fc:04:22:0b:80:aa:fd:77:a5:16:9d:
        36:47:f7:e9:5b:95:16:ff:bb:e6:db:98:3c:2a:aa:bd:4f:91:
        eb:20:86:44:09:7f:ef:62:69:ef:db:1e:79:7e:24:70:72:34:
        cf:1e
# openssl crl -in exampleca.crl -noout -CAfile cacert.pem
verify OK

When we get a text dump of the CRL, we can see the algorithm that was used to sign it, the CA that issued it, when it was issued, when the next list will be issued, and a list of all of the certificates that it contains. We can also use the crl command to verify the signature on the CRL. Doing so requires us to have a copy of the certificate that was used to sign it.

We can see in Example 3-10 that the version of the CRL that was generated was Version 1. By default, this is what OpenSSL will produce unless the crl_extensions key is specified in the configuration file in the ca section. We strongly recommend that you produce only Version 1 CRLs, unless you can be sure all of the software you’re using with your certificates supports Version 2. If it’s important that the software that supports Version 2 CRLs get them, you can produce both Version 1 and Version 2 lists.

Note that you are essentially on your own when it comes to publishing CRLs. One reasonable solution is to make CRLs available to all via secure HTTP.



[1] As we mentioned in Chapter 1, this is technically the job of an RA instead of a CA, but the CA generally deals with the RA transparently.