Quantcast
Channel: Planet Ubuntu
Viewing all articles
Browse latest Browse all 12025

Jason Gerard DeRose: How to enable perfect-forward-secrecy in Python 3.3

$
0
0

One of the many reasons to use Python3 is the ssl.SSLContext, which gives you quite comprehensive control of how you use TLS from Python.

As of Python 3.3, SSLContext supports perfect-forward-secrecy, which you can enable on your server-side SSLContext like this:

server_ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
server_ctx.set_ecdh_curve('prime256v1')

When implementing REST APIs, I highly recommend you secure them with TLS using client-side certificates for authentication. When you have control over both end-points, I recommend you configure TLS in a highly restrictive, modern way. Even though perfect-forward-secrecy must be enabled on the server-side, you can still configure your clients to only connect to servers that have enabled perfect-forward-secrecy (eg, by setting the ciphers to only include ECDHE variants).

For example, this is more or less the way that Dmedia will be configuring TLS for its server going forward:

server_ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
server_ctx.set_ecdh_curve('prime256v1')
server_ctx.verify_mode = ssl.CERT_REQUIRED
server_ctx.set_ciphers('ECDHE-RSA-AES256-SHA')
server_ctx.options |= ssl.OP_NO_COMPRESSION
server_ctx.options |= ssl.OP_SINGLE_ECDH_USE
server_ctx.options |= ssl.OP_CIPHER_SERVER_PREFERENCE
server_ctx.load_cert_chain('/my/server.cert', '/my/server.key')
server_ctx.load_verify_locations('/my/client.ca')

And this is how Dmedia will configure its client:

client_ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
client_ctx.verify_mode = ssl.CERT_REQUIRED
client_ctx.set_ciphers('ECDHE-RSA-AES256-SHA')
client_ctx.options |= ssl.OP_NO_COMPRESSION
client_ctx.load_cert_chain('/my/client.cert', '/my/client.key')
client_ctx.load_verify_locations('/my/server.ca')

Python 3.4

In Python 3.4 (which will be in Ubuntu Trusty), SSLContext supports TLSv1.2, and so for Python 3.4, I recommend you set the ciphers to 'ECDHE-RSA-AES256-GCM-SHA384', the big reason being that it's almost twice as fast.

For example, in a recent localhost-to-localhost benchmark I did (so Ethernet wouldn't be the bottleneck), I got:

ECDHE-RSA-AES256-SHA: 394 MB/second
ECDHE-RSA-AES256-GCM-SHA384: 740 MB/second

My recommended Python 3.4 server config is:

server_ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
server_ctx.set_ecdh_curve('prime256v1')
server_ctx.verify_mode = ssl.CERT_REQUIRED
server_ctx.set_ciphers('ECDHE-RSA-AES256-GCM-SHA384')
server_ctx.options |= ssl.OP_NO_COMPRESSION
server_ctx.options |= ssl.OP_SINGLE_ECDH_USE
server_ctx.options |= ssl.OP_CIPHER_SERVER_PREFERENCE
server_ctx.load_cert_chain('/my/server.cert', '/my/server.key')
server_ctx.load_verify_locations('/my/client.ca')

And my recommended Python 3.4 client config is:

client_ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
client_ctx.verify_mode = ssl.CERT_REQUIRED
client_ctx.set_ciphers('ECDHE-RSA-AES256-GCM-SHA384')
client_ctx.options |= ssl.OP_NO_COMPRESSION
client_ctx.load_cert_chain('/my/client.cert', '/my/client.key')
client_ctx.load_verify_locations('/my/server.ca')

Viewing all articles
Browse latest Browse all 12025

Trending Articles