Cover V13, i09
sep2004.tar

Real-World Uses for OpenSSL

Ryan Matteson

OpenSSL is an open source toolkit that implements the protocols and algorithms required by the SSL (Secure Socket Layer) and TLS (Transport Layer Security) protocols. The toolkit includes a general-purpose cryptographic API, a full-featured command-line utility, and uses an Apache-style license. In this article, I will introduce the OpenSSL command-line utility and provide several examples of how OpenSSL can be used to secure data and manage digital certificates. Two example shell scripts are included to illustrate how OpenSSL can be used to monitor secure Web servers and provide notification when digital certificates are about to expire.

Acquiring and Installing OpenSSL

The source code for OpenSSL can be acquired from the main OpenSSL Web site at:

http://www.openssl.org/source
or through one of the numerous mirrors. To install OpenSSL from source code, the latest tar archive should be downloaded, uncompressed, and extracted:

$ gunzip openssl-X.X.X.tar.gz
$ tar xfv openssl-X.X.X.tar
$ cd openssl-X.X.X
Once the source code has been extracted, review the INSTALL file. The INSTALL file contains detailed information on compiling OpenSSL and describes the flags available to the build process. To build OpenSSL with the default options, the config and make commands can be executed:

$ ./config
$ make
$ make install
The config command will invoke the Configure script, which is written in Perl. To avoid any issues with the configuration process, double-check that Perl 5.X or higher is installed. Once the build process is complete, the libraries and executables will be available in /usr/local/ssl. To change the default installation location, the "--prefix" option can be passed to the config script:

$ ./config --prefix /opt/openssl
Using OpenSSL
Once OpenSSL is installed, the command-line interface can be accessed with the openssl command:

$ openssl help
openssl:Error: 'help' is an invalid command.

Standard commands
asn1parse     ca          ciphers       crl           crl2pkcs7
dgst          dh          dhparam       dsa           dsaparam
enc           engine      errstr        gendh         gendsa
genrsa        nseq        ocsp          passwd        pkcs12
pkcs7         pkcs8       rand          req           rsa
rsautl        s_client    s_server      s_time        sess_id
smime         speed       spkac         verify        version
x509

Message Digest commands (see the 'dgst' command for more details)
md2           md4         md5           mdc2          rmd160
sha           sha1        

Cipher commands (see the 'enc' command for more details)
aes-128-cbc   aes-128-ecb aes-192-cbc   aes-192-ecb   aes-256-cbc
aes-256-ecb   base64      bf            bf-cbc        bf-cfb
bf-ecb        bf-ofb      cast          cast-cbc      cast5-cbc
cast5-cfb     cast5-ecb   cast5-ofb     des           des-cbc
des-cfb       des-ecb     des-ede       des-ede-cbc   des-ede-cfb
des-ede-ofb   des-ede3    des-ede3-cbc  des-ede3-cfb  des-ede3-ofb
des-ofb       des3        desx          idea          idea-cbc
idea-cfb      idea-ecb    idea-ofb      rc2           rc2-40-cbc
rc2-64-cbc    rc2-cbc     rc2-cfb       rc2-ecb       rc2-ofb
rc4           rc4-40      rc5           rc5-cbc       rc5-cfb
rc5-ecb       rc5-ofb
The help command is not recognized by OpenSSL, so all available menu options are printed. The individual help screens (Standard Commands, Message Digests, and Cipher commands) can be accessed individually with the list-standard-commands, list-message-digest-commands, and list-cipher-commands options:

$ openssl list-standard-commands
$ openssl list-message-digest-commands
$ openssl list-cipher-commands
To get detailed information on each option, please reference the openssl(1) manpage. Now that we know how to invoke the OpenSSL command line, let's have some fun!

Computing and Verifying Checksums

The Internet is used more and more frequently to distribute source code and binary software packages. When one of the software distribution servers is compromised, the integrity of the software packages can come into question. To ensure that the software has not been tampered with, a message digest can be used to create a digital fingerprint of a file. A message digest works by running a variable-length file through a hashing algorithm to produce a fixed-length output (the digital fingerprint). This operation is easy to perform, but reversing the operation is extremely difficult.

Once a fingerprint has been computed, it can be distributed to clients through a secure channel and used to ensure that the contents of a file have not changed.

OpenSSL supports several message digest algorithms, including: MD2, MD4, MD5, SHA, SHA1, MDC2, and RIPEMD-160. Each algorithm can be invoked by passing the algorithm name to the dgst command or passed directly to the openssl command. The following example utilizes the dgst option to compute an MD5 digest of /etc/secure/data:

$ openssl dgst -md5 /etc/secure/data
MD5(/etc/secure/data)= f268fc3e92ef844117365a3368b8fe45
The following example passes the digest algorithm directly to openssl, and generates an MD5 checksum of /etc/secure/data:

$ openssl md5 /etc/secure/data
MD5(/etc/secure/data)= f268fc3e92ef844117365a3368b8fe45
OpenSSL can also be combined with find to produce fingerprints for several files:

$ find /etc -type f | xargs openssl md5 > /etc/secure/md5_sigs.txt
This will create an MD5 hash of all files in the /etc directory. If you need to check whether a file in /etc was modified, you can compare the current fingerprint with the fingerprint calculated above. The file containing the fingerprints should be copied to read-only media and stored in a safe location.

Encrypting Data

Encryption is the process of converting data (often referred to as plaintext) to an alternate form (often referred to as ciphertext) that is indistinguishable from the original. The data encryption process usually requires a key and utilizes a set of algorithms to transform the plaintext data into ciphertext.

Symmetric key algorithms (also referred to as shared secret algorithms) utilize the same key to encrypt and decrypt data. Public key algorithms (also referred to as asymmetric algorithms) utilize different keys for encryption and decryption. Public key algorithms derive their name from the fact that one of the keys (the public key) can be distributed to others, and data encrypted with this key can only be decrypted with the associated private key.

OpenSSL supports several symmetric key algorithms, including: DES, 3DES, IDEA, Blowfish, and AES. Each symmetric-key algorithm can be invoked by passing the algorithm name to the enc command or passing it directly to the openssl command. The following example encrypts the file named passwd with the Blowfish algorithm:

$ openssl bf -e -in /etc/secure/passwd -out /etc/secure/passwd.enc.bf
enter bf-cbc encryption password:
Verifying - enter bf-cbc encryption password
The encrypted version of passwd will be placed in /etc/secure/passwd.enc.bf. The following example utilizes 3DES and the enc command to encrypt the file sensitive_data. The encrypted contents are placed in /etc/secure/sensitive_data.enc.3des:

$ openssl enc -e -3des -in /etc/secure/sensitive_data \
  -out /etc/secure/sensitive_data.enc.3des
enter bf-cbc encryption password:
Verifying - enter bf-cbc encryption password:
On occasion, it may be beneficial to send the contents of an encrypted file to a colleague or friend. The encrypted data is in binary format, which makes it difficult to embed in email.

OpenSSL supports the base64 standard, which can be used to represent binary data as ASCII text. To encrypt a file with the AES-128 algorithm, and base64 encode the contents, the "-base64" and "-aes128" arguments can be passed to openssl:

$ openssl enc -base64 -e -aes128 -in /etc/secure/data \
  -out /etc/secure/data.enc.aes128.b64
enter bf-cbc encryption password:
Verifying - enter bf-cbc encryption password:
If you choose to use email or other insecure data transport facilities to send encrypted data, it is highly recommended that you create a digital signature or fingerprint of the encrypted file. This will ensure that the encrypted contents have not been tampered with during transmission.

Decrypting Data

To decrypt a file that was previously encrypted, the -d option can be passed to the enc option or passed as an argument to the encryption algorithm. The following example shows how to decrypt the file /etc/secure/sensitive_data.enc.3des that was previously encrypted with the 3DES algorithm:

$ openssl enc -des3 -d -in /etc/secure/sensitive_data.enc.3des \
  -out /etc/secure/sensitive_data
This will place the decrypted file contents in the file /etc/secure/sensitive_data. If you want to view the contents of the text file on your terminal, the output of openssl can be piped to your favorite pager:

$ openssl enc -des3 -d -in /etc/secure/sensitive_data.enc.des3 | more
Generating Password File Entries

OpenSSL can be used to generate password hashes through the passwd command. This facility can be used to automate user provisioning or to conduct system-wide password updates. The following example shows how to generate an MD5 hash of the password string "blah":

$ echo blah | openssl passwd -stdin -1
The "-1" option indicates that the MD5 message digest algorithm should be used, and "-stdin" indicates that the passwd will be passed via standard input. If your authentication system does not support MD5, passwords can be created with crypt:

$ echo blah | openssl passwd -stdin -crypt -salt GH
This will generate a crypted version of the password "blah" with the salt "GH."

Digital Certificates

A digital certificate is an electronic "drivers license" that is used to prove the identity of a client or server. Certificate Authorities (CAs) are responsible for issuing digital certificates and proving the identity of the entity requesting the certificate. Digital certificates contain several pieces of information, including: a certificate version, a serial number to uniquely identify the certificate, an attribute (Issuer) to identity the organization who issued the certificate, a range of dates for which the certificate is valid, an attribute (Subject) to identify the site to which the certificate has been issued, and a digital signature. The digital signature is used by clients and servers to verify the authenticity of the certificate, and to ensure that the individual represented by the certificate is actually who they say they are.

When an organization wants to request a digital certificate from a certificate authority, they will need to submit a certificate-signing request (CSR). The certificate-signing request contains a public key, a common name (e.g., www.example.com) to uniquely identify the site, and locality information to identify the organization. The following example shows how to generate a certificate-signing request:

$ openssl req -new -outform PEM -keyform PEM -keyout secret.key \
              -out cert.csr -newkey rsa:1024

Generating a 1024 bit RSA private key
.............++++++
..............................................++++++
writing new private key to 'secret.key'
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) [AU]:US
State or Province Name (full name) [Some-State]:Georgia
Locality Name (eg, city) []:Atlanta
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:www.example.com
Email Address []: sysadmin@example.com
 
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
During the request-generation process, a 1024-bit RSA key pair is generated and various pieces of information are gathered. The OpenSSL utility will prompt for a pass-phrase, which is used to encrypt the contents of the private key. Once the keys are generated, the private key will be PEM encoded and placed in the file secret.key. The certificate-signing request is placed in the file cert.csr. This file contains the public key, locality information, and a common name to uniquely identify the site. You can print the contents of the certificate-signing request with the req command:

$ openssl -req -in cert.csr -text
Once you have verified the certificate signing request, you can submit the contents to your favorite Certificate Authority. The certificate authority will use the contents of this file along with their private key to generate a digital certificate.

Displaying the Contents of a Digital Certificate

Digital certificates can be stored in several formats. Two of the most common formats are PEM (Privacy Enhanced Mail) and DER (Definite Encoding Rules). OpenSSL can print the contents of both certificate formats with the x509 commands. The following example will print the contents of the PEM-encoded certificate cert.crt.pem:

$ openssl x509 -in cert.crt.pem -inform PEM -text -noout
OpenSSL also allows you to print individual attributes of a certificate:

$ openssl x509 -in cert.crt.der -inform DER -noout -enddate
This will print just the expiration data for the certificate cert.crt.der.

Converting Between Certificate Types

As mentioned above, digital certificates can be stored in a variety of formats. This can cause problems when a certificate needs to be migrated between heterogeneous Web servers or distributed between application components. OpenSSL provides the x509 option to convert between PEM- and DER-encoded certificates. The following example will convert a PEM-encoded certificate to DER format:

$ openssl x509 -in cert.crt.pem -inform PEM -out cert.crt.der -outform DER
Once the certificate has been converted, it will be placed in the file cert.crt.der. The following example converts a DER-formatted certificate to PEM format:

$ openssl x509 -in cert.crt.der -inform DER -out cert.crt.pem -outform PEM
The OpenSSL pkcs12 command can be used to import and export certificates stored in a PKCS#12 database. The following example will export a certificate with the alias Server-Cert from a PKCS#12 database:

$ openssl pkcs12 -export Server-Cert -in cert.db.pkcs12 -out cert.crt.p12
Once the certificate has been exported, it can be converted to PEM or DER format with the pkcs12 command:

$ openssl pkcs12 -in cert.crt.p12 -out cert.crt.pem
Monitoring Secure Web Server Connectivity with OpenSSL

Listing 1 shows how OpenSSL can be used to check whether an SSL-enabled Web site is handling new connections. The openssl s_client option is invoked, and an HTTP GET request is passed to the Web server after the SSL connection is set up. If the server fails to return a valid response, a message is logged via syslog, and an email is sent to the on-call pager. This script can run periodically via cron or be modified to run continuously as a daemon at system startup.

Checking for Expired Web Site Certificates

Digital certificates can be deployed to authenticate clients and to prove the identity of a server. When digital certificates are issued, an expiration date is assigned, which ensures that compromised certificates will not have an endless lifetime. During SSL connection establishment, clients and servers will typically check the expiration date assigned to a certificate. When server certificates expire, customers are presented with warning messages, which may cause confusion. Expired certificates may also lead to service disruption. To provide alarming capabilities to combat this problem, I developed ssl-cert-check.

Listing 2 (ssl-cert-check) is a bash script that utilizes GNU date and the openssl s_client command-line option. ssl-cert-check supports interactive and batch operations and can be configured to send email when a certificate is about to expire. ssl-cert-check will print a detailed help screen when invoked without any options:

$ ./ssl-cert-check
Usage: ./ssl-cert-check {{ [ -b ] && [ -f cert_file ] } || { \
  [ -s common_name ] && [ -p port] }} [ -e email ] \
  [ -x expir_days ] [ -q ] [ -a ] [ -h ]
  -a                : Send a warning message through email 
  -b                : Print the expiration date for all 
                      certificates in cert_file (batch mode)
  -e email address  : Email address to send expiration notices
  -f cert file      : File with a list of common names and ports 
                      (eg., blatch.com 443)
  -h                : Print this screen
  -p port           : Port to connect to (interactive mode)
  -s commmon name   : Server to connect to (interactive mode)
  -q                : Don't print anything on the console
  -x days           : Certificate expiration interval 
                      (eg. if cert_date < days)
The following command can be used to view the certificate expiration date for the daemons.net Web server running on port 443:

 $ ./ssl-cert-check -s www.daemons.net -p 443

Host                      Status    Expires         Days Left
www.daemons.net:443       Valid     May 24 2005     363
The script can also be run in batch mode, which will cause ssl-cert-check to process a full list of domain and TCP port combinations:

$ cat ssldomains
www.spotch.com 443
mail.daemons.net 995
www.daemons.net 443

$ ./ssl-cert-check -b -f ssldomains 

Host                      Status    Expires         Days Left
www.spotch.com:443        Down      ?                ?
mail.daemons.net:995      Expired   Oct 30 2002     -574
www.daemons.net:443       Valid     May 24 2005      363
ssl-cert-check also provides capabilities to alarm (via email) when a certificate is getting ready to expire. This capability combined with the quiet mode of operation will allow ssl-cert-check to be easily integrated into a scheduling facility:

$ ./ssl-cert-check -b -f ssldomains -q -a -x 90 -e matty@daemons.net
This will cause ssl-cert-check to check all the domains listed in the file ssldomains and send email to matty@daemons.net if a certificate will expire in 90-days or less.

Conclusion

In this article, I introduced a few examples of how OpenSSL can be used to secure data and manage digital certificates. I also provided two example scripts that can be used to check for certificate expiration and the status of an SSL-enabled Web server. Large portions of most bookstores and complete courses have been created to explain cryptography, encryption, SSL, and TLS. This article barely scratched the surface of what is available. As with all software, the examples should be tested thoroughly prior to use in any production environment.

Acknowledgements

I thank the OpenSSL developers and all the folks who have put time and energy into the design and implementation of the cryptographic algorithms and protocols discussed in this article.

References

Web Sites:

OpenSSL: http://www.openssl.org

ssl-cert-check: http://www.daemons.net/software

TLS 1.0 RFC: http://www.ietf.org/html.charters/tls-charter.html

Books:

Schneier, Bruce. 1996. Applied Cryptography. John Wiley & Sons.

Stallings, William. 2003. Cryptography and Network Security: Principles and Practice. Prentice Hall.

Thomas, Stephen. 2000. SSL & TLS Essentials: Securing the Web. John Wiley & Sons.

Viega, John; Matt Messier; and Pravir Chandra. Network Security with OpenSSL: Cryptography for Secure Communications. O'Reilly & Associates.

Ryan Matteson has been a UNIX systems administrator for eight years. He specializes in network security, Web technologies, Storage Area Networks, high-availability systems, Linux, and the Solaris operating systems. Questions and comments about this article can be addressed to: matty91@bellsouth.net.