Chapter 9. OpenSSL in Other Languages

So far, we’ve discussed OpenSSL in the context of the C programming language, but you don’t have to use C to use OpenSSL! Language bindings are available for many different languages, including Java, Perl, PHP, Python, and others. Unfortunately, none of the non-C language bindings that we’ve come across are as complete as the C API; nonetheless, it is important to discuss at least a few of the more popular and best-supported language bindings that are available.

The first section of this chapter is a discussion of Net::SSLeay, the most popular and complete module that is widely available for Perl. Be careful not to confuse Net::SSLeay with Crypt::SSLeay. The latter package is intended only to add support for HTTPS to the LWP package (a popular WWW interface library for Perl) and does not provide the additional interfaces to OpenSSL that Net::SSLeay does. The second section of this chapter is a discussion of M2Crypto, the most popular and complete suite of modules that is widely available for Python. The third section of this chapter is a brief discussion of the experimental OpenSSL extensions available in PHP 4.0.4 and newer versions.

For the purposes of these discussions, we assume that you have a familiarity with the language that is being discussed and its accompanying tools. It is not our intent to guide you through the installation of the modules or the common usage of the language. The specific purpose of this chapter is to demonstrate how to use the modules and get you started with OpenSSL in your own programs.

Net::SSLeay for Perl

Net::SSLeay is the most complete OpenSSL module available for Perl. It is written and maintained by Sampo Kellomäki () and can be found on the Web at http://www.symlabs.com/Net_SSLeay. As is the case with most Perl modules, it is also available from CPAN. Unfortunately, its installation is not as straightforward as one might hope, so take care in reading the accompanying installation instructions for guidance.

As its name suggests, the module has its roots in the old SSLeay library originally developed by Eric Young, which provides the foundation upon which OpenSSL has been built. SSLeay evolved into OpenSSL several years ago, and Net::SSLeay hasn’t supported old versions of SSLeay since early 1999. At the time of this writing, the latest version of Net::SSLeay is Version 1.13 and requires OpenSSL 0.9.6c or later.

The module comes with a fair number of scripts that serve as examples to demonstrate how to use the module’s basic functionality. It provides Perl bindings for many of the low-level OpenSSL library functions. Many convenience functions that are intended for use at a low level are also included. The module also contains several high-level functions that you can use to perform common tasks involving OpenSSL, such as obtaining a file securely from the Web or securely posting data to a CGI script.

A limited amount of documentation is also included with the module. A quick-reference file that contains a list of the functions that are exported is included, along with a simple one-line description of each. The main Perl module file, SSLeay.pm, also contains some documentation in perldoc format of the functions the module adds to the OpenSSL bindings. Aside from the quick-reference file, no additional documentation is provided for the OpenSSL bindings. In fact, the author refers you to the OpenSSL documentation and source code for more information.

Net::SSLeay Variables

Net::SSLeay exports several global variables that are useful for controlling the behavior of the modules. Some of them are useful only for debugging your programs, but most of them provide finer control over the behavior of OpenSSL itself or some of the utility functions that are provided by the module.

$linux_debug

This variable should be set only when the module is being used on a Linux system. If it is set to a nonzero value, process information from /proc/pid/stat will be displayed for each read and write.

$trace

This variable sets the trace level that is used by the high-level utility functions. It is intended primarily for debugging, so it should generally be set to zero in production programs (the zero guarantees silence). Valid values for this variable are 0 for silence, 1 for only errors to be reported, 2 for cipher information to be reported, 3 to report progress, and 4 to display everything, including the data that is both sent and received.

$slowly

This variable is used with the sslcat utility function. It controls the number of seconds that sslcat will sleep after sending data and before closing the sending side of the connection. It defaults to zero, which means that sslcat will not sleep at all, but some servers may require a delay; otherwise, they won’t be able to read all of the data that was sent.

$ssl_version

This variable sets the version of the SSL protocol that is used by the high-level utility functions. By default, it is set to 0, which indicates that the version should be guessed as SSLv2, SSLv3, or TLSv1. Valid values for this variable are 2 for SSLv2, 3 for SSLv3, 10 for TLSv1, and 0 to guess SSLv2, SSLv3, or TLSv1.

$random_device

This variable contains the name of a file that will be used to seed OpenSSL’s PRNG. The default setting for this variable is /dev/urandom, but not all operating systems have such a device. If your system does not have such a device, you should consider using a third-party program that can provide entropy, such as EGADS. You can optionally use /dev/random if your system has it; however, that device can block if not enough randomness is available. See Chapter 4 for a discussion on the importance of properly seeding the PRNG.

$how_random

This variable specifies, in bits, how much entropy should be collected from the source specified by $random_device. The default value is 512 bits. If you change this, be sure that you collect enough entropy, but also be careful that you do not collect too much, especially if you’re using /dev/random as your entropy source, because it could block until more becomes available.

Net::SSLeay Error Handling

In addition to providing Perl bindings for many of OpenSSL’s error handling functions, three utility functions are provded by Net::SSLeay to handle error conditions:

print_errs($msg)

This function returns a string containing a list of all of the OpenSSL errors that occurred since the OpenSSL function ERR_get_error( ) was last called. A newline character separates each error in the returned string, and each error is prefaced with the message string that you specify as an argument. Additionally, if the $trace variable is any nonzero value, the errors will be printed to stderr via Perl’s warn function.

die_if_ssl_error($msg)

This function will cause your program to terminate immediately by calling die with the message that you pass as an argument if an OpenSSL error has occurred. The function simply calls print_errs to determine if any errors have occurred. If print_errs returns any errors, the program is terminated.

die_now($msg)

This function will cause your program to terminate immediately by calling die with the message that you pass as an argument. Before calling die, print_errs is called so that any errors will be printed to stderr if the $trace global variable is set to any nonzero value.

Net::SSLeay Utility Functions

Net::SSLeay provides many high-level utility functions that simplify the use of OpenSSL. They’re mostly wrappers around the low-level OpenSSL functions for which the module also provides bindings. Several of the functions also provide a wrapper around the HTTPS protocol.

make_headers(@headers)

This function converts an associative array into a string formatted for sending directly to an HTTP server. The array’s keys should be the header identifier, and the values should be the value to be associated with each header identifier. Essentially, this function combines each key/value pair with a colon and joins all of the pairs with carriage returns and linefeeds. The return value from this function is the resulting string.

make_form(@data)

This function converts an associative array into a string formatted for sending form data to a CGI script. The array’s keys should be the field name, and the values should be the value to be associated with each field name. The values are encoded according to the rules governing special and reserved characters in URLs. Essentially, this function combines each key/value pair with an equal sign and joins all of the pairs with an ampersand. The return value from this function is the resulting string.

get_https($site, $port, $path, $headers, $content, $mime_type, $crt_path, $key_path)head_https($site, $port, $path, $headers, $content, $mime_type, $crt_path, $key_path)post_https($site, $port, $path, $headers, $content, $mime_type, $crt_path, $key_path)put_https($site, $port, $path, $headers, $content, $mime_type, $crt_path, $key_path)

These four functions are similar, so we’ll describe them together. They take the same arguments and perform the HTTP request that is signified by their names. Not all of the arguments are appropriate for all of the functions, and in many cases empty values can be specified without any adverse effects. All of the functions establish a secure connection using SSL with the HTTPS protocol. You should not pass a URL to the functions, but instead pass the separate components that make up a URL as arguments, individually. These functions will build the URL for you, establish the connection, perform the requested operation with the data you’ve provided, and return the data from the server to your program. It’s important to realize that these functions perform no real certificate verification, so the only protection they’re providing is against passive eavesdropping attacks.

The first argument, $site, should contain the hostname or IP address of the host you wish to contact. The second argument, $port, should be the port to connect to. For the HTTPS protocol, the default port is 443. The third argument, $path, should be the path to the page as well as any variables you wish to pass as part of the URL. Essentially, this is the remainder of the URL.

The fourth argument, $headers, should contain any additional headers that you wish to send with your request. You can use the function make_headers to build a string of header information from an associative array. By default, Net::SSLeay will include the standard Host and Accept headers, so you do not need to include them yourself. The fifth argument, $content, is useful only for the put_https and post_https functions. Use it to specify the data to send to the server. In the case of the post_https, you can use the function make_form to build a string of data from an associative array to send to the server. The sixth argument, $mime_type, is used to specify the MIME type of the data contained in the $content argument. If you do not specify a MIME type, application/x-www-form-urlencoded is used by default.

The final two arguments, $crt_path and $key_path, are optionally used to specify the path and filename to the client certificate and RSA private key to be used in establishing the connection. Remember that if you request a private key to be used in the transaction, the passphrase for the key will be requested from the console by OpenSSL if it is encrypted. The certificate and key files must be in PEM format, which also means that they may both be contained in the same file.

All four functions will return an array containing the results of the transaction. If an error occurs, the returned array will have only two elements. The first element will be undef, and the second element will be a string representation of the error that occurred. If the transaction is successful, the array will have three elements. The elements will be (in this order): the data that makes up the page, the response code from the server, and the headers returned from the server. The headers will be returned in the form of an associative array.

sslcat($host, $port, $content, $crt_path, $key_path)

This function establishes an SSL-secured connection to another host, sends it some data, waits for a response, and returns the remote host’s response to your program. The first two arguments, $host and $port, specify the hostname or IP address and the port number to connect to. The third argument, $content, specifies the data that you wish to send to the remote host.

The fourth and fifth arguments, $crt_path and $key_path, optionally specify the path and filename to the client certificate and RSA private key to be used in establishing the SSL connection. Remember that if you specify a key to be used, the passphrase for the key will be prompted for on the console if the key is encrypted.

The return value from this function will be the data returned by the remote host or undef if an error occurred. If you call the function to request an array as a return, the first element of the array will be the data that was received from the remote host, and the second element will be a string containing error information if an error occurred.

randomize($seed_file, $seed_string, $egd_path)

This is a convenience function used to seed OpenSSL’s PRNG. The first argument is the name of a file to be used as a seed file. The second argument is a string to be used as a seed. The third argument is the name of a Unix domain socket that is bound to a server that speaks the EGD protocol for gathering entropy. If the argument is undefined, the environment variable EGD_PATH will be consulted for the name of the socket to use. Additionally, if you’ve specified a random device with the $random_device variable and it exists, the information will be passed on to OpenSSL via RAND_load_file. This function has no return value.

set_cert_and_key($ctx, $cert_file, $key_file)

This is a convenience function for specifying the certificate and key to use for an SSL context. All three arguments are required. Note that if the RSA key specified by $key_file is encrypted, OpenSSL will prompt you on the console for the passphrase. This function returns 0 if an error has occurred; otherwise, the return is nonzero.

ssl_read_all($ssl, $howmuch)

This function reads $howmuch bytes from SSL connection specified by $ssl. The function will not return until the specified number of bytes has been read or EOF is encountered, whichever happens first. The return from this function will be the data that was received. If you call the function requesting an array return, the first element of the array will be the data received, and the second element will be the string representation of any errors that occurred.

ssl_read_CRLF($ssl, $max)

This function reads data from the SSL connection specified by $ssl until a carriage return and linefeed are received or the number of bytes equals $max if it is specified. The carriage return and linefeed characters will be included in the received data if they’re read before the maximum byte limit is reached. The return from this function will be the data that was received.

ssl_read_until($ssl, $delimiter, $max)

This function reads data from the SSL connection specified by $ssl until the specified delimiter is received or the number of bytes equals $max if it is specified. If no delimiter is specified, $/ or a linefeed character will be used, depending on whether $/ is defined or not. If the delimiter is encountered, it will be included in the data that is returned. The return from this function will be the data that was received.

ssl_write_all($ssl, $data)

This function writes the data specified by $data to the SSL connection specified by $ssl. The function will not return until all of the data has been written. The data to be written may be passed as a reference. The return from this function will be the number of bytes that were written. If you call the function requesting an array return, the first element of the array will be the number of bytes written, and the second element will be the string representation of any errors that occurred.

ssl_write_CRLF($ssl, $data)

This function is a simple wrapper around ssl_write_all that makes an additional call to ssl_write_all to write both a carriage return and a linefeed after your data. The return from this function is the total number of bytes written. Remember that this byte count will include the carriage return and linefeed characters.

Net::SSLeay Low-Level Bindings

The Net::SSLeay module does not provide bindings for all of the functions that OpenSSL exports as part of its public API; however, it does provide a sizable subset of them. Certainly, the most commonly used functions have bindings, and the author has added bindings for a random splattering of other functions as needed. We don’t provide a complete list of all of the bindings that are supported. There is a complete list contained in the Net::SSLeay package. If there is a function that is missing, you should consider adding it yourself or contacting the author of Net::SSLeay.

In general, the Perl bindings for OpenSSL match the C functions for which they provide bindings. That is, both the arguments and the return values are the same. As you would expect, there are some differences. The most significant difference is that the names of the Perl bindings are not prefixed with SSL_ as the OpenSSL C functions are. Instead, you should prefix the names with Net::SSLeay:: to get the function or constant that you want. If the function name does not start with SSL_ in the OpenSSL C library, the name is the same in Perl.

There are two notable exceptions to the rule that Perl bindings take the same arguments as OpenSSL C functions. Both read and write as exported by Net::SSLeay provide bindings to SSL_read and SSL_write; however, the Perl bindings are more intelligent about the data types that are passed through them. For example, write automatically figures out the number of bytes that need to be written.

For the most part, callbacks are not implemented in Net::SSLeay. Only one callback is implemented, and it does not come without a potentially severe restriction. The one callback that is implemented is the verify callback, which is used for verifying certificates. The restriction is that there can be only one callback across all SSL contexts, sessions, and connections. For most client applications, this restriction will probably never be encountered, but for server applications, the potential severity of the restriction increases significantly.

One final point to consider is that Net::SSLeay is not thread-aware. Given that threading is still experimental in Perl, it’s not so surprising that Net::SSLeay isn’t thread-aware. As Perl moves closer to fully supporting threading, this will become more of an issue, but for now it is something to keep in the back of your mind while designing and implementing your SSL-enabled applications in Perl using Net::SSLeay.

M2Crypto for Python

Although there are several solutions available for Python, M2Crypto is the most popular, the most complete, and not surprisingly, the most mature. It is written and maintained by Ng Pheng Siong () and can be found on the Web at http://www.post1.com/home/ngps/m2. It requires SWIG, which can be found on the Web at http://swig.sourceforge.net. At the time of writing, the latest version of M2Crypto is Version 0.06 and requires OpenSSL 0.9.6 or later and SWIG 1.3.6. It’s been tested and known to work on Unix and Windows with Python Versions 1.5.2, 2.0, and 2.1.

Although it is the most mature Python solution available, M2Crypto is barely a year old. Unfortunately, it is sorely lacking in documentation. Luckily, included in the distribution is a sizable collection of examples as well as a suite of unit test scripts that also serve as excellent examples of how to use the modules. M2Crypto contains not only a large set of low-level bindings to the OpenSSL C library functions, but a set of high-level classes that provide a far cleaner interface to SSL as well.

Low-Level Bindings

A significant number of the OpenSSL C library functions are directly bound. Many others are still available, although wrapped with a slightly different name, and their arguments may have changed slightly. These wrappers typically make the functions easier to use from Python and do a little extra work “under the hood” that may be necessary for everything to work properly for Python. You can make the low-level bindings to OpenSSL available in your program with t he following statement:

from M2Crypto import m2

All of the low-level functions are named entirely in lowercase, and the OpenSSL C functions are normally named in a combination of uppercase and lowercase. For example, the OpenSSL C function named SSL_CTX_new would become m2.ssl_ctx_new in Python. We will not include a complete list of the low-level bindings in this chapter; however, the M2Crypto package contains one.

We don’t recommend that you use the low-level bindings in your own programs, at least not without also using the high-level classes. The primary reason for this is that many of the SSL subsystems require some additional setup calls from Python to make them work properly. For example, to use the BIO functionality, you need to call m2.bio_init , an internal M2Crypto function, properly. If you’re using the high-level classes, such calls are made for you, and you can generally feel free to extend the classes if you need to.

High-Level Classes

M2Crypto contains a reasonably complete set of high-level classes that you can use in your programs. Use of the high-level classes is encouraged over the low-level bindings for a couple of reasons. The primary reason that we cited in the earlier section on the low-level interface is a good one. As M2Crypto evolves and matures, it’s possible that its internals will change, breaking your programs in the process. Another reason is because Python is primarily an object-oriented language, and the low-level interface is not object-oriented at all. A third reason is that OpenSSL’s C library functions are often cumbersome to use. The high-level classes provide a much cleaner, easier-to-use interface to OpenSSL’s functionality.

There are several submodules, all of which can be imported from the M2Crypto module to access the various groupings of functions that all make up the OpenSSL C API. Several of them are still works in progress, but the most commonly used SSL functionality is available.

M2Crypto.SSL

from M2Crypto import SSL

The SSL module contains several classes that provide the most basic interface to the OpenSSL C library. Included among them are Context, Connection, Session, SSLServer, ForkingSSLServer, and ThreadingSSLServer. The first, Context , is a wrapper around the C interface’s SSL_CTX object. All of OpenSSL’s connection-oriented services require a context on which to operate.

When a context is created, the version of the protocol that it will support must be supplied. You cannot change a context’s protocol once it has been created. The Context class’s constructor takes an optional parameter that specifies the protocol to use. The protocol can be sslv2, sslv3, tlsv1, or sslv23. If you do not specify a protocol, the default is sslv23, which indicates that SSLv2, SSLv3, or TLSv1 should be negotiated during the initial handshake. As we mentioned in Chapter 1, you should avoid supporting v2 in your applications.

Once a context object has been created, it can be used to establish an SSL connection. The class contains many methods that allow you to set and query the various attributes a context may have that are supported by OpenSSL itself. Operations include assigning a certificate and private key, loading CA certificates, and specifying criteria to determine whether a peer’s certificate is acceptable or not.

The Connection class combines OpenSSL with sockets to provide an all-in-one object for establishing both client and server connections, as well as transferring data bi-directionally over the connection. This class is little more than a convenience object, since it does all of the tedious work of setting up a socket and establishing an SSL connection for you. All that you need to do is create a Context and set it up to meet your needs. For example, to establish a connection using TLSv1 for the protocol, your code might look a little something like this:

from M2Crypto import SSL
 
ctx = SSL.Context('tlsv1')
conn = SSL.Connection(ctx)
conn.connect(('127.0.0.1', '443'))

The Session class is not one that you would typically create yourself. There are two ways to get a Session object. The first is from an existing Connection object by calling its get_session method. The second is by loading a saved session from a file via SSL.load_session. Once you have a Session object, you can dump it to a file using its write_bio method.

The last three classes, SSLServer , ForkingSSLServer , and ThreadingSSLServer , are SSL versions of the Python TCPServer class found in the SocketServer module. They all work in the same manner, except the constructor for each class requires an additional argument that is a Context object. You are of course required to create the Context object and set it up to meet your needs.

M2Crypto.BIO

from M2Crypto import BIO

The BIO module provides interface classes to OpenSSL’s BIO functions. The BIO class itself is an abstract class that provides the basic functionality of the other four classes that are built on top of it: MemoryBuffer, File, IOBuffer, and CipherStream. The BIO class itself is not intended to be instantiated. If you do, it’ll be mostly useless, capable of doing little more than throwing exceptions when you try to use it.

There isn’t much to be said for these four classes that we didn’t already cover in Chapter 4. BIO is simply an I/O abstraction, and these four classes provide four different types of I/O. The MemoryBuffer class provides a wrapper around the OpenSSL BIO_s_mem type, which is an in-memory I/O stream. The File class provides a wrapper around the OpenSSL BIO_s_fp type, which is a disk file. The IOBuffer class provides a wrapper around the OpenSSL BIO_f_buffer type, and it is typically used only internally by a Connection object’s makefile method. It essentially provides a wrapper around any other type of BIO.

Finally, the CipherStream class provides a wrapper around the OpenSSL BIO_f_cipher type, which is perhaps the most interesting of all four BIO wrappers that are supported by M2Crypto. It wraps around any other type of BIO of your choosing, encrypting data as it is written, and decrypting data as it is read. Some additional setup work is required to use this class, but all that is actually involved is setting the cipher to be used.

M2Crypto.EVP

from M2Crypto import EVP

The EVP module provides an interface to OpenSSL’s EVP interface. Additionally, it provides an interface to OpenSSL’s HMAC interface, which is not technically a part of the EVP interface. As we discussed in Chapters 6, 7, and 8, EVP is a high-level interface to message digests, symmetric ciphers, and public key algorithms. It provides a mechanism for computing cryptographic hashes, data encryption, and digital signatures.

The MessageDigest class provides the interface for computing cryptographic hashes. Its constructor requires an argument that is the string name of the algorithm to use. The available algorithms and their string names are listed in Chapter 7. Once a MessageDigest object is instantiated, its update method can be called as many times as necessary to supply it with the data to be hashed. A call to the final method computes the hash and returns it. Example 9-1 demonstrates.

Example 9-1. Computing the cryptographic hash of data
from M2Crypto import EVP
 
def hash(data, alg = 'sha1'):
    md = EVP.MessageDigest(alg)
    md.update(data)
    return md.final(  )

The HMAC class provides one of two interfaces for the OpenSSL HMAC support. The constructor accepts two arguments, the second of which is optional. The first argument is the key to use, and the second optional argument is the string name of the message digest algorithm to use. The available algorithms and their string names are listed in Chapter 7. If no message digest algorithm is specified, SHA1 is used. Once an HMAC object is instantiated, its update method can be called as many times as necessary to supply it with the data to be MAC’d. A call to the final method computes the MAC and returns it. The hmac function provides the other interface and is simply a wrapper around the OpenSSL hmac function. It accepts three arguments, the third of which is optional. The first argument is the key to use, and the second is the data to be MAC’d. The third and optional argument is the message digest algorithm to use. Again, SHA1 is the default if one is not specified. The return from the function is the computed HMAC.

The Cipher class provides the interface to data encryption using a symmetric cipher. The class’s interface is the same as the MessageDigest and HMAC classes. Once a Cipher object is constructed, the update method is used to supply it with the data to be encrypted or decrypted, and the final method completes the operation, returning the encrypted or decrypted data. The constructor requires four arguments, and accepts an additional four optional arguments.

class Cipher:              
             def _ _init_  _(self, alg, key, iv, op, key_as_bytes = 0, d = 'md5',    
                             salt = '', i = 1):
alg

The symmetric cipher to use. It is specified using the string name of the desired cipher. Chapter 6 lists the available ciphers and their string names.

key

The key to use to encrypt or decrypt the data.

iv

The initialization vector to use to encrypt or decrypt the data.

op

An integer that specifies whether encryption or decryption of the data should be performed. If op is specified as 1, encryption is performed. If it is specified as 0, decryption is performed.

key_as_bytes

Specifies how to interpret the specified key. If it is specified as a nonzero value, the key is interpreted as a password or passphrase. In this case, an initialization vector is computed, and the iv argument is filled with the initialization vector that was used.

d

Specifies the message digest algorithm that will be used to compute the key if key_as_bytes is specified as nonzero. The default is to use MD5.

salt

Specifies the salt that will be used to compute the key if key_as_bytes is specified as nonzero.

i

Specifies the number of iterations that will be performed to obtain the final key. In other words, it specifies the number of times the key data will be hashed.

Example 9-2 illustrates symmetric ciphers.

Example 9-2. Encrypting and decrypting with a symmetric cipher
from M2Crypto import EVP
 
def encrypt(password, data, alg):
    cipher = EVP.Cipher(alg, password, None, 1, 1, 'sha1')
    cipher.update(data)
    return cipher.final(  )
 
def decrypt(password, data, alg):
    cipher = EVP.Cipher(alg, password, None, 0, 1, 'sha1')
    cipher.update(data)
    return cipher.final(  )
 
password = 'any password will do'
plaintext = 'Hello, world!'
ciphertext = encrypt(password, plaintext, 'bf-cbc')
print 'Decrypted message text: %s' % decrypt(password, ciphertext, 'bf-cbc')

The EVP module also provides a PKey class that is intended to be a wrapper around the OpenSSL EVP interface for digital signatures and data encryption; however, it is incomplete, providing only limited support for creating digital signatures. No mechanism exists for verifying digital signatures or data encryption in this class. The digital signature support is also nonfunctional. The class is essentially useless in its current form, and so we will not discuss it in any more depth here.

Miscellaneous crypto

from M2Crypto import DH, DSA, RSA, RC4

The DH, DSA, and RSA modules provide access to the three supported low-level, public key cryptographic algorithms known by the same names. The RC4 module provides direct access to the symmetric cipher by the same name. It’s curious that RC4 is the only symmetric cipher that is supported directly with a class of its own, particularly since the EVP interface is exposed. We recommend that you avoid using it in favor of the EVP module’s Cipher class.

The DH module provides a class by the same name that is generally instantiated by using one of the four functions provided by the module. The function DH.gen_params can be used to create a new DH object with randomly generated parameters. The functions DH.load_params and DH.load_params_bio can be used to create a DH object created from parameters stored in a file. DH.load_params accepts a filename from which the parameters will be loaded, and DH.load_params_bio accepts a BIO object from which the parameters will be loaded. Finally, DH.set_params allows you to create a DH object and specify the parameters yourself.

The DSA module provides a class by the same name that is generally instantiated by one of several module functions. The function DSA.gen_params can be used to create a new DSA object with randomly generated parameters. DSA.load_params and DSA.load_params_bio create a DSA object from a file or a BIO object. DSA.load_key and DSA.load_key_bio create a DSA object loaded from a file or BIO object containing a PEM representation of a private key. There is no mechanism to load public DSA keys.

The RSA module provides two classes: RSA and RSA_pub. The classes should be instantiated using one of the module’s functions. RSA.gen_key returns an RSA object after generating a new key pair. RSA.load_key and RSA.load_key_bio both create an RSA object from a private key stored in PEM format from a file or BIO object. RSA.load_pub_key and RSA.load_pub_key_bio create an RSA_pub object from a public key stored in PEM representation from a file or BIO object. Finally, RSA.new_pub_key will instantiate an RSA_pub object from the public exponent and composite of the primes that make up a private key.

The RC4 module provides an RC4 class as an interface to the RC4 symmetric cipher algorithm. This class is intended to be instantiated directly. It can be instantiated with or without a key, and the key can be changed with a call to its set_key method. Calling the update method with data to be encrypted will return the encrypted data.

Python Module Extensions

In addition to providing the low-level OpenSSL bindings and an object-oriented approach to OpenSSL in the high-level classes, M2Crypto also includes extensions to three of the modules that are part of Python itself. The extensions are what you might expect: SSL extensions to httplib, urllib, and xmlrpclib. The extensions to httplib and urllib simply support HTTPS. The extensions to xmlrpclib add an SSL_Transport class.

Extensions to httplib: httpslib

To use the httplib extensions, you’ll need to import the M2Crypto.httpslib module:

from M2Crypto import httpslib

You don’t need to import from httplib as well. M2Crypto’s httpslib exports all of httplib in addition to its own extensions. The httplib interface changed drastically in Version 2.0 of Python. httpslib accounts for this and provides different extensions depending on the version of Python that you’re using.

If you’re using a version of Python earlier than 2.0, a single new class called HTTPS will be added. This class is a subclass of HTTP from httplib. The only detail that you need to concern yourself with is passing in an existing SSL context object to the constructor. For example, to connect to the local host on the default HTTPS port 443 using SSLv3, your code might look like this:

from M2Crypto import SSL, httpslib
 
context = SSL.Context('sslv3')
https = httpslib.HTTPS(context, '127.0.0.1:443')

If you’re using Version 2.0 of Python or later, two new classes called HTTPSConnection and HTTPS will be added. HTTPSConnection is a subclass of HTTPConnection, and HTTPS is a subclass of HTTP. They both work similarly to their parent classes, but expect some extra information in their constructors in order to utilize SSL. All of the extra arguments are optional keyword arguments:

key_file

Specifies the path and filename of an RSA private key file to be used in establishing the connection.

cert_file

Specifies the path and filename of a certificate file to be used in establishing the connection.

ssl_context

Specifies an existing SSL context object. If it is omitted, a context will be created using the sslv23 protocol.

The HTTPSConnection class accepts all three keyword arguments. The HTTPS class will recognize only ssl_context, silently ignoring the others. The code to connect to the local host on the default HTTPS port 443 using SSLv3 might look like this:

from M2Crypto import SSL, httpslib
 
context = SSL.Context('sslv3')
https = httpslib.HTTPSConnection('127.0.0.1:443', ssl_context = context)

It’s important to realize that these functions do not perform any real certificate verification, so the only real protection they’re providing is against passive eavesdropping attacks.

Extensions to urllib: m2urllib

To use the urllib extensions, you’ll need to import the M2Crypto.m2urllib module:

from M2Crypto import m2urllib

You don’t need to import urllib itself as well. The m2urllib module re-exports all of urllib along with its own extensions. Unlike httplib, the interface for urllib is the same for all currently supported versions of Python. The only addition is an open_https method added to the urllib.URLopener class. It works just the same as the existing open method does, taking the same arguments and returning the same values.

The open_https function does not take any additional arguments; it is responsible for creating the SSL context to be used, and you can’t set up certificate or private key information either. The default protocol version that the SSL context is created with is controlled by the DEFAULT_PROTOCOL variable. By default, it is set to sslv3, but you can change it to any of the other supported values for creating an SSL context. For example, if you wanted either v2 or v3 to work, you might do the following:

from M2Crypto import m2urllib
 
m2urllib.DEFAULT_PROTOCOL = 'sslv23'
connection = m2urllib.URLopener(  ).open_https('https://www.somesite.com')

Extensions to xmlrpclib: m2xmlrpclib

The xmlrpclib module is new in Python 2.2. If you’re using an older version of Python, you can find this module from a third party. To use the xmlrpclib extensions, you’ll need to import the M2Crypto.m2xmlrpclib module:

from M2Crypto import m2xmlrpclib

You don’t need to import xmlrpclib as well. The m2xmlrpclib module re-exports all of xmlrpclib along with its own extensions. The only addition that the m2xmlrpclib module makes is a class named SSL_Transport. The class’s constructor accepts a single optional argument that is an SSL context object. If you don’t specify, one will be created that uses the sslv23 protocol.

OpenSSL Support in PHP

PHP is a scripting language that is used primarily, if not exclusively, on the Web. It is normally HTML-embedded, although it is also capable of running as a CGI script. It boasts an extensive library of functions that provide interfaces to a wide variety of common external libraries and services, such as LDAP and MySQL. PHP-4.04pl1 introduced experimental support for OpenSSL. At the time of this writing, the current version of PHP is 4.1.1, and OpenSSL support is still considered experimental. Current versions of PHP require OpenSSL Version 0.9.5 or later.

Since PHP’s support for OpenSSL is considered experimental, anything relating to the implementation could still change, including the function names, parameters, and return values. The support for OpenSSL in PHP is more limited than Perl or Python’s support, but sufficient functionality does exist to make it moderately useful. Support for encryption, signing, S/MIME, key generation, and X.509 certificate manipulation is included.

PHP’s OpenSSL functions are high-level abstractions from the OpenSSL API. Unlike Perl or Python, none of the low-level OpenSSL API is exposed directly. While this simplifies the usage of OpenSSL greatly, it also restricts its capabilities. As newer versions of PHP have been released, new OpenSSL functionality has been introduced. We recommend that you use the latest version of PHP available to you if you wish to make use of its OpenSSL functionality.

General Functions

The PHP OpenSSL extension provides four functions required for the more specific functionality offered by the extension. These functions provide a mechanism for error reporting as well as private and public key management. In particular, many of the more specific functions require a public or private key, which are often supplied as a key resource. Key resources can be obtained from any one of the sources listed below, but in all cases the key data obtained from an external source must be PEM-encoded because PHP provides no support for reading DER-encoded data:

  • The resource retreived from a prior call to either openssl_get_publickey or openssl_get_privatekey

  • An X.509 resource for public keys

  • A string that specifies a filename to read the key from

  • A string that contains the key data

  • An array that contains the key as a string representing a filename or containing the key data and the passphrase required to decrypt the key

In Version 4.0.5 or later of PHP, any of the inputs to openssl_get_privatekey , openssl_get_publickey , or openssl_x509_read , which return key or certificate resources, can be used as the key or certificate resource to the function requiring the key or certificate resource. The earlier versions of the OpenSSL extension required the use of the three aforementioned functions, but versions that are more recent do not. If you’ll be using the same key or certificate more than once, it is generally a good idea to use the functions to obtain a resource rather than obtaining it each time you need to use it.

mixed openssl_error_string(void)

This function pops the most recent error from OpenSSL’s error stack and returns a string representation of the error. If the stack is empty, the return from this function will be false. The string returned will be an English representation of the error as returned from the OpenSSL function ERR_error_string. Note that OpenSSL pushes errors onto a stack, and that this function pops only one error from that stack. Call this function repeatedly until it returns false in order to get all of the available error information when an error occurs.

resource openssl_get_privatekey(mixed key [, string passphrase])

This function creates a key resource for a private key. The first argument, key, can be one of three representations of a public key: a string beginning with “file://” that contains the name of the file containing the private key data, a string that contains the private key data, or an array that contains the key information. If an array is used, the first element should be either a string that contains the name of the file containing the key data, or the key data. The second element should be the passphrase to decrypt the key. The optional argument, passphrase, should be a string containing the passphrase required to decrypt the key if one is necessary.

The return from this function is false if an error occurs; openssl_error_string should be used to obtain error information. If the key is successfully loaded and decrypted, the return will be a PHP resource for the key. When you’re done using the key resource, you should use openssl_free_key to release it.

resource openssl_get_publickey(mixed certificate)

This function creates a key resource for a public key. The first argument, key, can be one of three representations of a certificate from which the public key will be extracted: a certificate resource, a string beginning with “file://” that contains the name of the file containing the certificate data, or a string that contains the certificate data.

The return from this function is false if an error occurs; openssl_error_string should be used to obtain error information. If the key is successfully extracted from the certificate, the return will be a PHP resource for the key. When you’re done using the key resource, you should use openssl_free_key to release it.

void openssl_free_key(resource key)

This function releases a key resource that was previously obtained from either openssl_get_privatekey or openssl_get_publickey. You should call this function to free any internal resources that are associated with a PHP key resource when you are through using it.

Certificate Functions

The PHP OpenSSL extension provides a limited number of functions useful for manipulating X.509 certificates. The functions allow you to create and free a certificate resource, verify that a certificate has permission to perform a specific function, and obtain information about the certificate. All certificate data that is provided to PHP must be PEM-encoded.

resource openssl_x509_read(mixed certificate)

This function creates a certificate resource from X.509 certificate data. The certificate data may be supplied as one of two representations: a string beginning with “file://” that contains the name of the file containing the certificate data, or a string containing the certificate data.

The return from this function is false if an error occurs; openssl_error_string should be used to obtain error information. If the certificate is successfully loaded, the return will be a PHP resource for the certificate. When you’re done using the certificate resource, you should use openssl_x509_free to release it.

void openssl_x509_free(resource certificate)

This function releases a certificate resource that was previously obtained from openssl_x509_read. You should call this function to free any internal resources that are associated with a PHP certificate resource when you are through using it.

bool openssl_x509_checkpurpose(mixed certificate, int purpose, array cainfo [, string untrusted_file])

This function determines whether a certificate may be used to perform a specific function. The first argument, certificate, is a certificate resource obtained from openssl_x509_read. Table 9-1 lists the valid values for the second argument, purpose. Note that only one constant may be used at a time—the argument is not a bit mask. The third argument, cainfo, is a list of trusted certificate files or directories to be used in the verification of the certificate. If present, the optional argument, untrusted_file, is the name of the file containing any certificates of intermediate CAs required to verify the certificate. The extra certificates will not be trusted.

Table 9-1. Possible purpose values for openssl_x509_checkpurpose

Constant

Description

X509_PURPOSE_SSL_CLIENT

May the certificate be used for the client in an SSL session?

X509_PURPOSE_SSL_SERVER

May the certificate be used for the server in an SSL session?

X509_PURPOSE_NS_SSL_SERVER

May the certificate be used for a Netscape SSL server?

X509_PURPOSE_SMIME_SIGN

May the certificate be used for S/MIME signing?

X509_PURPOSE_SMIME_ENCRYPT

May the certificate be used for S/MIME encrypting?

X509_PURPOSE_CRL_SIGN

May the certificate be used to sign a certificate revocation list (CRL)?

X509_PURPOSE_ANY

May the certificate be used for any and all purposes?

The cainfo array should contain a list of files that will be used to verify the certificate. Directories may also be included in the list. Files should contain one or more certificates, and directories should contain certificates that would be accepted by the OpenSSL command-line tool commands that perform a similar function with the CApath option. Certificate files in a directory should contain one certificate per file and should be named with the hash value of the certificate subject’s name and an extension of “.0”. Any certificates made available via this function are trusted.

The return from this function will be true if the certificate may be used for the purpose that is being checked. If it may not, the return will be false. The integer value -1 will be returned if an error occurs in the verification process; openssl_error_string should be used to obtain error information.

array openssl_x509_parse(mixed certificate [, bool shortnames])

This function returns information about a certificate in an associative array. The keys for the array are currently undocumented, but easily discovered from the source code for the extension. We’ve listed them here in Table 9-2; however, due to the fact that they are undocumented, if anything in the OpenSSL extension is going to change in future versions, these keys have a high probability. If you can avoid it, we would advise against using this function for the time being until it stabilizes. If the second argument, shortnames, is omitted or specified as true, the keys in the returned array will use a shortened name.

Table 9-2. Keys for the array returned by openssl_x509_parse

Key name

Data type

Description

name

string

The name assigned to the certificate, if it has one. This key may not be present.

subject

array

An associative array that contains all of the fields comprising the subject’s distinguished name, such as commonName, organizationName, etc. The shortnames argument affects the keys in this array.

issuer

array

An associative array that contains all of the fields comprising the issuer’s distinguished name. The shortnames argument affects the keys in this array.

version

long

The X.509 version.

serialNumber

long

The certificate’s serial number.

validFrom

string

A string representation of the date the certificate is valid from.

validTo

string

A string representation of the date the certificate is valid to.

validFrom_time_t

long

A time_t integer representation of the date the certificate is valid from (number of seconds since Jan 1, 1970 00:00:00 GMT).

validTo_time_t

long

A time_t integer representation of the date the certificate is valid to.

alias

string

The alias assigned to the certificate, if it has one. This key may not be present.

purposes

array

Each element in this array represents a purpose that is supported by OpenSSL. The index values of this array correspond to the constants listed in Table 9-1. Each element of that array is another array containing three elements. The first two are bools. The first indicates whether the certificate may be used for that purpose, and the second indicates whether the certificate is a CA. The third is a string representation of the purpose name, which is affected by the shortnames argument.

Encryption and Signing Functions

The OpenSSL extension provides wrappers around OpenSSL’s high-level EVP suite of functions, which can be used for data encryption as well as for digital signing. The functions provided are actually close mappings to the OpenSSL API functions; however, the PHP wrappers have imposed some limitations on them, most notably by limiting the cipher for encryption and decryption to RC4, and the digest for signing and verification to SHA1. We hope that future versions of the extension will remove these limitations, allowing for much more flexibility and security.

Warning

There is another, potentially more serious problem with the encryption support in PHP. On systems in which the OpenSSL library cannot seed the PRNG itself, PHP provides no means to seed it. The problem exists particularly on Unix systems without a /dev/urandom device. On such systems, we do not recommend that you use the PHP interface to OpenSSL unless there is another module loaded into the same server that does initialize the OpenSSL PRNG, such as mod_ssl. This warning also holds for the S/MIME functions that are described in the next section.

int openssl_seal(string data, string sealed_data, array env_keys, array pub_keys)

This function is used for encrypting data. The data is encrypted using RC4 with a randomly generated secret key, which is then encrypted using a public key. The encrypted data is known as sealed data, and the encrypted secret key is known as an envelope. The recipient must have the envelope, the sealed data, and the private key matching the public key used to create the envelope to decrypt the sealed data. The function conveniently allows for multiple recipients by accepting an array of public keys.

The first argument, data, specifies the data that will be sealed. The second argument, sealed_data, receives the sealed data. The third argument, env_keys, receives the envelopes for each public key that is specified for the fourth argument, pub_keys. The public keys should be key resources returned by openssl_get_publickey. If an error occurs, the return value will be false; otherwise, it will be the length of the sealed data in bytes.

bool openssl_open(string sealed_data, string data, string env_key, mixed key)

This function is used for decrypting data that was previously encrypted using openssl_seal. The first argument, sealed_data, is the data to be decrypted. The decrypted data is placed into the second argument, data. The third argument, env_key, specifies the envelope containing the encrypted secret key required to decrypt the sealed data via RC4. The fourth argument, key, is the private key to use for decrypting the envelope to obtain the secret key. The private key should be specified as a key resource obtained from openssl_get_privatekey.

If the sealed data is decrypted successfully, the return from this function will be true, and the decrypted data will be placed into the second argument, data. If an error occurs, the return will be false, and you should use openssl_error_string to obtain error information. Note that encrypted data not created with the PHP OpenSSL extension can also be decrypted with this function, as long as it was encrypted using the RC4 cipher.

bool openssl_sign(string data, string signature, mixed key)

This function signs data using the SHA1 message digest algorithm. The first argument, data, is the data to be signed. The second argument, signature, receives the resultant signature. The third argument, key, is a private key resource to use to sign the data, and should be a key resource obtained from openssl_get_privatekey. Anybody who has the public key that matches the private key used to sign the data can then verify the signature.

If the data is successfully signed, the signature will be placed into the second argument, signature, and the return from the function will be true. If an error occurs, the return will be false, and openssl_error_string should be used to obtain error information.

int openssl_verify(string data, string signature, mixed key)

This function is used for verifying the signature of a chunk of data using the SHA1 message digest algorithm. The first argument, data, is the signed data to be verified. The second argument, signature, is the signature of that data. The third argument, key, is the public key that matches the private key used to compute the signature.

If the signature is valid, the return from this function will be the integer value 1. If it is incorrect, but no other errors occurred, the return will be the integer value 0. If an error occurs in the process of verifying the signature, the return will be the integer value -1, and openssl_error_string should be used to obtain error information. Note that data not signed with the PHP OpenSSL extension can also be verified with this function, as long as it was signed using the SHA1 message digest algorithm.

PKCS#7 (S/MIME) Functions

The final set of functions that the PHP OpenSSL extension offers is for PKCS#7, which are provided as structures encapsulated in MIME types defined by S/MIME. These functions provide for encryption, decryption, signing, and signature verification using X.509 certificates. The functions were added in PHP 4.0.6. They are not available in prior versions. These functions require use of the OpenSSL PRNG, and the PRNG must be seeded before you can use them safely. Unfortunately, there is no way to do this with PHP itself, as detailed in the warning in the previous section.

bool openssl_pkcs7_encrypt(string infile, string outfile, mixed certs, array headers [, long flags])

This function encrypts the data contained in the file named by the first argument, infile, and places it in the file named by the second argument, outfile. The encryption always uses a weak RC2 40-bit cipher, which is a limitation of the PHP interface. S/MIMEv2 supports both RC2 40-bit and 3DES, but the PHP implementation has unfortunately chosen to restrict the cipher to the weaker of the two. Public keys to use for encryption are obtained from the third argument, certs. The certificates to use for encryption are specified as an array, allowing for multiple recipients of the same message. The fourth argument, headers, is an array of data that will be prepended to the output file in plaintext. The array can be either indexed or associative. In the former case, each element of the array is a single line of text to be placed in the output file. In the latter case, each line is composed from the key and the value, joining them with a colon and a space. The fifth argument, flags, is optional and specifies options that can be used to control the encryption process. The argument is a bit mask, so you may specify multiple constants if they’re appropriate. Table 9-3 lists the possible flag constants.

If the function is successful, the return from the function will be true. If an error occurs in the encryption process, the return will be false and openssl_error_string should be used to obtain error information. On a successful run, the file specified by the second argument will contain the encrypted data. The process must have write access to the file, and it will be created if it does not exist. If it does exist, the existing file will be truncated before the output from this function is written to it.

Table 9-3. Flags: openssl_pkcs7_encrypt, openssl_pkcs7_sign, openssl_pkcs7_verify

Constant

Description

PKCS7_TEXT

When encrypting or signing, adds a Content-type: text/plain header to the output. When verifying a signature, the Content-type header is stripped.

PKCS7_BINARY

When encrypting or signing, prevents the conversion of bare linefeeds to carriage returns and linefeeds as required by the S/MIME specification to mark end of line.

PKCS7_NOINTERN

When verifying a signature, only the certificates supplied to the function are trusted, causing any included certificates to be considered untrusted.

PKCS7_NOVERIFY

Prevents the verification of the signer’s certificate of a signed message.

PKCS7_NOCHAIN

Prevents chained verification of the signer’s certificate. Causes certificates in the signed message to be ignored.

PKCS7_NOCERTS

When signing a message, prevents the signer’s certificate from being included in the output.

PKCS7_NOATTR

When signing a message, prevents attributes such as the signing time from being included in the output.

PKCS7_DETACHED

When signing a message, this is the default if no flags are specified. It causes the MIME type multipart/signed to be used. It’s a good idea to include this option because some mail relays can’t handle messages signed with this option turned off.

PKCS7_NOSIGS

Prevents verification of the signatures on a message

bool openssl_pkcs7_decrypt(string infile, string outfile, mixed certificate, mixed key)

This function decrypts an encrypted message from the file named by the first argument, infile, and writes the plaintext into the file named by the second argument, outfile. The decryption is done using an RC2 40-bit cipher. The third argument, certificate, specifies the certificate to use, and the fourth argument, key, specifies the private key that matches the certificate.

If the function is successful, the return value will be true. If an error occurs, the return value will be false, and openssl_error_string should be used to obtain error information. The process must have write access to the output file. The file will be created if it does not exist, or if it does exist, it will be truncated before the output from this function is written to it.

bool openssl_pkcs7_sign(string infile, string outfile, mixed certificate,mixed key, array headers [, long flags [, string extra_certificates]])

This signs the contents of the file named by the first argument, infile, and writes the result to the file named by the second argument, outfile. Unless PKCS7_NOCERTS is specified as part of the option flags argument, the certificate specified by the third argument, certificate, will be included in the result. The key specified by the fourth argument, key, should be a private key obtained from openssl_get_private, and will be used to sign the message. The fifth argument, headers, can be either an indexed or an associative array. The contents of the array will be prepended to the output after it has been signed. If the array is indexed, each element of the array is treated as a single line to be output. If the array is associative, one line will be written for each key, composed of the key and the value joined by a colon and a space. The sixth argument, flags, is optional and specifies signing options. It is a bit mask and can be composed of the constants described in Table 9-3. If the seventh argument, extra_certificates, is present, the certificates contained in the file that it names will also be included in the signed result.

If the function is successful, the signed message will be written to the output file named by the second argument, outfile, and the return from the function will be true. If an error occurs, the return will be false, and openssl_error_string should be used to obtain error information. The process must have write access to the output file, and it will be created if it does not exist. If the file does exist, it will be truncated before the output from this function is written to it.

bool openssl_pkcs7_verify(string infile, int flags [, string outfile [, array cainfo [, string extra_certificates]]])

This function verifies the signature on the contents of the file named by the first argument, infile. The second argument, flags, specifies a bit mask of options that control the verification process. Table 9-3 lists the constant definitions and their meanings. If the third argument, outfile, is present and not null, it specifies the name of a file that the certificates contained in the signed message will be written to. The fourth argument, cainfo, if present, contains a list of trusted certificates that should be used in verifying the signature. The fifth argument, extra_certificates, if present, specifies the name of a file that contains any untrusted certificates that should be used in verifying the signature.

If a list of trusted certificates for verification is supplied, the array should contain the names of files and/or directories. Files that are specified as such may contain multiple certificates. Any directory that is specified should contain one file per certificate, and the file should have a name composed of the certificate subject’s hash value and an extension of “.0”. Symbolic links named in this manner referring to real files of any other name are acceptable.

The return from this function is true if the signature is valid. If the signature is not valid, but no errors otherwise occurred, the return from the function is false. If an error occurs in the verification process, the return value will be -1, and openssl_error_string should be used to obtain error information. If an output file is specified, the process must have write access to it, and it will be created if it does not already exist. If the file does exist, it will be truncated before the output of this function is written to it.