Chapter 6 ■ tLS/SSL
103
0x00e0: 5504 0a13 2045 7861 6d70 6c65 2043 4120 U....Example.CA.
0x00f0: 6672 6f6d 2041 7072 6573 7320 4d65 6469 from.Apress.Medi
0x0100: 6120 4c4c 4331 3930 3706 0355 040b 1330 a.LLC1907..U...0
0x0110: 466f 756e 6461 7469 6f6e 7320 6f66 2050 Foundations.of.P
0x0120: 7974 686f 6e20 4e65 7477 6f72 6b20 5072 ython.Network.Pr
0x0130: 6f67 7261 6d6d 696e 6720 3372 6420 4564 ogramming.3rd.Ed
But once the encrypted cipher is put into use, it is no longer possible (assuming no bugs or weakness in the
encryption) for a third party to examine. Here is the packet that just carried the bytes 'Simple is better than
complex' from the server to the client on my machine:
16:49:26.545897 IP 127.0.0.1.1060 > 127.0.0.1.40220:
Flags [P.], seq 2082:2141, ack 426, win 350, options
[nop,nop,TS val 51288448 ecr 51285953], length 59
0x0000: 4500 006f 645f 4000 4006 d827 7f00 0001 E..od_@.@..'....
0x0010: 7f00 0001 0424 9d1c dbbf f412 f4d0 24a3 .....$........$.
0x0020: 8018 015e fe63 0000 0101 080a 030e 9980 ...^.c..........
0x0030: 030e 8fc1 1703 0300 367f 9b5d e6c3 dfbd ........6..]....
0x0040: 8f21 d83f 8b61 569f 78a0 2ac3 090b bc9f .!.?.aV.x.*.....
0x0050: 101d 2cb1 1c07 ee08 f784 f277 b11e 9214 ..,........w....
0x0060: ce02 8e2b 1c0b b630 9c2d f323 3674 f5 ...+...0.-.#6t.
Note again what I warned about earlier in this chapter: the server and client IP addresses and port numbers pass
completely in the clear. Only the data payload itself has been protected from any outside observer.
Variations on Socket Wrapping
All the scripts in this chapter present simple and universal steps to achieving TLS with the ssl module: creating
a configured SSLContext object that describes your security requirements, making the connection from client to
server yourself using a plain socket, and then calling the context’s wrap_socket() method to perform the actual
TLS negotiation. The reason that my examples always use this pattern is because it is robust, efficient, and the
most flexible approach to using the module’s API. It is the pattern that you can always use with success in a Python
application, and by always using it, you will craft clients and servers that are easy to read because their approach is
consistent and their code is easy to compare to the examples here and to each other.
However, the Standard Library ssl module provides a few variant shortcuts that you might see used in other
code, which I should therefore mention. Let me describe each of them along with their shortcomings.
The first alternative you will run into is the invocation of the module-level function ssl.wrap_socket() without
creating a context first. You will see this especially often in older code since it was actually the only way to create a TLS
connection before context objects were added in Python 3.2! It has at least four shortcomings.
• It is less efficient because, underneath the hood, it creates a new context object full of settings
every single time it is called. By instead building and configuring your own context, you can
reuse it over and over again and incur the expense of creating it only once.
• It fails to provide the flexibility of a real context—even though it offers nine (!) different
optional keyword arguments in a desperate attempt to provide enough knobs and buttons—it
still manages to omit things such as letting you specify the ciphers that you are willing to use.