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 is the most complete OpenSSL module available for Perl. It is written and maintained by Sampo Kellomäki (sampo@symlabs.com) 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 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.
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 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.
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.
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 (ngps@post1.com) 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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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')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.
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.
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.
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.
|
Constant |
Description |
|
|
May the certificate be used for the client in an SSL session? |
|
|
May the certificate be used for the server in an SSL session? |
|
|
May the certificate be used for a Netscape SSL server? |
|
|
May the certificate be used for S/MIME signing? |
|
|
May the certificate be used for S/MIME encrypting? |
|
|
May the certificate be used to sign a certificate revocation list (CRL)? |
|
|
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.
|
Key name |
Data type |
Description |
|
|
string |
The name assigned to the certificate, if it has one. This key may not be present. |
|
|
array |
An associative array that contains all of the fields comprising the
subject’s distinguished name, such as
|
|
|
array |
An associative array that contains all of the fields comprising the
issuer’s distinguished name. The
|
|
|
long |
The X.509 version. |
|
|
long |
The certificate’s serial number. |
|
|
string |
A string representation of the date the certificate is valid from. |
|
|
string |
A string representation of the date the certificate is valid to. |
|
|
long |
A |
|
|
long |
A |
|
|
string |
The alias assigned to the certificate, if it has one. This key may not be present. |
|
|
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 |
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.
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.
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.
|
Constant |
Description |
|
|
When encrypting or signing, adds a Content-type: text/plain header to the output. When verifying a signature, the Content-type header is stripped. |
|
|
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. |
|
|
When verifying a signature, only the certificates supplied to the function are trusted, causing any included certificates to be considered untrusted. |
|
|
Prevents the verification of the signer’s certificate of a signed message. |
|
|
Prevents chained verification of the signer’s certificate. Causes certificates in the signed message to be ignored. |
|
|
When signing a message, prevents the signer’s certificate from being included in the output. |
|
|
When signing a message, prevents attributes such as the signing time from being included in the output. |
|
|
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. |
|
|
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.