Securing Communications with SSL/TLS: Using

by Chris Pepper

In Securing Communications with SSL/TLS: A High-Level Overview, I discussed SSL/TLS and how they work. In this article, I discuss command-line procedures for working with SSL/TLS certificates. In Securing Communications with SSL/TLS: Streamlined CA Procedures (cert.command & sign.command, I will look at some streamlined CA tools.

Choose Your Weapon -- There are several different ways to deal with SSL/TLS certificates. The original the command-line openssl tool, which can do just about everything with certificates, but is neither simple nor well documented (there is a lot of documentation for OpenSSL, but much of it is poor or tied to a specific service or product). On the other hand, OpenSSL is ubiquitous. It is included with Mac OS X, Linux, Solaris, etc.; and serves as the basis for Apache httpd's SSL/TLS capabilities.

To assist customers through the complexities of SSL/TLS without having to deal with the command line and the totally un-Mac-like OpenSSL, Apple provides Certificate Assistant, available from Keychain Access (in /Applications/Utilities). The Assistant presents simple prompts to walk through working with both individual certificates (useful for SSL/TLS and encrypted mail), and CA certificates. Additionally, it can analyze and verify certificates. Unfortunately, the Assistant is Mac-only, which prevents its nifty CA/CSR interoperability feature from being fully useful, and has a tendency to lose CSRs (Certificate Signing Requests) silently, so I will not examine it further here. Perhaps in Mac OS X 10.5 "Leopard" it will be more useful...

Apple also provides not one but two non-graphical tools comparable to Certificate Assistant: certtool is a simple interactive text-based utility capable of handling the major certificate procedures (creating a CSR, creating a self-signed certificate, etc.). It uses simple prompts to request information; Apple designed certtool to manage certificates for the keychain, but Keychain Access makes it reasonably simple to import and export certificates and keys to text files. Apple has begun to replace certtool with a newer security command, but unfortunately it has all the same limitations as certtool, including being incomplete. Since both tools are Mac-only and neither is complete, I will not discuss them further here.

One of the easier ways to work with certificates on a Mac is through Server Admin (only available for Mac OS X Server). Server Admin makes it easy to create new certificates -- simply click on a server's name (not a service but the server itself), then Settings, then Certificates, and then the large '+' (plus sign) button. Fill in the blanks, then click Save. Next choose either "Request Signed Certificate From CA..." (to generate a Certificate Signing Request) or "Add Signed Certificate..." (to self-sign). Unfortunately, when using Server Admin, Mac OS X Server can get confused and lose or delete certificates, so it's important for Server users to keep good backups and test SSL/TLS services after working with certificates.

There are many alternatives. As one example, for a while I used the web interface on our Big-IP load balancers to create CSRs and self-signed certificates for various different sites -- the Big-IP UI is quick and simple, and about half our certificates were for the Big-IPs anyway.

The most common option is probably to use, a handy but rough perl script included with OpenSSL (and in Mac OS X, both Server and non-Server). The rest of this article will show you how to use Securing Communications with SSL/TLS: Streamlined CA Procedures (cert.command & sign.command) looks at streamlined scripts for the most common CA operations, cert.command and sign.command.

What Can You Do? -- There are a wide variety of things you might do with certificates, but among the most common are:

  1. Create a new Certificate Authority
  2. Create a new certificate signing request
  3. Create a self-signed certificate
  4. Request that a CA sign a CSR and return a signed certificate
  5. Sign a CSR with your own root certificate
  6. Install a certificate in a server
  7. Trust a certificate
  8. Verify a certificate file
  9. Test an SSL/TLS connection

OpenSSL can perform all the above except #2. Getting a CA to sign a CSR is normally handled through the CA's secure web site (protected using SSL/TLS, naturally!). Because the openssl command is complicated, the OpenSSL package includes, a perl script to facilitate various common actions. Mac OS X installs it as /System/Library/OpenSSL/misc/

www:~ julia$ /System/Library/OpenSSL/misc/ -help
usage: CA -newcert|-newreq|-newreq-nodes|-newca|-sign|-verify

The Very First Step: Think about Security -- You need to think carefully about several issues before setting up a CA. Understand that you do not necessarily need to choose the most paranoid answers, but it's important to spend some time considering how much paranoia is appropriate, which is largely determined by what you will use your CA-signed certificates to protect, and the particulars of your situation. Key questions include:

  1. What are you planning to do with this CA and the certificates it signs?
  2. How many people will trust this CA?
  3. How many certificates is the CA expected to create? How long will it last? 10 years is often reasonable for a root certificate, although commercial CAs tend to use longer terms to avoid expirations.
  4. What computer will you run the CA on?
  5. Will the CA files and directories be on internal or removable media?
  6. What account will manage the CA? Some people believe this should be root, since the CA is likely to be the most sensitive function for the machine it runs on.
  7. How much can you lock down the CA machine? Can you afford to keep it disconnected from the Internet entirely? A laptop that's normally closed and locked in a drawer might be a good option, if you have an older one available to dedicate.
  8. How will you back the CA up? For reasons discussed in Securing Communications with SSL/TLS: A High-Level Overview, backups of SSL/TLS keys are more complicated (sensitive) than normal backups. My current suggestion is to keep the CA directory on an encrypted file system (encrypting the CA key itself as well), and keep at least 2 backups in the most secure places you can find. I'm currently using an encrypted Disk Utility image on a USB "thumb drive", and a CD-R (containing the encrypted .dmg) for one of the backups.

Remember that there are plenty of people constantly trying to break into computers all over the world, while the number of people who actually enter any particular home or office is much smaller.

Configure OpenSSL -- Now verify that you are using the right openssl binary (/usr/bin/openssl); if you are using another one (Fink does this), you probably have to configure a different openssl.cnf file or change your $PATH. Then make a backup of /System/Library/OpenSSL/openssl.cnf and configure it to your requirements (only an administrator can do this):

www:~ julia$ which openssl
www:~ julia$ cd /System/Library/OpenSSL/
www:/System/Library/OpenSSL julia$ sudo cp -p openssl.cnf openssl.cnf.orig
www:/System/Library/OpenSSL julia$ bbedit openssl.cnf

You can use any text editor, as long as it saves openssl.cnf with UNIX line breaks ("LF" characters). I use BBEdit because it is excellent, and its bbedit command-line helper makes illustration clearer. Customize your openssl.cnf file with the CA directory you want to use and to reflect your organization. The diff output below shows a few changes to become a CA for reppep certificates. In "unified diff" output, lines beginning with a - (minus sign) were removed or modified from the original, and lines beginning with a + (plus sign) are additions or changes.

www:/System/Library/OpenSSL julia$ diff -U0 openssl.cnf.orig openssl.cnf
--- openssl.cnf.orig    2007-06-24 01:13:34.000000000 -0400
+++ openssl.cnf 2007-06-24 00:38:04.000000000 -0400
@@ -37 +37 @@
-dir            = ./demoCA              # Where everything is kept
+dir            = /Volumes/
@@ -41,2 +41,2 @@
-#unique_subject        = no                    # Set to 'no' to allow creation of
-                                       # several ctificates with same subject.
+unique_subject = no                    # Set to 'no' to allow creation of
+                                       # several certificates with same subject.
@@ -45 +45 @@
-certificate    = $dir/cacert.pem       # The CA certificate
+certificate    = $dir/       # The CA certificate
@@ -50 +50 @@
-private_key    = $dir/private/cakey.pem# The private key
+private_key    = $dir/private/       # The private key
@@ -125 +125 @@
-countryName_default            = AU
+countryName_default            = US
@@ -130 +130 @@
-stateOrProvinceName_default    = Some-State
+stateOrProvinceName_default    = New York
@@ -132,0 +133 @@
+localityName_default           = Brooklyn
@@ -135 +136 @@
-0.organizationName_default     = Internet Widgits Pty Ltd
+0.organizationName_default     = reppep
@@ -147,0 +149 @@
+emailAddress_default           =

A word of warning: uses a few standard filenames extensively, so after you run it, rename the output files before using again -- otherwise it will overwrite the files. Securing Communications with SSL/TLS: Streamlined CA Procedures (cert.command & sign.command) describes some friendlier tools that avoid overwriting files.

1. Create a new Certificate Authority -- Fundamentally, a CA is a party in possession of a root certificate which can sign other certificates. Unfortunately, -newca ignores openssl.cnf's dir setting, and always sets up a new CA in ./demoCA, so some tweaking is required for a real CA. In our example, I will work with a CA in /Volumes/ Additionally, it creates the root certificate with a 1-year lifetime, which is only suitable for testing. To fix this, change the $DAYS= line in to something more reasonable (I used 3650, for 10 years).

www:/System/Library/OpenSSL julia$ sudo cp -p misc/ misc/
www:/System/Library/OpenSSL julia$ bbedit misc/ 
www:/System/Library/OpenSSL julia$ diff -U0 misc/ misc/
--- misc/     2006-11-02 13:01:40.000000000 -0500
+++ misc/  2007-06-24 01:17:33.000000000 -0400
@@ -48 +48 @@
-$DAYS="-days 365";
+$DAYS="-days 3650";

When prompted for a "PEM pass phrase", enter a strong password! Someone who can read your private key can impersonate any server using one of its child certificates, and decrypt all its communications. Note that "Common Name" is the most important field. If your web site's hostname doesn't match the common name in the certificate, browsers will generate a security alert. Common names should generally be the full official domain name of the site, such as, rather than www or or

I suggest keeping your CA directory on an encrypted disk image, which means even if someone gets the whole thing, it won't be readable. The .dmg file could be on a hard disk (make sure it's only readable by authorized users) or on a USB thumb drive. In either case, make sure you have at least 2 backups. In my case, the disk image is called, so it mounts at /Volumes/

www:/System/Library/OpenSSL julia$ cd /Volumes/
www:/Volumes/ julia$ /System/Library/OpenSSL/misc/ -newca
CA certificate filename (or enter to create)

Making CA certificate ...
Generating a 1024 bit RSA private key
writing new private key to './demoCA/private/cakey.pem'
Enter PEM pass phrase:
Verifying - 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) [US]:
State or Province Name (full name) [New York]:
Locality Name (eg, city) [Brooklyn]:
Organization Name (eg, company) [reppep]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []
Email Address []:

Now you have the CA directory (demoCA) where insists on putting it. Get rid of the extra directory and finish setup:

www:/Volumes/ julia$ mv demoCA/* .
www:/Volumes/ julia$ rmdir demoCA/
www:/Volumes/ julia$ echo 01 > serial 
www:/Volumes/ julia$ chmod go-wrx private/
www:/Volumes/ julia$ mv private/cakey.pem private/
www:/Volumes/ julia$ ls -lR
total 16
-rw-r--r--   1 julia  admin  1249 Jun 24 01:23 cacert.pem
drwxr-xr-x   2 julia  admin    68 Jun 24 01:22 certs
drwxr-xr-x   2 julia  admin    68 Jun 24 01:22 crl
-rw-r--r--   1 julia  admin     0 Jun 24 01:22 index.txt
drwxr-xr-x   2 julia  admin    68 Jun 24 01:22 newcerts
drwx------   3 julia  admin   102 Jun 24 01:25 private
-rw-r--r--   1 julia  admin     3 Jun 24 01:25 serial




total 8
-rw-r--r--   1 julia  admin  963 Jun 24 01:23

Under the hood, creates several empty files and directories, and runs the openssl command to create a root certificate and key, something like "openssl req -new -x509 -days 3650 -keyout ./demoCA/private/cakey.pem -out ./demoCA/cacert.pem".

To review your new root certificate, use c_info, the certificate info tool:

www:/Volumes/ julia$ /System/Library/OpenSSL/misc/c_info cacert.pem 
subject= /C=US/ST=New York/L=Brooklyn/O=reppep/
issuer= /C=US/ST=New York/L=Brooklyn/O=reppep/
notAfter=Jun 21 05:23:21 2017 GMT

Once you have your root certificate, you can make it available for people to download and trust in their browsers. Since this is a critical piece of security infrastructure, think about how people can get it, and how they can know it's legitimate. If someone hacks your web site and puts up their own bogus certificate, how would you or your users know? One option is to publicize the fingerprint of the certificate in "alternative media", like a phone answering message, or on paper, which provides a reasonably tamper-proof check (assuming it's not a digital voice-mail system!), but that's something to decide based on the specifics of your situation.

Because certificates and private keys are base-64 encoded, and the important parts (the cryptographic keys) are really just large numbers, they're hard to tell apart. To alleviate this, it's handy to embed additional information into the certificate files (OpenSSL conveniently ignores everything it doesn't want), which can make them easier to work with. I suggest something like the following:

www:/Volumes/ julia$ openssl x509 -text -fingerprint -sha1 -in cacert.pem -out
SHA1 Fingerprint=FB:08:82:02:62:6F:5D:51:BB:70:6F:EE:A9:54:BC:04:3C:C0:9B:0D

This produces, which combines the encoded certificate itself from cacert.pem with a bunch of (non-sensitive) information about the certificate, creating a new annotated root certificate file.

If you want to reset your serial number, note that serial numbers are in hexadecimal, and OpenSSL assumes they contain an even number of digits. A common way to reset the serial number is "echo 01 > serial". Otherwise OpenSSL will start with a random serial number.

2. Create a new certificate signing request -- "/System/Library/OpenSSL/misc/ -newreq-nodes" creates a new CSR, ready for a CA to sign. CSRs are not usable until they have been converted into real certificates by being signed.

For more security, server keys should be encrypted, and " -newreq" automatically encrypts the new private key it creates along with the CSR, using DES (the older US "Data Encryption Standard"). Unfortunately, encryption means software using the certificate & key cannot start unattended, because an authorized human must enter the decryption passphrase to access the certificate. In reality, private keys for server software are routinely not encrypted to facilitate automatic restarts, and " -newreq-nodes" ensures the private key is not encrypted. With an unencrypted private key, it is essential to protect the private key file with access controls (UNIX permissions, restricted login access to the CA computer and files, etc.). Be sure to review permissions on new server key files, as well as the root key (inside the CA's private directory) to ensure only authorized users can access them.

www:/Volumes/ julia$ /System/Library/OpenSSL/misc/ -newreq-nodes
Generating a 1024 bit RSA private key
writing new private key to 'newkey.pem'
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) [US]:
State or Province Name (full name) [New York]:
Locality Name (eg, city) [Brooklyn]:
Organization Name (eg, company) [reppep]:
Organizational Unit Name (eg, section) []:
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 []:
Request is in newreq.pem, private key is in newkey.pem

3. Create a self-signed certificate -- " -newcert" creates a CSR and uses the CSR to sign itself, thus creating a certificate which attests to its own validity. Self-signed certificates are extremely common for testing and private use, as they provide exactly the same encryption as CA-signed certificates for free. This command produces newkey.pem and newcert.pem, so make sure you don't have files with these names left over from a previous operation, or they would be overwritten and lost. You might also want to append the root certificate and/or add identifying information to the certificate file (see the previous section, and Securing Communications with SSL/TLS: Streamlined CA Procedures (cert.command & sign.command), for more on adding fingerprints to certificates).

4. Request that a CA sign a CSR and return a signed certificate -- This is the part OpenSSL can't do for you. On the other hand, you could sign someone else's CSR if you are a CA (see below for how).

I'm most familiar with Thawte, although we keep an eye out for cheaper alternatives. The last competitor we considered was GeoTrust, also bought by VeriSign before we could switch, so we're wondering how things will settle out.

5. Sign a CSR with your own root certificate -- If you are serving as your own CA, "/System/Library/OpenSSL/misc/ -sign" will sign newreq.pem in the current directory using your CA certificate, producing newcert.pem as output.

Remember that if you create a root certificate (thus becoming a certificate authority) and use that to sign another certificate, the result is not a "self-signed certificate" -- "self-signed" means a certificate signs itself, so the "certificate chain" is actually a loop containing one item. A certificate signed by a different root certificate is a 'proper' certificate with a real (non-circular) chain of trust, even if the root certificate belongs to the same party as the server certificate.

6. Install a certificate in a server -- Every server application that can handle SSL/TLS has its own configuration system, but certificates and keys in Apache httpd (both the 1.3 and 2.x flavors) are controlled by the SSL directives. The simplest way to deal with a private CA and server certificate is to append the private CA's certificate to the end of the server certificate file, and specify this file for both the SSLCertificateKeyFile and SSLCertificateChainFile directives. The key (which is secret) goes in another file, and must be protected from unauthorized access. Apple's Server Admin is somewhat limited, and may be unable to import certificates containing multiple certificates or human-readable certificate descriptions. I am currently manually specifying keys for Apache httpd, Postfix, Cyrus, and jabberd, and complaining loudly while hoping this is sorted out in Leopard. You may also have to quit and relaunch Safari, Firefox, and/or to pick up certificate changes.

www:/Volumes/ julia$ grep SSLCertificate /etc/httpd/sites/
        SSLCertificateKeyFile "/etc/certificates/"
        SSLCertificateFile "/etc/certificates/"
        SSLCertificateChainFile "/etc/certificates/"

A benefit of doing it this way is that the user will see the whole certificate chain in their browser or, and can accept the root certificate directly from that warning dialog, thus trusting all the other certificates it has signed. Without the SSLCertificateChainFile, a browser will present the server cert, but not offer to trust the root certificate.

7. Trust a certificate -- Unfortunately, due to legitimate fears about attackers installing their own CA certificates into browsers to make users trust fraudulent sites, adding trust for a private CA has gone from an obscure task to an actively discouraged one. In Firefox 1.5, for instance, when connecting to a SSL/TLS site with an unknown root certificate, the browser allowed you to accept the root CA directly from the unknown certificate warning window; in Firefox 2.0 this option has been removed. Now accepting a new certificate requires you to visit Firefox > Preferences > Advanced > Encryption > View Certificates > Authorities > Import, find the certificate file, (verify a fingerprint via the View button,) select "Trust this certificate to identify web sites.", and finally click the OK button.

Fortunately trusting a new root certificate for Safari and Apple's is simpler. Normally, when Safari finds an untrusted site, it presents a dialog asking if you wish to connect. Clicking "Show Certificate" reveals a little information about it (click the triangle by Details for the rest), and clicking "Always trust these certificates" followed by "Continue" will prompt for an administrator password and add them to the X509Anchors keychain, avoiding future confirmations. If the certificate chain is set up properly on the server this trusts the root certificate, not just the server certificate.

Apple's method for trusting certificate files already on disk is relatively easy too: Open Keychain Access, click "Show Keychains" in the lower left-hand corner if necessary, drag the new certificate onto the X509Anchors keychain, and authenticate to allow the addition. Alternatively, double-click the .crt or .pem file containing the certificate, pick X509Anchors from the pop-up list, hit OK, and authenticate.

It is sometimes necessary to quit and relaunch the browser and Keychain Access to pick up certificate trust changes.

8. Verify a certificate file -- The standard way to check a certificate is to click the lock icon in a web browser, but there are many others, particularly useful if the certificate is not for a web site, or you need to check a certificate before using it. Certificate Assistant (available from the Keychain Access menu in the Keychain Access application) is one option. For local certificates, you can also use "openssl x509 -text -fingerprint -sha1 -in *certificate.crt*". See #9, below, for how to check remote certificates with openssl s_client.

9. Test an SSL/TLS connection -- One of the most useful troubleshooting techniques for Internet communications is connecting to a troublesome server via the telnet command and poking around, requesting help or trying commands. With SSL/TLS encryption this becomes impossible, so openssl's s_client mode fills the gap. openssl s_client establishes an encrypted connection to the specified server and then allows the user to type commands, which are encrypted and sent ("GET /" in the example below); responses from the server are decrypted and displayed. In addition, openssl displays the server's certificate.

www:/Volumes/ julia$ openssl s_client -showcerts -connect
depth=1 /C=US/ST=New York/L=Brooklyn/O=reppep/
verify error:num=19:self signed certificate in certificate chain
verify return:0
Certificate chain
 0 s:/C=US/ST=New York/O=reppep/
   i:/C=US/ST=New York/L=Brooklyn/O=reppep/
 1 s:/C=US/ST=New York/L=Brooklyn/O=reppep/
   i:/C=US/ST=New York/L=Brooklyn/O=reppep/
Server certificate
subject=/C=US/ST=New York/O=reppep/
issuer=/C=US/ST=New York/L=Brooklyn/O=reppep/
No client certificate CA names sent
SSL handshake has read 2224 bytes and written 316 bytes
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 512 bit
    Protocol  : TLSv1
    Cipher    : DHE-RSA-AES256-SHA
    Session-ID: CE1B007F6A88B50ECC70E7FA56289897839A1BF1BFDDD3D1E55BB912D7FFD51F
    Master-Key: 2FB4EC18F5ECA964143304FA3D6194F185FC2C74C91532627264DD7248F261F845E4DBD6E93F27C63D1FE877C0BD9AA4
    Key-Arg   : None
    Start Time: 1182663596
    Timeout   : 300 (sec)
    Verify return code: 19 (self signed certificate in certificate chain)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    <meta http-equiv="refresh" content="1;url=">


<p>You probably want <a href=""></a>.</p>


In some situations, openssl s_client won't be appropriate for troubleshooting SSL/TLS connections; in these cases, ssldump may be more appropriate.

What Comes Next? In Securing Communications with SSL/TLS: Streamlined CA Procedures (cert.command & sign.command) of this article, I will look at some simple scripts to making running a CA more convenient.