Chapter 6 ■ tLS/SSL
99
Python 3.4 Default Contexts
Several open source implementations of TLS are available. The Python Standard Library opts to wrap the most
popular, the OpenSSL library, which despite several recent security incidents still seems to be considered the best
option for most systems and languages. Some Python distributions come with their own OpenSSL, while others
simply wrap the version of OpenSSL that happens to come bundled with your operating system. The Standard Library
module has the old and nostalgic name ssl. Although you will focus your attention on ssl in this book, be aware that
other cryptography projects are underway in the Python community, including a pyOpenSSL project that reveals much
more of the underlying library’s API.
Through its introduction of the ssl.create_default_context() function, Python 3.4 makes it dramatically
easier for Python applications to use TLS safely than did earlier versions of Python. It is an excellent example of the
kind of “opinionated API” that most users need. We should thank Christian Heimes for adding the idea of a default
context to the Standard Library, as well as Donald Stufft for pushing to give it strong and useful opinions. The other
mechanisms that the ssl module offers for setting up TLS connections are forced to stick with older and less secure
defaults because they had already made the promise not to break backward compatibility when new versions of
Python come out. But create_default_context() is quite willing to raise an exception the next time you upgrade
Python if the TLS cipher or key length that you have been using is now believed to be insecure.
By abandoning the promise that you can upgrade Python without changing your application’s behavior,
create_default_context() can carefully choose the ciphers it will support, which lets you off the hook—you will not
have to become a TLS expert and read security blogs if you simply rely on its advice and then keep Python updated
on your machine. Do retest your applications after each upgrade to make sure that they can still connect to their TLS
peers. If an application fails, then investigate whether the peer at the other end of the problematic connection can also
be upgraded to support more modern ciphers or mechanisms.
How is a default context created and used? Listing 6-3 shows how both a simple client and server can safely
secure a TCP socket using TLS.
Listing 6-3. Securing a Socket with TLS for Both Client and Server in Python 3.4 or Newer
#!/usr/bin/env python3
Foundations of Python Network Programming, Third Edition
https://github.com/brandon-rhodes/fopnp/blob/m/py3/chapter06/safe_tls.py
Simple TLS client and server using safe configuration defaults
import argparse, socket, ssl
def client(host, port, cafile=None):
purpose = ssl.Purpose.SERVER_AUTH
context = ssl.create_default_context(purpose, cafile=cafile)
raw_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
raw_sock.connect((host, port))
print('Connected to host {!r} and port {}'.format(host, port))
ssl_sock = context.wrap_socket(raw_sock, server_hostname=host)