OpenSSL is primarily a library that is used by developers to include support for strong cryptography in their programs, but it is also a tool that provides access to much of its functionality from the command line. The command-line tool makes it easy to perform common operations, such as computing the MD5 hash of a file’s contents. What’s more, the command-line tool provides the ability to access much of OpenSSL’s higher-level functionality from shell scripts on Unix or batch files on Windows. It also provides a simple interface for languages that do not have native SSL bindings, but can run shell commands.
There’s no question that the command-line tool can seem quite complex to the uninitiated. It sports a large set of commands, and even larger sets of options that can be used to further refine and control those commands. OpenSSL does come with some documentation that covers most of the available commands and options supported by the command-line tool, but even that documentation can seem intimidating. Indeed, when you’re trying to discover the magical incantation to create a self-signed certificate, the documentation provided with OpenSSL does not provide an intuitive way to go about finding that information, even though it is in fact buried in there.
This chapter contains an overview of the command-line tool, providing some basic background information that will help make some sense of how the tool’s command structure is organized. We’ll also provide a high-level overview of how to accomplish many common tasks, including using message digests, symmetric ciphers, and public key cryptography. The Appendix contains a reference for the commands that the command-line tool supports.
We will refer to the command-line tool throughout this book, and, in some instances, we also provide examples that are more complex than what we’ve included in this chapter. In particular, Chapter 3 makes extensive use of the command-line tool.
The command-line tool
executable is aptly named
openssl
on Unix, and
openssl.exe
on Windows. It has two modes of operation: interactive and batch.
When the program is started without any options, it will enter
interactive mode. When operating in interactive mode, a prompt is
displayed indicating that it is ready to process your command. After
each command is completed, the prompt is redisplayed, and
it’s once again ready to process another command.
The program can be exited by simply issuing the
quit
command. Commands entered in interactive mode
are handled in precisely the same manner as if you’d
entered them from the command line in batch mode; the
only difference is that you don’t need to type
“openssl” before each command.
We’ll normally operate the tool in batch mode in our
examples, but if you feel more comfortable using the interactive
mode, that’s fine.
The first part of a command is the name of the command itself. It’s followed by any options that you wish to specify, each one separated by a space. Options normally begin with a hyphen and often require a parameter of their own, in which case the parameter is placed after a space.
Unless indicated otherwise, the order in which you specify options is not significant. There are only a small number of cases in which the order is significant, usually because a specific option must appear on the command line as the last option specified.
The command-line tool provides a large number of options for each of its many commands. Remembering the option names, their defaults if they’re not specified, and even to include them with a command to obtain the desired result can be difficult, if not downright frustrating at times. The task of managing options is made considerably simpler using configuration files.
OpenSSL includes a default configuration file that is normally used
unless an alternate one is specified. The settings in the default
configuration are all quite reasonable, but it can often be useful to
replace them with settings that are better tailored to your own
needs. The location of the default configuration file varies greatly,
depending on the operating system that you’re using
and how OpenSSL was built and installed. So, unfortunately, we
can’t point you to any one specific location to find
it. Although it is not at all intuitive, the command-line tool will
tell you where the default configuration file is located if you issue
the ca
command without any options. Any errors
that are issued due to the lack of options may be safely ignored.
Unfortunately, only three of the many commands supported by the
command-line tool make any use of the configuration file. On the
bright side, the three commands that do use it are perhaps the most
complex of all of the supported commands, and accept the greatest
number of options to control their behavior. The commands that do
support the configuration file are
ca
, req
, and
x509
(we discuss these commands below).
An OpenSSL configuration file is organized in sections. Each section contains a set of keys, and each key has an associated value. Sections and keys are both named and case-sensitive. A configuration file is parsed from top to bottom with sections delimited by a line containing the name of the section surrounded by square brackets. The other lines contain key and value pairs that belong to the most recently parsed section delimiter. In addition, an optional global section that is unnamed occurs before the first named section in the file. Keys are separated from their associated value by an equals sign (=).
For the most part, whitespace is insignificant. Comments may begin anywhere on a line with a hash mark (#), and they end at the end of the line on which they begin. Key and section names may not contain whitespace, but they may be surrounded by it. Leading and trailing whitespace is stripped from a value, but any whitespace in the middle is significant. Example 2-1 shows an excerpt from the default OpenSSL configuration file.
[ ca ] default_ca = CA_default # The default ca section #################################################################### [ CA_default ] dir = ./demoCA # 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/cacert.pem # The CA certificate serial = $dir/serial # The current serial number crl = $dir/crl.pem # The current CRL private_key = $dir/private/cakey.pem# The private key RANDFILE = $dir/private/.rand # private random number file x509_extensions = usr_cert # The extentions to add to the cert # Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs # so this is commented out by default to leave a V1 CRL. # crl_extensions = crl_ext 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
In the example, you’ll notice the use of
$dir
. Used in a value, a key name preceded by a
dollar sign is known as a macro, and is replaced with the value for
that key. Only macros using keys that are defined within the same
section or in the global section will be expanded. Additionally, the
key must be defined before you use it as a macro in a value, because
the macro is expanded as the configuration file parses rather than
when the value is used. Macros are particularly useful when you have
a number of values referencing the same path in a filename.
Although only a few commands currently make any use of a configuration file, other commands may be modified in the future to take advantage of them. Each command that currently uses the configuration file reads its base configuration information from a section that shares the name of the command. Other sections that are not named after a command may exist, and quite frequently, they do. Many keys’ values are interpreted as the name of a section to use for finding more keys. We’ll see frequent examples of this as we examine the commands that do use the configuration file in detail.
In Chapter 1, we introduced cryptographic hash functions, better known as message digest algorithms, which can be used for computing a checksum of a block of data. OpenSSL includes support for MD2, MD4, MD5, MDC2, SHA1 (sometimes called DSS1), and RIPEMD-160. SHA1 and RIPEMD-160 produce 160-bit hashes, and the others all produce 128-bit hashes. Unless you have a need for compatibility, we recommend that you use only SHA1 or RIPEMD-160. Both SHA1 and RIPEMD-160 provide excellent security for general-purpose use, but SHA1 is significantly more common. MD5 is a very popular message digest algorithm, but it does not have a good security margin for all applications. We discuss message digests in detail in Chapter 7.
OpenSSL handles SHA1 oddly. There are places where you must refer to
it as DSS1 (the dgst
command, described later),
and there are places where you cannot refer to it as DSS1 (everywhere
else). This is a limitation of the implementation. Use SHA1 as the
name, unless we specifically mention that you need to use DSS1.
The command-line tool provides commands for using most of the
supported algorithms. The dgst
command is the main
command for accessing message digests, but most of the algorithms can
be accessed using a command of the same name as the algorithm. The
exception is
RIPEMD-160, which is named
rmd160
.
When using the dgst
command, the algorithm is specified
using an option with the name of the algorithm, with the exception of
RIPEMD-160, which also uses the name rmd160
for
this interface. Regardless of the algorithm or form of the command,
each of the algorithms accepts the same options to control how the
command will function.
The default operation performed with any of the message digest
commands is computing a hash for a block of data. That block of data
can be read from stdin
, or it can be one or more
files. When more than one file is used, a separate hash is computed
for each file. By default, the computed hash or hashes are written in
hexadecimal format to stdout
, unless an alternate
output file is specified.
In addition to computing hashes, the message digest commands can also be used for signing and verifying signatures. When signing or verifying a signature, only one file should be used at a time; otherwise, the signatures will run together and end up being difficult to separate into a usable form. When signing, a signature is generated for the hash of the file to be signed. A private key is required to sign, and either RSA or DSA may be used. When you use a DSA private key, you must use the DSS1 message digest (even though it is the same as the SHA1 algorithm). You may use any algorithm other than DSS1 with an RSA private key. Verifying a signature is simply the reverse of signing. Normally, a public key is required to verify a signature, but a private key will work, too, because a public key can be derived from the private key, but not vice versa! When verifying a signature with an RSA key, public or private, you’ll also need to know which message digest algorithm was used to generate the signature.
The following examples illustrate the use of the message digest commands:
$ openssl dgst -sha1 file.txt
Computes an SHA1 hash for the file named
file.txt and write it to
stdout
in hexadecimal form.
$ openssl sha1 -out digest.txt file.txt
Computes an SHA1 hash for the file named file.txt and write it in hexadecimal form to the file named digest.txt.
$ openssl dgst -dss1 -sign dsakey.pem -out dsasign.bin file.txt
Signs the SHA1 (DSS1) hash of the file named file.txt using the DSA private key in the file dsakey.pem and write the signature out to the file dsasign.bin. The PEM file format is a widely used format for storing cryptographic objects such as private keys, certificates, and so on. The “bin” extension indicates that the output is raw binary.
$ openssl dgst -dss1 -prverify dsakey.pem -signature dsasign.bin file.txt
Verifies the signature of the file named file.txt that is contained in the file dsasign.bin using the SHA1 (DSS1) message digest algorithm and the DSA private key from the file dsakey.pem.
$ openssl sha1 -sign rsaprivate.pem -out rsasign.bin file.txt
Signs the SHA1 hash of the file named file.txt using the RSA private key in the file rsaprivate.pem and write the signature out to the file rsasign.bin.
$ openssl sha1 -verify rsapublic.pem -signature rsasign.bin file.txt
Verifies the signature of the file named file.txt that is contained in the file rsasign.bin using the SHA1 message digest algorithm and the RSA public key from the file rsapublic.pem.
OpenSSL supports a wide variety of symmetric ciphers. Of course, these ciphers are also available for use with the command-line tool. Many of the large number of ciphers are variations of a base cipher. The basic ciphers supported by the command-line tool are Blowfish, CAST5, DES, 3DES (Triple DES), IDEA, RC2, RC4, and RC5. Version 0.9.7 of OpenSSL adds support for AES. Most of the supported symmetric ciphers support a variety of different modes, including CBC, CFB, ECB, and OFB. For each cipher, the default mode is always CBC if a mode is not explicitly specified. Each of the supported symmetric ciphers and their various modes of operation are discussed in detail in Chapter 6. In particular, it is important to mention that you should generally never use ECB, because it is incredibly difficult to use securely.
The enc
command is the main command for
accessing symmetric ciphers, but each cipher can
also be accessed using a command of the same name as the cipher. With
the enc
command, the cipher is specified using an
option with the name of the cipher. Regardless of the cipher or form
of the command that is used, each of the ciphers accepts the same
options to control how the command will function. In addition to
providing encryption and decryption of data with symmetric ciphers,
the base64
command or option to the
enc
command can also be used for encoding and
decoding of data in base64.
The default operation to be
performed with any of the cipher commands is to encrypt or base64
encode the data. Normally, data is read from stdin
and written to stdout
, but input and output files
may be specified. Only a single file can be encrypted, decrypted,
base64 encoded, or base64 decoded at a time. When encrypting or
decrypting, an option can be specified to perform base64 encoding
after encryption or base64 decoding before decryption.
Each of the ciphers requires a key when encryption or decryption is performed. Recall from the brief discussion of symmetric ciphers in Chapter 1 that the key is what provides the security of a symmetric cipher. In contrast with traditional cryptographic techniques, modern cipher algorithms are widely available to be scrutinized by anyone that has the time and interest. The key used to encrypt data must be known only to you and the intended recipient or recipients of the encrypted data.
A password is often used to
derive a key and initialization vector that will encrypt or decrypt
the data. It is also possible to specify the key and initialization
vector to be used explicitly, but supplying that information on your
own is often prone to error. In addition, different ciphers have
different key requirements, so supplying your own key requires
in-depth knowledge of the particular cipher. The password can be
specified with the pass
option, according to the
general guidelines for passwords and passphrases outlined later in
this chapter. If no password or key information is specified, the
tool will present a prompt to obtain it.
If you specify a password or passphrase to derive the key and initialization vector, the command-line tool uses a standard OpenSSL function to perform the task. Essentially, the password or passphrase that you specify is combined with a salt . The salt that is used in this case is simply eight random bytes. The MD5 hash of the combined salt and password or passphrase is then computed and broken into two parts, which are then used as the key and initialization vector.
The following examples illustrate the use of the symmetric cipher commands:
$ openssl enc -des3 -salt -in plaintext.doc -out ciphertext.bin
Encrypts the contents of the file plaintext.doc using DES3 in CBC mode and places the resulting ciphertext into ciphertext.bin. Since no password or key parameters were specified, a prompt for a password from which a key can be derived will be presented.
$ openssl enc -des3-ede-ofb -d -in ciphertext.bin -out plaintext.doc -pass pass:trousers
Decrypts the contents of the file ciphertext.bin using DES3 operating in OFB mode and places the resulting plaintext into plaintext.doc. The password “trousers” will be used to decrypt the file. Note that this example will not successfully decrypt the file from the previous example, since we used a different mode of encryption (CBC instead of OFB).
$ openssl bf-cfb -salt -in plaintext.doc -out ciphertext.bin -pass env:PASSWORD
Encrypts the contents of the file plaintext.doc using the Blowfish cipher in CFB mode and places the resulting ciphertext into ciphertext.bin. The contents of the environment variable PASSWORD will be used for the password to generate the key.
$ openssl base64 -in ciphertext.bin -out base64.txt
Encodes the contents of the file ciphertext.bin in base64 and writes the result to the file base64.txt.
$ openssl rc5 -in plaintext.doc -out ciphertext.bin -S C62CB1D49F158ADC -iv E9EDACA1BD7090C6 -K 89D4B1678D604FAA3DBFFD030A314B29
Encrypts the contents of the file plaintext.doc using the RC5 cipher in CBC mode and places the resulting ciphertext into ciphertext.bin. The specified salt, key, and initialization vector will be used to encrypt the plaintext. Keys are specified by their hexadecimal representation.
The Appendix gives a complete list of algorithms used to perform symmetric encryption.
The SSL protocol relies heavily on a variety of different cryptographic algorithms, including message digest algorithms, symmetric ciphers, and public key cryptography. Its use of most of these algorithms is generally done without the need for any human intervention. A common exception, though, is its use of public key cryptography. For example, in order for a server to employ the SSL protocol, it requires a private key and a certificate . The certificate contains the public key that matches the server’s private key. These keys must be created as part of the process for configuring the server to use SSL, and they are frequently not created automatically. Instead, they must be created by whoever is configuring the server.
SSL isn’t the only protocol that makes use of public key cryptography. Most modern software that supports encrypted communications uses it, too. Some of the more popular examples include SSH, PGP (Pretty Good Privacy), and S/MIME. All of these examples use public key cryptography in some form, and we’re overlooking many other applications as well. We discuss OpenSSL’s support for public key cryptography in detail in Chapter 8.
Diffie-Hellman is used for key agreement . In simple terms, key agreement is the exchange of information over an insecure medium that allows each of the two parties in a conversation to compute a value that is typically used as the key for a symmetric cipher. By itself, Diffie-Hellman cannot be used for encryption or authentication; it only provides secrecy. Because the exchange of information takes place over an insecure medium, it should never be used by itself. Some means of authenticating the parties in the conversation should also be used.
Diffie-Hellman works by first creating a set of parameters that are agreed upon by both parties in the conversation. The parameters, consisting of a randomly chosen prime number and a generator value that is typically specified as either 2 or 5, are public and can be either agreed upon before the conversation begins or exchanged as part of the conversation. Using the agreed-upon parameters, each party computes a public and private key. As its name implies, the private key is never shared with anyone. The parties exchange their public keys, and then each party can compute the shared secret using their private key and the peer’s public key.
The command-line tool provides a command for generating
Diffie-Hellman parameters, but the only method for generating keys is
deprecated, and should not be used. OpenSSL 0.9.5 added the
dhparam
command, and in doing so, deprecated
the two commands dh
and gendh
, which
were capable of generating Diffie-Hellman parameters and keys,
respectively. As of this writing, the two deprecated commands are
still accessible in OpenSSL 0.9.7, but because
they’re deprecated, we’ll pretend
that they do not exist, because they’re likely to be
completely removed from the next release of OpenSSL. Unfortunately,
the new dhparam
command does not support the
generation of Diffie-Hellman keys, but it is likely that future
versions will add support for it.
The following examples illustrate the use of the Diffie-Hellman commands:
$ openssl dhparam -out dhparam.pem -2 1024
Generates a new set of Diffie-Hellman parameters using a generator of 2 and a random 1,024-bit prime, and writes the parameters in PEM format to the file dhparam.pem.
$ openssl dhparam -in dhparam.pem -noout -C
Reads a set of Diffie-Hellman parameters from the file
dhparam.pem and writes a C code representation
of the parameters to stdout
.
As its name implies, the Digital Signature Algorithm (DSA) is used for creating and verifying digital signatures. It provides authentication, but cannot be used for encryption or secrecy. DSA is frequently used in combination with Diffie-Hellman. Two parties in a conversation can exchange DSA public keys before the conversation begins (or during the conversation using certificates, as we’ll explain in Chapter 3) and use the DSA keys to authenticate the communication of Diffie-Hellman parameters and keys. Combining Diffie-Hellman with DSA provides authentication and secrecy, and by using the shared secret resulting from the Diffie-Hellman exchange as a key, a symmetric cipher can then be used for encryption.
Just like Diffie-Hellman, DSA also requires parameters from which keys are generated. There is no harm in making the parameters used to generate a key pair public, but there’s equally no compelling reason to do so. Only the private key that is generated must be kept private, as is implied by its name. The public key is the only thing that really needs to be shared with any party that wishes to verify the authenticity of anything signed with a private key.
Three commands are provided by the command-line tool for generating
DSA parameters and keys, as well as for examining and manipulating
them. The dsaparam
command is used to generate and examine
DSA parameters. Its function and options are not unlike those of the
dhparam
command. One major difference between the
two is that the dsaparam
command also provides an
option to generate a private DSA key. The private key resulting from
the dsaparam
command will be unencrypted, which
means that neither a password nor a passphrase will be required to
decrypt and make use of it.
The gendsa
command is used for generating private
keys from a set of DSA parameters. By default, the generated private
key will not be encrypted, but options are available that allow the
key to be encrypted using any one of the DES, 3DES, or IDEA ciphers.
No options are provided for specifying the password or passphrase to
use for encryption on the command line, so encrypted DSA private key
generation cannot be easily automated.
Both the dsaparam
and gendsa
commands are capable of generating private keys, either encrypted or
not, but neither of them has the capability for generating a public
key, which is required in order for DSA to provide any utility. The
dsa
command provides the means by which a
public key can be generated from a private key. It also allows
changes to be made to the encryption on a private key. For private
keys that are not encrypted, encryption can be added, and for private
keys that are already encrypted, the password or passphrase can be
changed, as well as the encryption cipher that’s
used to encrypt it. It’s also possible to remove the
encryption on a private key with this command.
The following examples illustrate the use of the DSA commands:
$ openssl dsaparam -out dsaparam.pem 1024
Generates a new set of DSA parameters and writes them to the file dsaparam.pem. The length of the prime and generator parameters will be 1,024 bits.
$ openssl gendsa -out dsaprivatekey.pem -des3 dsaparam.pem
Generates a new DSA private key using the parameters from the file dsaparam.pem, encrypts the newly generated private key with the 3DES cipher, and writes the result out to the file dsaprivatekey.pem.
$ openssl dsa -in dsaprivatekey.pem -pubout -out dsapublickey.pem
Computes the public key that corresponds to the private key contained in the file dsaprivatekey.pem and writes the public key out to the file dsapublickey.pem.
$ openssl dsa -in dsaprivatekey.pem -out dsaprivatekey.pem -des3 -passin
pass:oldpword -passout pass:newpword
Reads a private key from the file dsaprivatekey.pem, decrypts it using the password “oldpword”, re-encrypts it using the password “newpword”, and writes the newly encrypted private key back out to the file dsaprivatekey.pem.
RSA is the most popular public key algorithm currently in use, despite the fact that it was encumbered by patent restrictions until the patent expired in September of 2000. It is named after its creators, Ron Rivest, Adi Shamir, and Leonard Adleman. One of the reasons that it is so popular is because it provides secrecy, authentication, and encryption all in one neat little package.
Unlike Diffie-Hellman and DSA, the RSA algorithm does not require parameters to be generated before keys can be generated, which simplifies the amount of work that is necessary to generate keys, and authenticate and encrypt communications. The command-line tool provides three commands for generating, examining, manipulating, and using RSA keys.
OpenSSL’s
genrsa
command is used to generate a new RSA
private key. Generation of an RSA private key involves finding two
large prime numbers, each approximately half the length of the key. A
typical key size for RSA is 1,024. We don’t
recommend that you use smaller key lengths or key lengths greater
than 2,048 bits. By default, the generated private key will be
unencrypted, but the command does have the ability to encrypt the
resultant key using DES, 3DES, or IDEA.
The rsa
command is used to manipulate and
examine RSA keys and is the RSA version of the dsa
command for DSA keys. It is capable of adding, modifying, and
removing the encryption protecting an RSA private key. It is also
capable of producing an RSA public key from a private key. The
command can also be used to display information about a public or
private key.
The rsautl
command provides the ability to use an
RSA key pair for encryption and signatures. Options are provided for
encrypting and decrypting data, as well as for signing and verifying
signatures. Remember that signing is normally performed on hashes, so
this command is not useful for signing large amounts of data, or even
more than 160 bits of data. In general, we do not recommend that you
use this command at all for signing data. You should use the
enc
command instead. Additionally, encryption and decryption using RSA is
slow, and for that reason, it should not be used on its own. Instead,
it is commonly used to encrypt a key for a symmetric cipher. This is
discussed in more detail in Chapter 8.
The following examples illustrate the use of the RSA commands:
$ openssl genrsa -out rsaprivatekey.pem -passout pass:trousers -des3 1024
Generates a 1,024-bit RSA private key, encrypts it using 3DES and a password of “trousers”, and writes the result to the file rsaprivatekey.pem.
$ openssl rsa -in rsaprivatekey.pem -passin pass:trousers -pubout -out rsapublickey.pem
Reads an RSA private key from the file rsaprivatekey.pem, decrypts it using the password “trousers”, and writes the corresponding public key to the file rsapublickey.pem.
$ openssl rsautl -encrypt -pubin -inkey rsapublickey.pem -in plain.txt -out cipher.txt
Using the RSA public key from the file rsapublickey.pem, the contents of the file plain.txt are encrypted and written to the file cipher.txt.
$ openssl rsautl -decrypt -inkey rsaprivatekey.pem -in cipher.txt -out plain.txt
Using the RSA private key from the file rsaprivatekey.pem, the contents of the file cipher.txt are decrypted and written to the file plain.txt.
$ openssl rsautl -sign -inkey rsaprivatekey.pem -in plain.txt -out signature.bin
Using the RSA private key from the file rsaprivatekey.pem, the contents of the file plain.txt are signed, and the signature is written to the file signature.bin.
$ openssl rsautl -verify -pubin -inkey rsapublickey.pem -in signature.bin -out plain.txt
Using the RSA public key from the file rsapublickey.pem, the signature in the file signature.bin is verified, and the original unsigned data is written out to the file plain.txt.
S/MIME is a competing standard to PGP (Pretty Good Privacy) for the secure exchange of email. It provides authentication and encryption of email messages using public key cryptography, as does PGP. One of the primary differences in the two standards is that S/MIME uses a public key infrastructure to establish trust, whereas PGP does not. Trust is established when there is some means of proving that someone with a public key is actually that person, and that the key belongs to that person.
PGP was written and released in 1991 by Phil Zimmermann. It quickly became the de facto standard for the secure exchange of information throughout the world. Today, PGP has become an open standard known as OpenPGP, and is documented in RFC 2440. Because PGP does not rely on a public key infrastructure to establish trust, it is easy to set up and use. Today, one of the most common methods of establishing trust is obtaining someone’s public key either from a key server or directly from that person, and manually verifying the key’s fingerprint by comparing it with the fingerprint information obtained directly from the key’s owner over some trusted medium, such as the telephone or paper mail. It is also possible to sign a public key, so if Alice trusts Bob’s key, and Bob has used his key to sign Charlie’s key, Alice knows that she can trust Charlie’s key if the signature matches Bob’s. PGP works for small groups of people, but it does not scale well.
S/MIME stands for Secure Multipurpose Internet Mail Exchange. RSA Security developed the initial version in 1995 in cooperation with several other software companies; the IETF developed Version 3. Like PGP, S/MIME also provides encryption and authentication services. A public key infrastructure is used as a means of establishing trust, which means that S/MIME is capable of scaling to support large groups of people. The downside is that it requires the use of a public key infrastructure, which means that it is slightly more difficult to set up than PGP because a certificate must be obtained from a Certification Authority that is trusted by anyone using the certificate to encrypt or verify communications. Public keys are exchanged in the form of X.509 certificates, which require a Certification Authority to issue certificates that can be used. Because a Certification Authority is involved in the exchange of public keys, trust can be established if the certificate that issued a certificate is trusted. Public key infrastructure is discussed in detail in Chapter 3.
S/MIME messages may have multiple recipients. For an encrypted message, the body of the message is encrypted using a symmetric cipher, and the key for the symmetric cipher is encrypted using the recipient’s public key. When multiple recipients are involved, the same symmetric key is used, but the key is encrypted using each recipient’s public key. For example, if Alice sends the same message to Bob and Charlie, two encrypted copies of the key for the symmetric cipher are included in the message. One copy is encrypted using Bob’s public key, and the other is encrypted using Charlie’s public key. To decrypt a message, the recipient’s certificate is required to determine which encrypted key to decrypt.
The command-line tool provides the
smime
command, which supports encryption,
decryption, signing, and verifying S/MIME v2 messages (support for
S/MIME v3 is limited and is not likely to work). Email applications
that do not natively support S/MIME can often be made to support it
by using the command-line tool’s
smime
command to process incoming and outgoing
messages. The smime
command does have some
limitations, and it is not recommended in any kind of production
environment. However, it provides a good foundation for building a
more powerful and fully featured S/MIME implementation.
The following examples illustrate the use of the S/MIME commands:
$ openssl smime -encrypt -in mail.txt -des3 -out mail.enc cert.pem
Obtains a public key from the X.509 certificate in the file cert.pem and encrypts the contents of the file mail.txt using that key and 3DES. The resulting encrypted S/MIME message is written to the file mail.enc.
$ openssl smime -decrypt -in mail.enc -recip cert.pem -inkey key.pem -out mail.txt
Obtains the recipient’s public key from the X.509 certificate in the file cert.pem and decrypts the S/MIME message from the file mail.enc using the private key from the file key.pem. The decrypted message is written to the file mail.txt.
$ openssl smime -sign -in mail.txt -signer cert.pem -inkey key.pem -out mail.sgn
The signer’s X.509 certificate is obtained from the file cert.pem, and the contents of the file mail.txt are signed using the private key from the file key.pem. The certificate is included in the S/MIME message that is written to the file mail.sgn.
$ openssl smime -verify -in mail.sgn -out mail.txt
Verifies the signature on the S/MIME message contained in the file mail.sgn and writes the result to the file mail.txt. The signer’s certificate is expected to be included as part of the S/MIME message.
Many commands (particularly those that involve a private key) require a password or passphrase to complete successfully, usually to decrypt a key that is stored securely on a disk. Normally, the command-line tool will prompt you to enter a password or passphrase when appropriate, even if you’re not running the tool in interactive mode. The need for a password or passphrase to be physically entered by someone using the keyboard at the computer when it’s needed makes using the tool for automated processes difficult, to say the least.
Fortunately, there’s
a solution. Many of the commands accept options that allow you to
specify the necessary password or passphrase. Unfortunately, the
options are not consistently named, so you need to use the right
option with the right command. In general, the options
passin
and passout
are used. No
matter what the option is named, it requires a parameter that
specifies how the password or passphrase will be obtained. A variety
of sources may be specified, some of them not very secure at all.
None of them provides the level of security that someone sitting at
the computer and typing in the password or passphrase does, but you
need to determine for yourself what you consider to be an acceptable
risk.
This method for reading a password is distinctly different from the
default method. The default method reads passwords from the actual
terminal device (TTY), thus explicitly avoiding input redirection
from the command line. The stdin
method for
providing passwords allows for such input redirection.
This method can be used to supply the password or passphrase directly on the command line itself. If your password or passphrase contains spaces, you typically need to enclose the whole of the parameter in quotes, but the precise method of handling such a situation may differ on the platform that you’re using.
We strongly recommend that you do not use this method, for two
reasons. First, if you’re using batch mode, the
command line for a process is readily accessible to any other process
that is running on the system. In fact, on such systems there are
commands specifically designed for this purpose, such as the
ps
command on Unix systems. Second, if
you’re using this as part of a script, it usually
means the password or passphrase will be contained in your script,
which also means that the password or passphrase can be easily
compromised.
This method obtains the password or passphrase from an environment variable. We recommend against using this method, although not as strongly as we do against specifying the password or passphrase directly on the command line. This method is slightly more secure, but a process’s environment is still available to other processes on some operating systems under the right circumstances.
This method obtains the password or passphrase by reading it from the named file. The file containing the password or passphrase should be well protected, denying read access to any user on the system other than the owner of the file. Additionally, on Unix systems steps should be taken to ensure that each directory that parents the file does not allow access to a user other than the owner.
This method obtains the password or passphrase by reading it from the specified file descriptor. This method is really useful only when the tool is launched from another process and not directly from the command line because the tool’s process must have inherited the file descriptor from its parent in order for it to gain access.
In Chapter 1, we briefly discussed the need for cryptographic randomness. We’ll expand on this discussion in Chapter 4. For now, we’ll just deal with how to seed the OpenSSL PRNG properly from the command line. Because many of the cryptographic commands depend on random numbers, it is important that the PRNG be seeded properly.
The command-line tool will attempt to seed the PRNG on its own, but it may not always be able to do so. When the PRNG is not properly seeded, the tool will emit a warning message indicating that the random numbers it generates will be predictable. Additionally, you may wish to use a more conservative seeding mechanism than the one used by default.
On Windows systems, a variety of sources will be used to seed the PRNG, including the contents of the screen. None of these sources is particularly entropic, and depending on the version of Windows that you’re using, the entropy sources vary. Unix systems that have a device named /dev/urandom will use that device to obtain entropy for seeding the PRNG. Most modern versions of Unix provide support for this device, which we’ll discuss in detail in Chapter 4. In addition, beginning with Version 0.9.7, OpenSSL will also attempt to seed the PRNG by connecting to an EGD socket to obtain entropy. By default, OpenSSL is built with four well-known names for sockets that it will attempt a connection with.
In addition to the base entropy sources, the command-line tool will
also look for a file to obtain seed data from. If the
RANDFILE
environment variable is
set, its value will be used as the name of the file to use for
seeding the PRNG. If it is not set, a default filename of
.rnd will be used, and the value of the
HOME
environment variable will be used to specify
the location of that file. If the HOME
environment
variable is not set, as is often the case on non-Unix systems, the
current directory will be used to find the file. Once the name of the
file has been determined, the contents of that file will be loaded
and used to seed the PRNG if it exists.
Many of OpenSSL’s commands require that its PRNG be
properly seeded so that the random numbers it generates are
unpredictable. In particular, any of the commands that generate key
pairs always require unpredictable random numbers in order for them
to be effective. When the tool is unable to seed the PRNG on its own,
the tool provides an option named
rand
that can be used to provide additional
entropy sources.
The rand
option requires a parameter that contains
a list of files to be used as entropy sources. The list may be as
short as a single file, or as long as the number of filenames you can
fit on the command line. Each file in the list is separated by a
platform-dependent separator character rather than a space. The
separator character is a semi-colon (
;) on Windows, a comma (,) on OpenVMS,
and a colon (:) on all other platforms. On Unix systems, each
filename in the list is first checked to see if it is an Entropy
Gathering Daemon (EGD) socket. If it is, entropy will be gathered
from an EGD server; otherwise, seed data will be read from the
contents of the named file.
EGD is an entropy-gathering daemon written in Perl that is intended for use in the absence of /dev/random or /dev/urandom. It is available from http://egd.sourceforge.net/ and runs on any Unix-based system that has Perl installed. It doesn’t work on Windows, but other entropy-gathering solutions are available for Windows. In particular, we recommend EGADS (Entropy Gathering And Distribution System), a C-based infrastructure that supports both Unix and Windows. This is a preferable solution even on Unix machines because it is far more conservative in its entropy collection and estimation. It is even a good solution on systems with a /dev/random. In such cases, it uses /dev/random as a single source of entropy. EGADS is available from http://www.securesw.com/egads/. It can be used anywhere an EGD socket is expected.
If Perl is installed on your system, EGD is easy to set up and run. Perl has become ubiquitous in the Unix world, so it’s unlikely that a modern system does not have it installed. Because EGD uses Perl, it’s very portable, even though it was originally written for Linux systems. On the other hand, EGD works by gathering its entropy from the output of running processes, a number of which produce a questionable amount of unpredictable data. Perhaps its biggest limitation is that it works only on Unix systems.
EGADS can be a bit more difficult to get up and running, but will usually compile straight from the distribution with a minimal amount of effort. On systems that do not have /dev/random, EGADS also gathers its entropy from the output of running processes. These processes are not as widely varied as EGD’s list. EGADS provides an EGD-compatible interface on Unix systems. Because EGADS provides an EGD interface and will use /dev/random to gather entropy, it provides a simplified interface for gathering entropy to clients such as those built with OpenSSL. It also supports Windows NT 4.0 and higher, which have no built-in entropy gathering services. It does not work on Windows 95, 98, or ME. Finally, EGADS also contains a cryptographically secure PRNG.
18.226.104.250