Introducing SSL and Certificates using SSLeay

Frederick J. Hirsch
The Open Group Research Institute

Published in World Wide Web Journal, Summer 1997


Security is important on the Web. Whether sharing financial, business, or personal information, people want to know with whom they are communicating (authentication), they want to ensure that what is sent is what is received (integrity), and they want to prevent others from intercepting what they are communicating (privacy). The Secure Sockets Layer protocol [13] provides one means for achieving these goals and is the subject of this article. We introduce SSL by reviewing cryptographic techniques and by discussing certificates. We then describe SSL and packages for implementing SSL. We conclude with examples of how to use SSLeay, the free implementation of SSL by Eric Young. We use the SSLeay toolkit to create a Certificate Authority, as well as server and client certificates.

1. Introduction

An introduction to SSL, this article is aimed at readers who are familiar with the Web, HTTP, and Web servers, but are not security experts. It is not intended to be a definitive guide to the SSL protocol, nor does it discuss specific servers, techniques for managing certificates in an organization, or the important legal issues of patents and import and export restrictions *. Rather, this article guides users in implementing SSL, and pulls together various concepts, definitions, and examples as a starting point for further exploration.

2. Cryptographic Techniques

Understanding SSL requires an understanding of cryptographic algorithms, message digest functions, and digital signatures. These techniques are the subject of entire books [8], and provide the basis for privacy, integrity, and authentication.

Cryptographic Algorithms

Suppose Alice wants to send a message to her bank to transfer some money. Alice would like the message to be private, since it will include information such as her account number and transfer amount. One solution is to use a cryptographic algorithm, a technique that would transform her message into an encrypted form, unreadable except by those it is intended for. Once in this form, the message may only be interpreted through the use of a secret key. Without the key the message is useless: good cryptographic algorithms make it so difficult for intruders to decode the original text that it isn't worth their effort.

There are two categories of cryptographic algorithms: conventional and public key.

Message Digests

Although Alice may encrypt her message to make it private, there is still a concern that someone might modify her original message message or substitute it with a different one, in order to transfer the money to themselves, for instance. One way of guaranteeing the integrity of Alice's message is to create a concise summary of her message and send this to the bank as well. Upon receipt of the message, the bank creates its own summary and compares it with the one Alice sent. If they agree then the message was received intact.

A summary such as this is called a message digest, or one-way hash. Message digests are used to create short, fixed-length representations of longer, variable-length messages. Digest algorithms are designed to produce unique digests for different messages. Message digests are designed to make it too difficult to determine the message from the digest, and also impossible to find two different messages which create the same digest -- thus eliminating the possibility of substituting one message for another while maintaining the same digest.

Another challenge that Alice faces is finding a way to send the digest to the bank securely; when this is achieved, the integrity of the associated message is assured. One way to to this is to include the digest in a digital signature.

Digital Signatures

When Alice sends a message to the bank, the bank needs to ensure that the message is really from her, so an intruder does not request a transaction involving her account. A digital signature, created by Alice and included with the message, serves this purpose **.

Digital signatures are created by encrypting a digest of the message, and other information (such as a sequence number) with the sender's private key. Though anyone may decrypt the signature using the public key, only the signer knows the private key. This means that only they may have signed it. Including the digest in the signature means the signature is only good for that message; it also ensures the integrity of the message since no one can change the digest and still sign it. To guard against interception and reuse of the signature by an intruder at a later date, the signature contains a unique sequence number. This protects the bank from a fraudulent claim from Alice that she did not send the message -- only she could have signed it (non-repudiation).

3. Certificates

Although Alice could have sent a private message to the bank, signed it, and ensured the integrity of the message, she still needs to be sure that she is really communicating with the bank. This means that she needs to be sure that the public key she is using corresponds to the bank's private key. Similarly, the bank also needs to verify that the message signature really corresponds to Alice's signature. If each party has a certificate which validates the other's identity, confirms the public key, and is signed by a trusted agency, then they both will be assured that they are communicating with whom they think they are. Such a trusted agency is called a Certificate Authority, and certificates are used for authentication.

Certificate Contents

A certificate associates a public key with the real identity of an individual, server, or other entity, known as the subject. As shown in Table 1, information about the subject includes identifying information (the distinguished name), and the public key. It also includes the identification and signature of the Certificate Authority that issued the certificate, and the period of time during which the certificate is valid. It may have additional information (or extensions) as well as administrative information for the Certificate Authority's use, such as a serial number.

Table 1: Certificate Information
Subject Distinguished Name, Public Key
Issuer Distinguished Name, Signature
Period of Validity Not Before Date, Not After Date
Administrative Information Version, Serial Number
Extended Information

A distinguished name is used to provide an identity in a specific context -- for instance, an individual might have a personal certificate as well as one for their identity as an employee. Distinguished names are defined by the X.509 standard [2], which defines the fields, field names, and abbreviations used to refer to the fields (Table 2).

Table 2: Distinguished Name Information
FieldAbbreviationDescription Example
Common NameCN Name being certifiedCN=Frederick Hirsch
Organization or CompanyO Name is associated with this
O=The Open Group
Organizational UnitOU Name is associated with this
organization unit, such as a department
OU=Research Institute
City/LocalityL Name is located in this CityL=Cambridge
State/ProvinceSP Name is located in this State/Province SP=Massachusetts
CountryC Name is located in this Country
(ISO code)

A Certificate Authority may define a policy specifying which distinguished field names are optional, and which are required. It may also place requirements upon the field contents, as may users of certificates. As an example, a Netscape browser requires that the Common Name for a certificate representing a server have a name which matches a regular expression for the domain name of that server, such as *

The binary format of a certificate is defined using the ASN.1 notation [ 1], [4]. This notation defines how to specify the contents, and encoding rules define how this information is translated into binary form. The binary encoding of the certificate is defined using Distinguished Encoding Rules (DER), which are based on the more general Basic Encoding Rules (BER). For those transmissions which cannot handle binary, the binary form may be translated into an ASCII form by using base64 encoding. This encoded version is called PEM encoded, when placed between the following lines:


Certificate Authorities

By first verifying the information in a certificate request before granting the certificate, the Certificate Authority assures the identity of the private key owner of a key-pair. For instance, if Alice requests a personal certificate, the Certificate Authority must first make sure that Alice really is the person the certificate request claims.

Certificate Chains

A Certificate Authority may also issue a certificate for another Certificate Authority. When examining a certificate, Alice may need to examine the certificate of the issuer, for each parent Certificate Authority, until reaching one which she has confidence in. She may decide to trust only certificates with a limited chain of issuers, to reduce her risk of a "bad" certificate in the chain.

Creating a Root Level Certificate Authority

As noted earlier, each certificate requires an issuer to assert the validity of the identity of the certificate subject, up to the top-level Certificate Authority. This presents a problem: Since this is who vouches for the certificate of the top-level authority, which has no issuer? In this unique case, the certificate is "self-signed", so the issuer of the certificate is the same as the subject. As a result, one must exercise extra care in trusting a self-signed certificate. The wide publication of a public key by the root authority reduces the risk in trusting this key -- it would be obvious if someone else publicized a key claiming to be the authority. Browsers are preconfigured to trust well-known certificate authorities.

A number of companies, such as VeriSign [11] have established themselves as certificate authorities. These companies provide the following services:

It is also possible to create your own Certificate Authority. Although risky in the Internet environment, it may be useful within an Intranet where the organization can easily verify the identities of individuals and servers.

Certificate Management

Establishing a Certificate Authority is a responsibility which requires a solid administrative, technical, and management framework. Certificate Authorities not only issue certificates, they also manage them -- that is, they determine how long certificates are valid, they renew them, and they keep lists of certificates that have already been issued but are no longer valid (certificate revocation lists, or CRLs). Say Alice is entitled to a certificate as an employee of a company. Say too, that the certificate needs to be revoked when Alice leaves the company. Since certificates are objects that get passed around, it is impossible to tell from the certificate alone that it has been revoked. When examining certificates for validity, therefore, it is necessary to contact the issuing Certificate Authority to check CRLs -- this is not usually an automated part of the process.

If you use a Certificate Authority that is not configured into browsers by default, it is necessary to load the Certificate Authority certificate into the browser, enabling the browser to validate server certificates signed by that Certificate Authority. Doing so may be dangerous, since once loaded, the browser will accept all certificates signed by that Certificate Authority.

4. SSL

The Secure Sockets Layer protocol (SSL) is a protocol layer which may be placed between a reliable connection-oriented network layer protocol (e.g. TCP/IP) and the application protocol layer (e.g. HTTP). SSL provides for secure communication between client and server by allowing mutual authentication, the use of digital signatures for integrity, and encryption for privacy.

The protocol is designed to support a range of choices for specific algorithms used for cryptography, digests, and signatures. This allows algorithm selection for specific servers to be made based on legal, export or other concerns, and also enables the protocol to take advantage of new algorithms. Choices are negotiated between client and server at the start of establishing a protocol session.

There are a number of versions of the SSL protocol, as shown in Table 3.

Table 3: Versions of SSL
Version Source Description Browser Support

SSL 2.0 published by Netscape [12] Original protocol Netscape 3.0, Internet Explorer 3.0

SSL 3.0 Expired Internet Draft [13] Revisions to prevent specific security attacks, add ciphers, and support certificate chains Netscape 3.0, Internet Explorer 3.0

TLS 2.0 IETF Draft [15] Revision of SSL 3.0 None

As noted in Table 3, one of the benefits in SSL 3.0 is that it adds support of certificate chain loading. This feature allows a server to pass a server certificate along with issuer certificates to the browser. Chain loading also permits the browser to validate the server certificate, even if Certificate Authority certificates are not installed for the intermediate issuers, since they are included in the certificate chain. SSL 3.0 is the basis for the Transaction Layer Security [TLS] protocol standard, currently in development by the Internet Engineering Task Force (IETF).

Session Establishment

The SSL session is established by following a handshake sequence between client and server, as shown in Figure 1. This sequence may vary, depending on whether the server is configured to provide a server certificate or request a client certificate. Though cases exist, where additional handshake steps are required for management of cipher information, this article summarizes one common scenario: see the SSL specification for the full range of possibilities.

Once an SSL session has been established it may be reused, thus avoiding the performance penalty of repeating the many steps needed to start a session.

The elements of the handshake sequence, as used by the client and server, are listed below:

  1. Negotiate the Cipher Suite to be used during data transfer
  2. Establish and share a session key between client and server
  3. Optionally authenticate the server to the client
  4. Optionally authenticate the client to the server

Figure 1: Simplified Handshake Sequence

The first step, Cipher Suite Negotiation, allows the client and server to choose a Cipher Suite supportable by both of them. The SSL3.0 protocol specification defines 31 Cipher Suites. A Cipher Suite is defined by the following components:

These three elements are described in the sections that follow.

Key Exchange Method

The key exchange method defines how the shared secret symmetric cryptography key used for application data transfer will be agreed upon by client and server. SSL 2.0 uses RSA key exchange, while SSL 3.0 supports a choice of key exchange algorithms including the RSA key exchange when certificates are used, and Diffie-Hellman key exchange for exchanging keys without certificates and without prior communication between client and server [5].

One variable in the choice of key exchange methods is digital signatures -- whether or not to use them, and if so, what kind of signatures to use. Signing with a private key provides assurance against a man-in-the-middle-attack during the information exchange used in generating the shared key [8, p516].

Cipher for Data Transfer

SSL uses the conventional cryptography algorithm (symmetric cryptography) described earlier for encrypting messages in a session. There are nine choices, including the choice to perform no encryption: "CBC" refers to Cipher Block Chaining, which means that a portion of the previously encrypted cipher text is used in the encryption of the current block. "DES" refers to the Data Encryption Standard [8, ch12], which has a number of variants (including DES40 and 3DES_EDE). "Idea" is one of the best and cryptographically strongest available algorithms, and "RC2" is a proprietary algorithm from RSA [8, ch13].

Digest Function

The choice of digest function determines how a digest is created from a record unit. SSL supports the following:

The message digest is used to create a Message Authentication Code (MAC) which is encrypted with the message to provide integrity and to prevent against replay attacks.

Handshake Sequence Protocol

The handshake sequence uses three protocols: These protocols, as well as application protocol data, are encapsulated in the "SSL Record Protocol", as shown in Figure 2. An encapsulated protocol is transferred as data by the lower layer protocol, which does not examine the data. The encapsulated protocol has no knowledge of the underlying protocol.

Figure 2: SSL Protocol Stack

The encapsulation of SSL control protocols by the record protocol means that if an active session is renegotiated the control protocols will be transmitted securely. If there were no session before, then the NULL cipher suite is used, which means there is no encryption and messages have no integrity digests until the session has been established.

Data Transfer

The SSL Record Protocol, shown in Figure 3, is used to transfer application and SSL Control data between the client and server, possibly fragmenting this data into smaller units, or combining multiple higher level protocol data messages into single units. It may compress, attach digest signatures, and encrypt these units before transmitting them using the underlying reliable transport protocol.

Figure 3: SSL Record Protocol

Securing Web HTTP Communication

One common use of SSL is to secure Web HTTP communication between a browser client and a Web server. This case does not preclude the use of non-secured HTTP. The secure version uses URLs that begin with https rather than http, and a different server port (by default 443). The browser will maintain client certificate private keys when they are generated, and display an indicator if a secure connection is being used.

Implementing SSL

Although one might write an SSL implementation from scratch following the specification, it is much easier to use one of the existing SSL toolkit libraries. In addition, because of patents, it is usually necessary to license some of the cryptography libraries, at least in the United States. SSL toolkits include encryption, message digest, and certificate management routines. Each also requires the use of a licensed public key package in the United States, from Security Dynamics (Originally available from the Public Key Partners [RFC1170] and then from RSA, which was acquired by Security Dynamics [17] .)

There are two prominent RSA public key packages available:

These two public key implementations include a complete toolkit of public key algorithms (including RSA encryption and Diffie-Hellman key exchange), symmetric encryption algorithms, and digest functions. They may be used with SSL Toolkits, the most prominent of which include the following:

6. SSLeay Examples

This section offers examples for creating a Certificate Authority, as well as requesting, signing, and using certificates with SSLeay. The Appendix offers brief instructions for installing SSLeay, establishing the SSLeay certificate environment, information on the SSLeay configuration file, and sample HTML pages and CGI scripts. SSLeay 0.6.6 supports SSL 2.0, and SSLeay-0.8.1 supports both SSL 2.0 and 3.0. SSL 2.0 is widely implemented and interoperation is easier than with SSL 3.0; we use SSLeay with SSL 2.0 in the examples that follow.

a. Creating a Self-Signed CA Certificate

The first step in creating a Certificate Authority (apart from designing the management, administrative and legal framework) is to create a self-signed certificate for the Certificate Authority. This is done in SSLeay by running the req command (see Example 5 in the Appendix). This command produces a certificate file (CAcert.pem) and key file (CAkey.pem). The CA certificate and key files must remain in $SSLDIR/private, which is where SSLeay will look for them by default (as specified in the ssleay.cnf CA default section), both when acting as a certificate authority, and also when used by the server to implement SSL and validate client certificates signed by the CA.

Install the self-signed certificate in a browser so the browser will recognize server certificates signed by the Certificate Authority. Installing a CA certificate in a browser is somewhat dangerous, unless you trust that certificate and the security of the Certificate Authority. Once installed, the browser accepts any certificate signed by that authority.

To install the CA certificate, load it using HTTP Content-Type application/x-x509-ca-cert. To do this in a manner which does not depend on the server, use the cgi-script (Example 6 in the Appendix), or save the certificate in a file with a cacert suffix and define this suffix in the server configuration file to correspond to the application/x-x509-ca-cert MIME type. For the Apache server, for example, add the line AddType application/x-x509-ca-cert cacert to srm.conf. The certificate and key files must also remain available to SSLeay for the server to be able to use the public key, and the certificate authority to use the private key.

b. Creating a Server Certificate

A server certificate authenticates the server to the client. To make a server certificate, create a certificate request, sign it with the self-signed CA certificate, and then install the certificate as follows:
  1. Use the "req" command to create a new certificate request with SSLeay (See Example 8 in the Appendix). This command creates files containing a certificate request and the private key.
  2. Sign the request using the "ca" command (see Example 11 in the Appendix). This will produce a file containing the certificate.
  3. Copy the certificate and key files to the server certificate directories.
    cp newcert.pem $certdir/sitecert.pem
    cp newkey.pem $certdir/sitekey.pem
  4. Create hashes for the certificates in the server directory:
    CD $certdir
    ln -s sitecert.pem `$SSLDIR/bin/x509 -noout -hash < sitecert.pem`.0
  5. Create the DER format server certificate file:
    $SSLDIR/bin/x509 -in CAcert.pem -out CAcert.der -outform DER
  6. Update the server configuration file to specify that this is the server certificate to use.
In order to easily find certificates, SSLeay uses hashes of the certificate subject names. Thus, when looking for the certificate of the issuer of a certificate, it looks for a file named with the hash value of the issuer name. The avoids opening files and examining certificates to find a match. The SSLeay x509 command may be used to manipulate certificates; one option is to create a hash of the subject name.

Once these steps have been completed, an SSL connection may be established if the server does not require client certificates.

b. Creating a Client Certificate

A client certificate is used to authenticate a client to a server. Creating and installing a client certificate is more difficult than creating a server certificate because the client must generate a key-pair, keep the private key to itself, and send the public key to the certificate authority to be incorporated into a certificate request. Once a signed certificate has been created using the Certificate Authority, this client certificate must be installed in the client so that the client may present it when needed.

Different clients such as Netscape Navigator 3.01 Gold and Microsoft Internet Explorer 3.02 support different mechanisms for creating client certificates. In this section, we demonstrate a technique for creating and installing a client certificate for each, using SSLeay certificate routines to sign certificate requests (Back up the Windows NT registry before creating client certificates with Internet Explorer).

The procedure for creating a client certificate involves HTML forms; these forms include client specific features such as special tags or JavaScript programs, and Perl CGI scripts that call SSLeay certificate handling applications. The procedures do not rely on special server features, other than the ability to run Perl CGI scripts. The examples completely automate the process, causing a client certificate to be installed once the request form is submitted. (In a production environment the Certificate Authority would need to perform validation instead of automatically issuing the certificate.)

The general steps for creating a client certificate are as follows:

  1. User requests HTML page that displays form on client
  2. User enters identification information
  3. Submission of the form causes the following sequence to occur:
    1. Browser generates a key pair (public and private key)
    2. Private key is stored in browser
    3. Public key is sent with identification information to the server
    4. Server CGI script creates certificate and loads it into the client

The HTML form includes fields (containing defaults) for the different distinguished name attributes which are to be used in the client certificate, information allowing the browser to generate a key-pair, and a hidden field used to return this information to the CGI script. This hidden information is browser dependent.

In Netscape Navigator, the form contains an additional FORM tag, the <KEYGEN> tag. This tag creates a key pair, and causes the public key to be returned as a form value when the form is submitted (see Example 12 in the Appendix for source of a sample form). The <KEYGEN> tag causes the browser to display a choice of security grades, depending on the version of Navigator. All of the form information is used by the CGI script to create a certificate request, and this request is used to create a client certificate (See Figure 4).

Figure 4: Sample Netscape Navigator User Certificate Form
Sample Netscape Navigator User Certificate Form

The Microsoft Internet Explorer HTML form in Figure 5 is more complicated, because Internet Explorer requires a JavaScript (or Visual Basic) program in the page to use an ActiveX control to generate a key pair and create a certificate request. The JavaScript program is downloaded with the HTML page, and called when you press the Submit form button. The program calls the GenReqForm method of the certenr3 ActiveX control, passing it the distinguished name values from the form. The certificate request produced by the control is then loaded into a hidden field of the form, and returned with the form values to the server CGI script (see Example 15 in the Appendix for a sample HTML page).

Figure 5: Sample Internet Explorer User Certificate Form
Sample Internet Explorer User Certificate Form

Both Netscape Navigator and Microsoft Internet Explorer present a sequence of dialogs as part of the key-pair creation. If this sequence is successfully completed then the form will cause the server CGI script to be called with the data from the form. Examples 13 and 15 in the Appendix present two CGI scripts, one for each browser, since the processing is different.

The CGI script for Netscape Navigator (Example 14 in the Appendix) creates a file containing the distinguished name values returned by the form, and a special SPKAC value for the "Signed Public Key And Challenge" generated by Navigator The "ca" command is called with this file as an argument to generate a client certificate. If successful this is returned by the CGI script as an application/x-x509-user-cert HTTP Content-Type. Navigator recognizes this type, and prompts the user for the remainder of the steps required to install the user certificate in the browser. (See Example 13 for the sample CGI script for Netscape Navigator).

The CGI script for processing the Internet Explorer request (Example 16 in the Appendix) is more complicated. It takes the certificate request returned by the form and reformats it to conform to lines of length 72, and then uses the SSLeay ca command to create a signed user certificate based on this request. It then takes the client certificate and combines it with the SSLeay certificate revocation list (CRL) to create a PKCS#7 certificate using the SSLeay crl2pkcs7 utility. The CGI Perl script then dynamically creates an HTML page which includes a JavaScript program to call the AcceptCredentials method of the certenr3 ActiveX control to install the PKCS#7 certificate. This page is designed to take advantage of the JavaScript onLoad method to automatically call the JavaScript program when the page is loaded, so that the certificate is immediately installed without user interaction. (In a production system such automatic installation may not be desired.)

Although I was able to establish an SSL connection using client certificates with Netscape Navigator, and establish an SSL connection with a VeriSign client certificate and the VeriSign client certificate test page, I was unable to establish an SSL client-certificate connection using my client certificate with Microsoft Internet Explorer. The reason for this discrepancy will require more research or additional information from Microsoft.

Once the HTML forms and CGI scripts have been written, and the ActiveX control installed, the process of creating client certificates using SSLeay is simple for users.

Configuring a Server and Establishing an SSL connection

The server must have a server certificate installed, and the server's CA certificate must have been installed in the browser. The server will only request a client certificate from the browser if it is required in the server configuration file. Apache uses the following directive in httpd.conf :
# Set SSLVerifyClient to:
# 0 if no certificate is required
# 1 if the client may present a valid certificate
# 2 if the client must present a valid certificate
# 3 if the client may present a valid certificate but it is not required to
#   have a valid CA
SSLVerifyClient 0
An SSL connection is established by requesting a URL from the browser of the form "", where the domain refers to the server which supports SSL.


SSL uses encryption, message digests, digital signatures and certificates to implement a protocol layer for providing privacy, integrity and authentication to application protocols such as HTTP. This is valuable in the Web since it will allow a much greater degree of secure communication than is available without SSL. A number of toolkits exist for implementing SSL, including SSLeay. These toolkits also provide the facilities for creating ones own Intranet Certificate Authority and managing certificates. Many issues exist with respect to certificates, including those of certificate revocation and expiration, as well as management issues. Undoubtedly the remaining issues involved in the management of certificates and Web security will be addressed, but an implementation of SSL using SSLeay permits much more confidence in Web communications.


This appendix offers a number of examples for certificate management using SSLeay. The CGI scripts assume you are using Apache (tested with 1.2b7). If you have trouble it might be due to a version issue. The scripts in these examples also assume that the server installation directory includes the following subdirectories: When the scripts operate they create files containing certificate requests, and certificates.

SSLeay Installation

We have experimented using SSLeay and RSARef on UNIX with the Secure Domain Gateway, a special SSL web server that interfaces with the Distributed Computing Environment (DCE). We have also experimented using Apache-SSL (apache_1.2b10+ssl_1.6.tar). The following examples assume that you are building SSLeay under UNIX (e.g. HP-UX) but it is possible to build SSLeay on other platforms such as Windows NT. The SSLeay-0.8.1 distribution is obtained as a tar file (SSLeay-0.8.1.tar). Extracting from the tar file will create a new directory, SSLeay-0.8.1 in which SSLeay is built.

The following examples assume you are working in the SSLeay-0.8.1 directory. Change to this directory and build SSLeay following the directions in the INSTALL file. The examples assume that the results of building SSLeay are installed in $SSLDIR (e.g. /opt/dev/ssl).

SSLeay uses a configuration file (ssleay.cnf) which supports named sections, so one configuration file may be used for several purposes. We have modified this file, and show some of these modifications in the examples that follow. Subsequent descriptions in this document show various relevant sections of the log file.

Note that the addition of SSL to the server requires rebuilding the server to include the SSL toolkit and public key sources, and modifying the server configuration to support SSL.

The SSLeay Certificate Environment

Before using SSLeay, create an environment for managing certificates, update the SSLeay configuration file, and update the server configuration file. Establish the SSLeay certificate management environment using the sequence in Example 1.
Example 1: Establishing the SSLeay Certificate Environment

mkdir ${SSLDIR}/certs 
mkdir ${SSLDIR}/crl 
mkdir ${SSLDIR}/newcerts
mkdir ${SSLDIR}/private
echo "01" > ${SSLDIR}/serial
touch ${SSLDIR}/index.txt

The SSLeay Configuration File

The SSLeay configuration file (ssleay.cnf) has multiple sections. These configuration sections must be updated before the certificate authority may be used, especially the dir specification in the certificate authority configuration shown in Example 2. The dir specification value should be the same as $SSLDIR (e.g. /opt/dev/ssl).

Example 2 SSLeay Configuration File: ca section
[ ca ]
default_ca	= CA_default		# The default ca section

[ CA_default ]

dir		= /opt/dev/ssl		# Where everything is kept
certs		= $dir/certs		# Where the issued certs are kept
crl_dir		= $dir/crl			# Where the issued crl are kept
database		= $dir/index.txt		# database index file.
new_certs_dir	= $dir/newcerts		# default place for new certs.

certificate	= $dir/private/CAcert.pem 	# The CA certificate
serial		= $dir/serial 		# The current serial number
crl		= $dir/clr/crl.pem 		# The current CRL
private_key	= $dir/private/CAkey.pem	# The private key
RANDFILE		= $dir/private/.rand	# private random number file

x509_extensions		= x509v3_extensions	# The extentions to add to the cert
default_days		= 365		# how long to certify for
default_crl_days= 30			# how long before next CRL
default_md	= md5			# which md to use.
preserve	= no			# keep passed DN ordering

# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy		= policy_match

The "req" section of the configuration file is used when creating certificate requests, and supplies defaults and length limits for the various distinguished name fields. In our examples it has the configuration as shown in Example 3.

Example 3: SSLeay Configuration File: Request Section
[ req ]
default_bits		= 512
default_keyfile 	= privkey.pem
distinguished_name	= req_distinguished_name
attributes		= req_attributes

[ req_distinguished_name ]
countryName			= Country Name (2 letter code)
countryName_default		= US
countryName_min			= 2
countryName_max			= 2

stateOrProvinceName		= State or Province Name (full name)
stateOrProvinceName_default	= MA

localityName			= Locality Name (eg, city)
localityName_default		= Cambridge

organizationName		= Organization Name (eg, company)
organizationName_default	= The Open Group

organizationalUnitName		= Organizational Unit Name (eg, section)
organizationalUnitName_default	= Research Institute

commonName			= Common Name (eg, YOUR name)
commonName_default		=
commonName_max			= 64

emailAddress			= Email Address
emailAddress_max		= 40

[ req_attributes ]
challengePassword		= A challenge password
challengePassword_min		= 4
challengePassword_max		= 20

The policy section of the configuration file is used to define different certificate request signing policies. The examples here include the most lenient policy (policy_anything) and a stricter policy (policy_match) which restricts the values of certificate fields. The purpose of a policy is to guide processing of a certificate request.

In Example 4, match means that the value of the field in the request must match the value in the CA certificate, or the request will not be signed. optional means the the field need not be present, while supplied means that it must be present in the certificate request.

Example 4: SSLeay Configuration File: Policy Section
# For the CA policy
[ policy_match ]
countryName		= match
stateOrProvinceName	= match
organizationName	= match
organizationalUnitName	= match
commonName		= supplied
emailAddress		= optional

# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ]
countryName		= optional
stateOrProvinceName	= optional
localityName		= optional
organizationName	= optional
organizationalUnitName	= optional
commonName		= supplied
emailAddress		= optional

Creating a Self-Signed CA certificate

The SSLeay req command creates a self-signed certificate when the -x509 switch is used. The certificate is placed in the file CAcert.pem, and the private key in CAkey.pem. This command prompts for the password (e.g. caKEY) for the private key, and is used as shown in Example 5.

Example 5: Creating a Self-Signed CA Certificate
$SSLDIR/bin/ssleay req -new -x509 -keyout ${SSLDIR}/private/CAkey.pem \
      -out ${SSLDIR}/private/CAcert.pem  -config /opt/www/lib/ssleay.cnf

Using configuration from /opt/www/lib/ssleay.cnf
Generating a 512 bit private key
writing new private key to '../private/CAkey.pem'
Enter PEM pass phrase:
Verifying password - Enter PEM pass phrase:
You are about to be asked to enter information that will be incorperated
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) [US]:
State or Province Name (full name) [MA]:
Locality Name (eg, city) [Cambridge]:
Organization Name (eg, company) [The Open Group]:
Organizational Unit Name (eg, section) [Research Institute]:
Common Name (eg, YOUR name) []:Example CA
Email Address []

The SSLeay configuration file specifies the location of the CA certificate and key files using the following directives in the ca section:

# The CA certificate
certificate     = $dir/private/CAcert.pem

# The private key
private_key     = $dir/private/CAkey.pem

The Apache-SSL server httpd.conf file specifies the CA certificate and key files as follows:

# Set the CA certificate verification path (must be PEM encoded).
SSLCACertificatePath /opt/dev/ssl/private

# Set the CA certificate verification file (must be PEM encoded).
SSLCACertificateFile /opt/dev/ssl/private/CAcert.pem

Loading a CA certificate into a browser using a CGI script

Load the CA certificate into the browser by accessing an HTML form like that in Example 6. This form calls a CGI script to load the certificate using the application/x-x509-ca-cert MIME type as the Content-Type.

Example 6: HTML Form to Request CA Certificate to Load Into Browser
<H1>Load Certificate Authority Certificate</H1>

<TD>Netscape Browser (PEM Format):</TD>

<TR><TD>Microsoft Browser (DER Format):</TD>

<INPUT TYPE="SUBMIT" VALUE="Load Certificate">

Example 7 shows the script.

Example 7: Perl CGI Script to Load CA Certificate into Browser
#!/usr/local/bin/perl -T

require 5.003;
use strict;
use CGI;

my $cert_dir = "/opt/www/lib/certs";
my $cert_file = "CAcert.pem";

my $query = new CGI;

my $kind = $query->param('FORMAT');
if($kind eq 'DER') { $cert_file = "CAcert.der"; }

my $cert_path = "$cert_dir/$cert_file";

open(CERT, "<$cert_path");
my $data = join '',;
print "Content-Type: application/x-x509-ca-cert\n";
print "Content-Length: ", length($data), "\n\n$data";


Install the Certificate Authority certificate in the server certificate database as well as the browser, so that the server is able to locate the public key and validate certificate signatures signed by the certificate authority.

Server Certificates

Creating a Certificate Request

The SSLeay req command is used to create a PKCS#10 (Public-Key Cryptography Standards [3]) certificate request. It also generates a key pair when -new is specified, and may indicate the length of time the certificate is valid with the -days switch. SSLeay prompts for a new password for this certificate (call it siteKEY). A certificate request may be created as shown in Example 8.

Example 8: Using SSLeay to Create Certificate Request
cd $SSLDIR/bin
./ssleay req  -new -keyout newkey.pem -out newreq.pem  -days 360\
	-config /opt/www/lib/ssleay.cnf 

Using configuration from /opt/www/lib/ssleay.cnf
Generating a 512 bit private key
writing new private key to 'newkey.pem'
Enter PEM pass phrase:
Verifying password - Enter PEM pass phrase:
You are about to be asked to enter information that will be incorperated
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) [US]:
State or Province Name (full name) [MA]:
Locality Name (eg, city) [Cambridge]:
Organization Name (eg, company) [The Open Group]:
Organizational Unit Name (eg, section) [Research Institute]:
Common Name (eg, YOUR name) []:
Email Address []

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Example 9 shows the results in a certificate request being created in newreq.pem (in this paper certificates and keys are truncated).

Example 9: Sample Certificate Request

Example 10 shows a private key for the certificate being created in newkey.pem.

Example 10: Sample Private Key
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,21F13B37A796482C


Signing a Certificate Request

A server certificate is created by signing the certificate request using the SSLeay ca command. The -policy switch specifies the section of the SSLeay configuration file that defines which distinguished name fields are required, and the order of the fields. As an example, our test configuration file specifies the policy_anything section which makes all the listed distinguished name fields optional.

When this command is executed, it prompts for the certificate authority password, as shown in Example 11.

Example 11: Signing a Certificate Request to Create Server Certificate
cat newreq.pem newkey.pem > new.pem
./ssleay ca  -policy policy_anything -out newcert.pem \
	-config /opt/www/lib/ssleay.cnf -infiles new.pem

Using configuration from /opt/www/lib/ssleay.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:'MA'
localityName          :PRINTABLE:'Cambridge'
organizationName      :PRINTABLE:'The Open Group'
organizationalUnitName:PRINTABLE:'Research Institute'
commonName            :PRINTABLE:''
emailAddress          :IA5STRING:''
Certificate is to be certified until May 12 15:39:33 1998 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
Data Base Updated

The server certificate is created in the file newcert.pem as shown in Example 12 (line-breaks added for issuer and subject).

Example 12: Sample Server Certificate
issuer :/C=US/SP=MA/L=Cambridge/O=The Open Group/OU=Research Institute/
        CN=Example CA/
subject:/C=US/SP=MA/L=Cambridge/O=The Open Group/OU=Research Institute/
serial :01

        Version: 0 (0x0)
        Serial Number: 1 (0x1)
        Signature Algorithm: md5withRSAEncryption
        Issuer: C=US, SP=MA, L=Cambridge, O=The Open Group, 
                OU=Research Institute, 
                CN=Example CA/
            Not Before: May 12 15:39:33 1997 GMT
            Not After : May 12 15:39:33 1998 GMT
        Subject: C=US, SP=MA, L=Cambridge, O=The Open Group, 
                 OU=Research Institute, 
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Exponent: 65537 (0x10001)
    Signature Algorithm: md5withRSAEncryption


The Apache-SSL httpd.conf file must be modified to specify the server certificate and key files as follows:

# Point SSLCertificateFile at a PEM encoded certificate.
SSLCertificateFile /opt/www/lib/certs/sitecert.pem

# If the key is not combined with the certificate, use this directive to
# point at the key file. If this starts with a '/' it specifies an absolute
# path, otherwise it is relative to the default certificate area. That is,
# it means "/private/".
SSLCertificateKeyFile /opt/www/lib/certs/sitekey.pem

Client Certificates

Form to create Netscape Client Certificate Request

Netscape returns a "Signed Public Key And Challenge" (SPKAC) public key when the <KEYGEN> form element is encountered. The form in Example 13 returns this in the SPKAC hidden field. The CGI script then accesses this field and passes the SPKAC value to SSLeay using the -spkac switch to the ca command. (See ns-ca.doc in the doc directory in the SSLeay distribution).

Example 13: Sample Form to Request Netscape Client Certificate

<HTML><HEAD><TITLE>Create Client Certificate</TITLE></HEAD><BODY>
<CENTER><H1>Create Client Certificate</H1></CENTER>

<FORM NAME="GenerateForm" ACTION="">
<TR><TD>Common Name:</TD><TD>
<INPUT TYPE="TEXT" NAME="commonName" VALUE="Client Certificate" SIZE=64>
<INPUT TYPE="TEXT" NAME="emailAddress" VALUE="" SIZE=40>
<INPUT TYPE="TEXT" NAME="organizationName" VALUE="The Open Group">
<TR><TD>Organizational Unit:</TD><TD>
<INPUT TYPE="TEXT" NAME="organizationalUnitName" VALUE="Research Institute">
<TR><TD>Locality (City):</TD><TD>
<INPUT TYPE="TEXT" NAME="localityName" VALUE="Cambridge">
<INPUT TYPE="TEXT" NAME="stateOrProvinceName" VALUE="MA">
<INPUT TYPE="TEXT" NAME="countryName" VALUE="US" SIZE="2">
' keygen is Netscape specific and will be ignored in
' internet explorer
<KEYGEN NAME="SPKAC" CHALLENGE="challengePassword">


Perl Script to Process Netscape Client Certificate Request

Example 14 shows a Perl script used to create a client certificate for Netscape Navigator, as discussed in the section "Creating a Client Certificate".

Example 14: Sample Perl Script to Process Netscape Client Certificate Request

require 5.003;
use strict;
use CGI;

use File::CounterFile;			# module to maintain certificate request counter

my $doc_dir = $ENV{'DOCUMENT_ROOT'};		# apache specific location for storage
unless($doc_dir) {
    print "<HTML><HEAD><TITLE>Failure</TITLE></HEAD>";
    print "<BODY>DOCUMENT_ROOT not defined</BODY></HTML>";

my $base_dir = $doc_dir;
$base_dir =~ s/\/htdocs//;

my $SSLDIR  = '/opt/dev/ssl';			# define where SSLeay files are located
my $CA = "$SSLDIR/bin/ca";
my $CONFIG =  "/opt/www/lib/ssleay.cnf";
my $CAPASS = "caKEY";

my $query = new CGI;			# get a handle on the form data

my $key = $query->param('SPKAC'); 		# this will fail if not Netscape browser
unless($key) { fail("No Key provided $key. Netscape required"); }

my $counter = new File::CounterFile("$base_dir/.counter", 1);
unless($counter) { fail("Could not create counter: $!"); }
my $count = $counter->inc();

my $certs_dir = "$base_dir/certs"; 
my $req_file = "$certs_dir/cert$count.req"; 	# certificate request filename
my $result_file = "$certs_dir/cert$count.result"; # certificate filename

# Explicitly list form fields we must have for certificate creation to work.
my @req_names = ('commonName', 'emailAddress', 'organizationName',
		 'organizationalUnitName', 'localityName', 'stateOrProvinceName',
		 'countryName', 'SPKAC');

# build the request file
open(REQ, ">$req_file") or fail("Could not create request $req_file: $!");

my $name;
foreach $name (@req_names) {
    my $value = $query->param("$name");
    $value =~ tr/\n//d;
    print REQ "$name = $value\n";
# make sure we actually created a request file
unless(-f $req_file) { fail("request missing: $req_file"); }

unless(-e $CA) { fail("command missing"); }	# ensure that ca command will run

# command for processing certificate request, without password
my $cmd = "$CA -config $CONFIG -spkac $req_file -out $result_file -days 360";
my $rc =  system("$cmd -key $CAPASS 2>errs");
if($rc != 0) { fail("$cmd<P>rc = $rc", "errs"); }

open(CERT, "<$result_file") or fail("Could not open $result_file<P>$!");

# send the client certificate to the browser
print "Content-Type: application/x-x509-user-cert\n";

my $result = join '', <CERT>;
close CERT;

my $len = length($result);
print "Content-Length: $Len\n\n";
print $result;


sub fail {
    my($msg, $errs) = @_;

    print $query->header;
    print $query->start_html(-title => "Certificate Request Failure"); 
    print "<H2>Certificate request failed</H2>$MSG<P>";
    if($errs) {
	if(open(ERR, "<errs")) {
	    while(<ERR>) {
		print "$_<BR>";
	    close ERR;
    print $query->dump();
    print $query->end_html();


The CGI script for Netscape Navigator creates a file containing the distinguished name values returned by the form, and a special SPKAC value for the "Signed Public Key And Challenge (SPKAC)" generated by Navigator. This file contains the information which would be in a certificate request, and is used to generate the certificate.

The SSLeay ca command is called with this file as an argument to generate a client certificate, as follows (Also see ns-ca.doc from the SSLeay documentation) :

$SSLDIR/bin/ca -spkac $req_file -out $result_file -days 360 -key $CAPASS \
        -config /opt/www/lib/ssleay.cnf 2>errs

This example shows the command after some of the Perl processing to create the command has been performed. The $req_file variable contains the name of a unique file in the certs directory used to contain the certificate request information obtained from the CGI form data. The $result_file variable contains the name of a unique file in the certs directory used to contain the certificate. The $CAPASS Perl variable contains the CA key.

If the ca command is successful, then the certificate is returned by the CGI script as an application/x-x509-user-cert HTTP Content-Type. Navigator recognizes this type, and prompts the user for the remainder of the steps required to install the user certificate in the browser.

Form to create Microsoft Client Certificate Request

Example 15 shows the HTML form used to generate a certificate request from Microsoft Internet Explorer, as discussed in the section "Creating a client certificate".

Example 15: Sample HTML Form with JavaScript and ActiveX to Request Microsoft Internet Explorer Client Certificate
<HTML><HEAD><TITLE>Client Certificate Request</TITLE></HEAD><BODY>

<!-- Use the Microsoft ActiveX control to generate the certificate -->
<OBJECT CLASSID="clsid:33BEC9E0-F78F-11cf-B782-00C04FD7BF43"

<!-- JavaScript or Visual Basic will work. -->

// this is from JavaScript: The Definitive Guide, since
// Microsoft implementation of Math.random() is broken
function random() {
    random.seed = (random.seed*random.a + random.c) % random.m;
    return random.seed/random.m;
random.m = 714025; random.a = 4096; random.c = 150889;
random.seed = (new Date()).getTime()%random.m;

function GenReq ()
    var sessionId		= "a_unique_session_id";
    var reqHardware     	= 0;
    var szName          	= "";
    var szPurpose       	= "ClientAuth";
    var doAcceptanceUINow   	= 0;
    var doAcceptanceUILater	= 0;
    var doOnline        	= 1;
    var keySpec = 1;

    szName = "";
    if (document.GenReqForm.commonName.value == "")
	alert("No Common Name");
	return false;
     szName = "CN=" + document.GenReqForm.commonName.value;

    if (document.GenReqForm.countryName.value == "")
	alert("No Country");
	return false;
	szName = szName + "; C=" + document.GenReqForm.countryName.value;

    if (document.GenReqForm.stateOrProvinceName.value == "")
	alert("No State or Province");
	return false;
	szName = szName + "; S=" + document.GenReqForm.stateOrProvinceName.value;

    if (document.GenReqForm.localityName.value == "")
	alert("No City");
	return false;
	szName = szName + "; L=" + document.GenReqForm.localityName.value;

    if (document.GenReqForm.organizationName.value == "")
	alert("No Organization");
	return false;
	szName = szName + "; O=" + document.GenReqForm.organizationName.value;

    if (document.GenReqForm.organizationalUnitName.value == "")
	alert("No Organizational Unit");
	return false;
	szName = szName + "; OU=" + document.GenReqForm.organizationalUnitName.value;

    /* make session id unique */
    sessionId = "xx" + Math.round(random() * 1000);

    sz10 = certHelper.GenerateKeyPair(sessionId, reqHardware, szName,
                                      0, szPurpose, doAcceptanceUINow, 
                                      doOnline, keySpec, "", "", 1);

     * The condition sz10 being empty occurs on any condition in which the
     * credential was not successfully generated. In particular, it occurs
     * when the operation was cancelled by the user, as well as additional
     * errors. A cancel is distinguished from other unsuccessful
	* generations by an empty sz10 and an error value of zero.

    if (sz10 != "")
	document.GenReqForm.reqEntry.value = sz10;
     document.GenReqForm.sessionId.value = sessionId;
    } else {
	   alert("Key Pair Generation failed");
	   return false;


<CENTER><H3>Generate key pair and client certificate request</H3></CENTER>

     NAME="GenReqForm"  onSubmit="GenReq()">
<TR><TD>Common Name:</TD><TD>
<INPUT TYPE=TEXT NAME="commonName" VALUE="Client Certificate" SIZE=64>


</TD></TR><TR><TD>State or Province:</TD><TD>
<INPUT TYPE=TEXT NAME="stateOrProvinceName" VALUE="MA">

<INPUT TYPE=TEXT NAME="localityName" VALUE="Cambridge">

<INPUT TYPE=TEXT NAME="organizationName" VALUE="The Open Group">

</TD></TR><TR><TD>Organizational Unit:</TD><TD>
<INPUT TYPE=TEXT NAME="organizationalUnitName" VALUE="Research Institute">





Perl Script to Process Microsoft Client Certificate Request

Example 16 shows a Perl script used to create a client certificate for Microsoft Internet Explorer, as discussed in the section "Creating a client certificate". This script uses JavaScript and an ActiveX control to install the certificate into Internet Explorer.
Example 16: Sample Perl Script to Process Internet Explorer Client Certificate Request

require 5.003;
use strict;
use CGI;

use File::CounterFile;         		# module to maintain certificate request counter

my $SSLDIR  = '/opt/dev/ssl';
my $CA = "$SSLDIR/bin/ca";
my $CRL2PKCS7 = "$SSLDIR/bin/crl2pkcs7";
my $CONFIG =  "/opt/www/lib/ssleay.cnf";
my $CRL = "$SSLDIR/crl/crl.pem";
my $CAPASS = "caKEY";

my $doc_dir = $ENV{'DOCUMENT_ROOT'};		# apache specific location for storage
unless($doc_dir) {
    print "<HTML><HEAD><TITLE>Failure</TITLE></HEAD><BODY>DOCUMENT_ROOT not defined</BODY></HTML>";
my $base_dir = $doc_dir;
$base_dir =~ s/\/htdocs//;

my $query = new CGI;

my $req = $query->param('reqEntry');

unless($req) { fail("No Certificate Request Provided"); }

my $counter = new File::CounterFile("$base_dir/Counter", 1);
unless($counter) { fail("Count not create counter: $!"); }
my $count = $counter->inc();

my $certs_dir = "$base_dir/certs"; 
my $req_file = "$certs_dir/cert$count.req";
my $result_file = "$certs_dir/cert$count.result";
my $key_file = "$certs_dir/$count.key";
my $debug_file = "$certs_dir/$count.debug";
my $pkcs7_file = "$certs_dir/cert$count.pkcs";

#process request
$req =~ tr/\r//d;
$req =~ tr/\n//d;

# save the certificate request to a file, as received
open(REQ, ">$req_file") or fail("Could no save certificate request to file");

my $result = 1;
while($result) {
    $result = substr($req, 0, 72);
    if($result) {
	print REQ "$result\n";
	$req = substr($req, 72);
print REQ "-----END CERTIFICATE REQUEST-----\n";

unless(-e $CA) { fail("$CA command missing"); }

my $cmd = "$CA -config $CONFIG -in $req_file -out $result_file -days 360 -policy policy_match";
my $rc =  system("$cmd -key $CAPASS 2>errs <<END\ny\NY\nEND");

my $session = $query->param('sessionId');
my $cn = $query->param('commonName');

if($rc != 0) { fail("Certification Request Failed</h2>$cmd<P>rc = $rc<P>\
                       sessionID = $session<BR>req = $req<BR>", "errs"); }

my $cmd = "$CRL2PKCS7 -certfile $result_file -in $CRL -out $pkcs7_file";
my $rc =  system("$cmd 2>errs");

open(CERT, "<$pkcs7_file") or fail("Could not open $pkcs7_file<P>$!");
my $certificate = "";
my $started = 0;
while(<CERT>) {
    if(/BEGIN PKCS7/) {
	$started = 1;
    if(/END PKCS7/) {

    if($started) { 
	$certificate .= "$_"; 

open(MSG, ">MSG") or fail("Could not generate message");

print MSG <<_END_TEXT_;
<HTML><HEAD><TITLE>Finish Client Certificate Installation</TITLE>

<!-- Use the Microsoft ActiveX control to install the certificate -->
<OBJECT  CLASSID="clsid:33BEC9E0-F78F-11cf-B782-00C04FD7BF43"

function InstallCert (subject, sessionId, cert)
    if( sessionId == "") {
	alert("No Session id");

    if(cert == "") {
	alert("No Certificate");

    var doAcceptanceUILater = 0;

    result  = certHelper.AcceptCredentials(sessionId, cert, 0,

    if(result == "") {
	var MSG = "Attempt to install " + subject + " client certificate failed";
	return false;
    } else {
	var MSG = subject + " client certificate installed";

<BODY onLoad="InstallCert('$cn', '$session', '$certificate');">
Installing client certificate for $cn<BR>
session: $session<BR>



open(RD, "<MSG") or fail("Could not open MSG file");
my $MSG = join '', <RD>;

my $Len = length($MSG);

print "Content-Type: text/html\n";
print "Content-Length: $Len\n\n";
print $MSG;


sub fail {
    my($MSG, $errs) = @_;

    print $query->header;
    print $query->start_html(-title => "Certificate Request Failure"); 
    print "<H2>Certificate request failed</H2>$MSG<P>";
    if($errs) {
	if(open(ERR, "<errs")) {
	    while(<ERR>) {
		print "$_<BR>";
	    close ERR;
    print $query->dump();
    print $query->end_html();


It is more complicated than the Netscape Navigator CGI script because it must create an HTML page containing JavaScript which calls an ActiveX control in order to install the client certificate. The CGI script does the following:

  1. Validates and reformats the certificate request passed in the hidden field.
  2. Calls the SSLeay ca command to create a certificate from the request
  3. Combines the certificate with a certificate revocation list to create a PKCS#7 certificate
  4. Dynamically generates an HTML form containing the certificate
  5. Sends the HTML form to browser to install the certificate

The script takes the certificate request generated by Internet Explorer from a hidden form field, and reformats it so that each line in the request is 72 characters long. It then passes this certificate request to the SSLeay ca command to generate a certificate, as follows:

$SSLDIR/bin/ca -in $req_file -out $result_file -days 360 -policy policy_match \
	-config /opt/www/lib/ssleay.cnf  -key $CAPASS 2>errs
This example shows the command after some of the Perl processing to create the command has been performed. The $req_file variable contains the name of a unique file in the certs directory used to contain the reformatted certificate request (the file is useful for debugging). The $result_file variable contains the name of a unique file in the certs directory used to contain the certificate. The $CAPASS Perl variable contains the CA key.

Once the certificate has been successfully generated, the SSLeay crl2pkcs7 utility is used to combine the certificate with the SSLeay certificate revocation list (CRL) to create a PKCS#7 certificate. This is done using the crl2pkcs7 command as follows:

$SSLDIR/bin/crl2pkcs7 -certfile $result_file -in $CRL -out $pkcs7_file 2>errs
This example shows the command after some of the Perl processing to create the command has been performed. The $result_file variable contains the name of a unique file in the certs directory used to contain the certificate. The $pkcs7_file Perl variable contains the name of a unique file in the certs directory used to contain the result PKCS#7 certificate. The $CRL Perl variable contains $SSLDIR/crl/crl.pem, the file containing the Certificate Authority certificate revocation list.

A certificate revocation list may be created using SSLeay as follows:

$SSLDIR/bin/ca -gencrl -config /opt/www/lib/ssleay.cnf -out $SSLDIR/crl/crl.pem

Once the PKCS#7 certificate has been successfully generated, an HTML page is dynamically generated. This page contains JavaScript code which calls an ActiveX control to install the certificate in the browser. The page in this example is designed to automatically load the certificate once the page has loaded into the browser, by using the JavaScript onLoad command. In a production system such automatic installation may not be desired.


Many thanks to Eric Young for creating SSLeay, Tim Hudson for his SSLeay work, and Jeff Barber for modifying it to work with Netscape client certificates.

Thanks to Rick Cormier, Ed Frankenberry, Scott Meeks, Tom Titchner, David Weisman and Mary Ellen Zurko for reviewing this article and providing many useful suggestions and insights. Thanks to Doug McEachern for reviewing the Perl code.



  1. CCITT. Recommendation X.208: Specification of Abstract Syntax Notation One (ASN.1). 1988.

  2. CCITT. Recommendation X.509: The Directory - Authentication Framework. 1988.

  3. Kaliski ,Burton S.,Jr., "An Overview of the PKCS Standards", An RSA Laboratories Technical Note, revised November 1, 1993.

  4. Kaliski, Burton S., Jr., "A Layman's Guide to a Subset of ASN.1, BER, and DER", An RSA Laboratories Technical Note, revised November 1, 1993.

  5. Kaufman, Charlie, Perlman, Radia , Speciner, Mike , Network Security: PRIVATE Communication in a PUBLIC world, Prentice Hall, 1995.

  6. Koops, Bert-Jaap, "Crypto Law Survey", version 8.2, May 1997.

  7. Phaos, SSL Resource Center,

  8. Schneier,Bruce , Applied Cryptography, 2nd Edition, Wiley, 1996. See for various materials by Bruce Schneier.

  9. Microsoft Certificate Specifications, "Installing Certificates and Root Keys in Microsoft Internet Explorer 3.0 and IIS",

  10. Netscape Certificate Specifications,

  11. VeriSign Digital Id FAQ,

  12. SSL2.0,

  13. SSL3.0 Internet Draft,

  14. TLS Working Group (IETF),

  15. TLS2.0,

  16. BSAFE3.0,

  17. RSARef,

  18. SSLava,

  19. SSLRef,

  20. SSLPlus,

  21. SSLeay FAQ,

Additional Resources

  1. Taher Elgamal, Jeff Treuhaft, Frank Chen, "Securing Communications on the Intranet and Over the Internet", Netscape Communications Corporation, July 1996.

  2. Flanegan, D., JavaScript - The Definitive Guide, 2nd Edition, O'Reilly & Associates, 1997.

  3. Laurie, Ben, and Laurie, Peter, Apache - The Definitive Guide, O'Reilly & Associates, 1997.

  4. RSARef-FAQ,

  5. Stein, Lincoln D., How to Set Up and Maintain a Web Site, 2nd Edition, Addison-Wesley, 1997.

  6. SSL_Talk_FAQ,

  7. SSLeay-0.8.1 (SSLeay-0.8.1.tar.gz)

  8. Wall, L, Christiansen,T, Schwartz, R, Programming Perl, 2nd Edition, O'Reilly & Associates, 1996.

  9. World Wide Web Journal, "Advancing HTML", Winter 1997, Vol. 2, No. 1.

About the Author

Frederick J. Hirsch
The Open Group Research Institute
11 Cambridge Center, Room 418
Cambridge, MA 02142

Frederick J. Hirsch is a Principal Research Engineer at The Open Group Research Institute.

His interests include human-computer interaction, artificial intelligence and marketing. He is currently working on software to add functionality and ease of use to the Web by extending browsers, filtering HTTP streams, and implementing server plugins.

Before joining the Open Group Research Institute he wrote software for security trading at the MacGregor group and for network analysis at Bolt, Beranek and Newman (BBN). Prior to that, he worked on the Datakit local network at AT&T Bell Laboratories. He has an MBA from Boston University, a Master's in Computer Engineering from Stanford University, and a Bachelor of Science in Computer Science and Electrical Engineering from MIT.