Real World Uses For OpenSSL


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. This article will introduce the OpenSSL command line utility, and provide several examples of how OpenSSL can be used to secure data, manage digital certificates, and debug SSL communications. 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 website, 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, the INSTALL file should be reviewed. 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, you will want to double check that perl 5.X or higher is installed. Once the build process completes, the libraries and executables will be available in /usr/local/ssl. If you wish to change the default installation location, the “–prefix” option can be appended to the config command.

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 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 taking a variable length file, and running it 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 Ripe MD160. 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 if 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 taking data (often referred to as plaintext) and converting it 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 passed 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 wish 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/services.bf | 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 the certificate is valid, an attribute (Subject) to identify the site the certificate has been issued to, and a digital signature. The digital signature is used by clients and servers 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, two 1024-bit RSA keys are 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 signature. The certificate authority will also assign an expiration date, and incorporate additional attributes to uniquely identify the certificate authority.

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 PEM -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.der.crt. 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

The ssl-service-check script can be used to check if an SSL-enabled website is handling new connections. The openssl s_client option is invoked, and an HTTP GET request is passed to the web server . If the server fails to return a valid response, a message is logged via syslog, and an E-mail is send to the on call pager. This script can run periodically via cron, or modified to run continuously as a daemon on system startup.

Checking for expired website 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 potential confusion. Expired certificates may also lead to service disruption. To provide alarming capabilities to combat this problem, I developed ssl-cert-check.

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 [ -e email address ] [ -x days ] [-q] [-a] [-h] [-i] [-n]
       { [ -s common_name ] && [ -p port] } || { [ -f cert_file ] } || { [ -c certificate file ] }

  -a                : Send a warning message through E-mail 
  -c cert file      : Print the expiration date for the PEM or PKCS12 formatted certificate in cert file
  -e E-mail address : E-mail address to send expiration notices
  -f cert file      : File with a list of FQDNs and ports
  -h                : Print this screen
  -i                : Print the issuer of the certificate
  -k password       : PKCS12 file password
  -n                : Run as a Nagios plugin
  -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 prefetch.net web server running on port 443:

$ ssl-cert-check -s prefetch.net -p 443

Host                           Status   Expires              Days Left
prefetch.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.prefetch.net 995
prefetch.net 443

$ ssl-cert-check -b -f ssldomains

Host                           Status   Expires              Days Left
www.spotch.com:443             Down     ?                    ?   
mail.prefetch.net:995          Expired  Oct 30 2002          -574 
prefetch.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 root

This will cause ssl-cert-check to check all the domains listed in the file ssldomains, and send email to root if a certificate will expire in 90-days or less.

Conclusion

In this article, I attempted to cover a few examples of how OpenSSL can be used to secure data and troubleshoot SSL communications. 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.

References

The following references were used while writing this article:

Acknowledgements

Ryan would like to 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.

Originally published in the September ‘04 issue of SysAdmin Magazine