Chapter 6 ■ tLS/SSL
113
The OpenSSL library will consider any of these combinations to be fair game under the setting set_
cipher('ECDH+AES128'). Again, my recommendation is to use the default context if at all possible and otherwise
to test the specific client and server that you expect to use, trying to choose one or two strong ciphers that they both
support. But if you wind up doing more experimenting and debugging than that, then I hope Listing 6-4 will be a
useful tool as you experiment and narrow down OpenSSL’s behavior. Be sure to download a fresh version of Listing 6-4
from the URL in the comment at its top when you have the chance because the version in the book will grow out-of-
date; I will work to keep the one online updated with recent developments both in cryptography and in the Python
ssl API.
Summary
This chapter addresses a topic on which few people are truly expert: the use of cryptography to protect data as it is in
flight across a TCP socket and, specifically, the use of the TLS protocol (once named SSL) from Python.
In a typical TLS exchange, the client demands a certificate from the server—a digital document that asserts an
identity. An authority that both the client and the server trust should sign it, and it must include a public key of which
the server then needs to prove it actually possesses a copy. The client should verify that the identity stated in the
certificate matches the hostname to which it thinks it has connected. Finally, the client and server negotiate settings
such as the cipher, compression, and keys, which are then used to protect the data passing in both directions over
the socket.
Many administrators do not even attempt to support TLS in their applications. Instead, they hide the applications
behind industrial-strength front ends such as Apache, nginx, or HAProxy that can perform TLS on their behalf.
Services that have content delivery networks in front of them must also offload TLS responsibility instead of
embedding it in their own application.
Though a web search will suggest third-party libraries that can perform TLS in Python, the language’s built-in
abilities come from its OpenSSL-powered ssl module in the Standard Library. Assuming that ssl is available and
working properly on your operating system and version of Python, basic encrypted channels can be set up, needing
only a server certificate to operate.
Python applications written for Python 3.4 and newer (I strongly recommend using at least version 3.4, if your
application is going to do its own TLS) will generally follow the pattern of creating a “context” object, opening a
connection, and then calling the context’s wrap_socket() method to turn the connection over to the control of the
TLS protocol. Although the ssl module does provide one or two shortcut functions that you will see used in older
code, the context-connect-wrap pattern is the most universal and flexible.
Many Python clients and servers can simply accept the settings provided by the default “context” object returned
by ssl.create_default_context() that tries to make servers slightly strict in the settings that they will accept
but make clients a little more lenient so that they can successfully connect to servers with only old versions of TLS
available. Other Python applications will want to instantiate SSLContext themselves so as to tailor the protocol and
cipher to their specific requirements. In any case, either the test script shown in this chapter or another TLS tool can
be used to explore the behaviors that result from the settings.
The Standard Library supports a number of protocols that can be optionally secured with TLS, most of which
are explored in later chapters of this book. They all support an SSLContext object if you can provide one. Third-
party libraries, at the moment, provide poor support for contexts, since Python 3.4 has only recently been released
and since most Python programmers are still using Python 2 in any case. Ideally, both situations will improve over
the years.
Once you have implemented TLS in your application, it is always worthwhile to test it using tools that will attempt
various kinds of connections with varying sets of parameters. Both third-party tools and web sites are available outside
of Python for testing both TLS clients and servers, and the tool shown in Listing 6-4 can be used with Python 3.4 right
on your own machine if you want to throw different settings at OpenSSL to see how it negotiates and behaves.