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.
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.
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!
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.
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.
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
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.”
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.
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.
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
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.
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.
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.
The following references were used while writing this article:
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