The Sorry State Of SSL

TLS is the best technology we have for securing our communications. It comes with many sharp edges though. This talk tries to jumpstart a rough understanding and these links should help you to complete the picture.

So far, I’ve held it at PyCon US 2014 in Montreal, PyCon Russia 2014, EuroPython 2014, and PyCon Poland 2014. The PyCon US slides are here.

Update 2015-04-11: One year later, the Python TLS situation improved.


PGP for data at rest, TLS for data in motion. Neither are perfect, but both are subjected to intense scrutiny by researchers —Thomas H. Ptacek

Do not try to roll your own crypto or you’ll end up explaining why you thought that RSA keys with a public exponent of 1 are a good idea or why you chose to go for ECB mode and everyone can see the penguin (probably because your crypto library uses it by default).

Put effort into using TLS properly instead. You can’t beat the NSA if they’re really interested in you. But if you act sensibly, you can avoid that some contractor can read your emails out of boredom. If you’re concerned with performance: don’t.

Some people think that encryption by default is unnecessary. There are good reasons to deploy even your cat content using HTTPS though.


  • 1995: SSL 2.0, an inherently insecure Netscape standard. Having this activated is a serious security vulnerability.
  • 1996: SSL 3.0. A much better Netscape standard that got an ex post RFC by the IETF. Deploying it is also considered a security problem since the POODLE attack and should be avoided (RFC 7568)
  • 1999: TLS 1.0. The first official IETF standard. Not to be confused with STARTTLS. Mostly an SSL 3.1 spec-wise.
  • 2006: TLS 1.1. Fixed mainly the CBC-related attacks like BEAST.
  • 2008: TLS 1.2. Both enhanced security and grew nifty features. Make sure this is what you deploy.

How Does TLS Even Work?

TLS is a protocol that adds authentication (certificates), confidentiality (encryption), and integrity (MACs) to your connection-oriented transport layer (presumably TCP).

The TLS handshake is actually mostly straightforward.


  • Authentication is achieved using X.509 certificates. They contain identity information signed by a presumably trusted third party called Certificate Authority or just CA.
  • Each certificate must have a valid trust path to a trusted root certificate which are public certificates of CAs that are shipped with your operating system or browser.
  • On some systems, you have to install them by hand:

    • FreeBSD: ca_root_nss
    • debian/Red Hat: ca-certificates
    • Mozilla’s trust database is publicly available.

      Not using the system-wide trust DB will quite likely catch some hate from ops folks though who prefer a central DB that gets updated by the distributions and they can modify as they see it fit.

    • The curl devs convert it into the more common PEM format.

  • The type of the key that belongs to the certificate determines the algorithm that is used for signing data. The current possibilities are:



  • The most common and well-researched cipher is the Advanced Encryption Standard block cipher.
  • AES-256 is not really better than AES-128 due to key scheduling issues.
  • Block ciphers need a mode of operation in order to chop up and pad the data to their block size (in AES’s case: 128 bits in all variants). The most common way is currently Cipher-block chaining (CBC). Unfortunately it was poorly implemented in TLS, which caused multiple problems. TLS 1.1 fixed most of them. Then TLS 1.2 introduced a new mode: the Galois/Counter Mode that has a MAC built right in. This is also known as Authenticated Encryption with Associated Data (AEAD).
  • The traditional way to avoid CBC-mode vulnerabilities was RC4 because it’s a stream cipher that doesn’t need chopping/padding. That’s probably not the brightest idea anymore.
  • Adam Langley of Google is working on standardizing the excellent ChaCha20 stream cipher with a Poly1305 MAC. Google has already deployed it on their own servers and it works with Chrome that runs on a computer that hasn’t AES-GCM hardware support.
  • He also put together an overview of current cipher weaknesses.
  • And also an overview of the current best replacements and short-term future of them.

Key Exchange

  • Since symmetric ciphers are used for the payload, the peers need to agree on identical keys over an unencrypted channel.
  • As a general rule, you want perfect forward secret (PFS) key exchange so a key leak or a court order doesn’t render the cipher text of all your users into plaintext.
  • The still most common key exchange method is RSA that we already know from the authentication section. It is fast which is one of the reasons for its wide deployment. And unfortunately not PFS.
  • Diffie-Hellman ephemeral (DHE) is PFS, but slow.
  • Elliptic Curve DHE (ECDHE) is both fast and PFS.
  • Get PFS right and you won’t have to pull stunts like Lavabit and give the FBI your server key printed in a 4 point font.
  • Getting PFS right in a big distributed system is tricky, be careful to not botch it.
  • At the end, both sides use the common master secret to derive multiple keys from it.


  • Message authentication codes (MACs) are used to ensure that traffic is not tampered with.
  • The most common ones are Keyed Hash MACs (HMACs) that are used since TLS 1.0. The hash function that’s part of the cipher suite is then used.
  • TLS 1.2 allows ciphers to bring their own MACs. Examples are Poly1305 used together with ChaCha20 or the block cipher mode Galois/Counter Mode (GCM) that has an integrated MAC.


You get TLS by linking to one of the more or less common TLS libraries.

  • OpenSSL is well-known and runs on a wide variety of platforms. Also well-known for bad code and frequent security problems and people argue it can’t get any better. It’s the worst except for everything else. You and your company can help to change that. There’s hope though.
  • LibreSSL is a fork of OpenSSL by the OpenBSD folks. Their goal is to clean up OpenSSL’s code base. As noble as it is, I doubt a big ball of mud without serious test coverage can be cleaned up without significant breakage.
  • BoringSSL is another for of OpenSSL. This time from the Google crew.
  • Network Security Services or NSS. Mozilla’s crypto stack including TLS. Not to be confused with Name Service Switch. Widely used in the Mozilla universe and by Red Hat. Also still used by Chrome on many platforms but they are planning to switch to OpenSSL.
  • SecureTransport, the native TLS of iOS and OS X. Nowadays infamous for its goto fail bug.
  • GnuTLS is the LGPL answer to OpenSSL since GPL software technically can’t link against OpenSSL. Had it’s own goto fail comically shortly after SecureTransport.
  • Secure Channel is Microsoft’s native TLS. Had also its share of problems of course.
  • miTLS is a verified implementation in F# but it’s not in noteworthy use yet. TLS implementations in memory-safe and/or verifiable programming languages (as opposed to C) are probably our biggest hope to get out of this mess.
  • s2n is a TLS library from Amazon that aims for security by implementing only the important subset of TLS. Sadly written in C and depends on parts of OpenSSL’s libcrypto for certain ciphers (builds also with LibreSSL and BoringSSL).

Summing up, the commonly used one are all terrible, but you should still use one of them since they are the most widely audited. For more alternatives see this handy overview.

The rest of this collection is heavily biased towards OpenSSL because it’s the most widely used cross-platform toolkit. A lot of the links and hints are toolkit-agnostic though.

User Pitfalls

Tin Foil/Out of Your Control

  • Your computer and phone trust certificate authorities you probably wouldn’t choose to trust yourself. There isn’t much you can do.
  • We have a rich history of fatal trust incidents.
  • Some of the trusted root certificates aren’t even actively used. In other words they aren’t useful and just raise the risk of abuse.
  • Microsoft’s TLS will call home if it can’t verify a certificate to double-check.


  • Run up to date software.
  • Whatever you do, test it afterwards.
  • SSL Pulse, aka the current state of TLS/HTTPS in the wild. It will make you drink.
  • Try to get a 4096 bits RSA certificate signed with a SHA-2 hash. Or ECDSA if you can.
  • Get your cipher suites right.

    ECDHE-ECDSA-AES128-GCM-SHA256 would be nice, but 4096 bits RSA certificates signed with SHA-2 are realistic and good enough for now.

  • Make sure your DHE parameters are strong enough. I for one don’t care about Java 6 clients.

  • OWASP Transport Layer Protection Cheat Sheet has some general tips.



Trust DBs

  • SSL_CTX_set_default_verify_paths will load root certificates from paths specified via environment variables or compiled in default paths. Completely undocumented but this mailing list thread is enlightening.
  • Christian Heimes wrote a nice summary of platform-specific trust DBs for OpenSSL in a preparation for a PEP (that probably won’t happen in that form).
  • OS X’s default OpenSSL is not only hopelessly outdated (0.9.8y as of OS X 10.9.2) but also contains a few hacks that make its verification practices a bit unpredictable. But in the common case it will do exactly what you expect it to do: verify according to the system keychain.
  • Homebrew’s OpenSSL clones the root certificates from the system keyring on installation and makes SSL_CTX_set_default_verify_paths work.
  • For Windows you’ll need something like wincertstore for Python.
  • If you’re afraid of rogue CAs, you may want to consider to employ certificate pinning.


Test your settings. How’s My SSL? offers a handy JSON endpoint if you’re writing an HTTPS client.


  • Avoid doing TLS yourself in the first place if you can. Especially for web apps, just put an nginx or an Apache or a stud in front of it.
  • The Python Cryptography Authority is an attempt to bring high-quality crypto libraries to Python.
  • cryptography being the flagship product: a crypto library without foot guns and with PyPy-friendly CFFI-bindings for OpenSSL (and more soon). You shouldn’t really use them directly though. Instead go for…
  • pyOpenSSL if you need low-level TLS in Python. The standard library moves too slowly for a security-sensitive topic like this. As of PyCon 2015, yours truly is the maintainer.
  • Kenneth Reitz is packaging Mozilla’s trust database as certifi on PyPI. Use that if you don’t want to cope with the system trust db bullshit but want to do the right thing.
  • Use requests for your HTTPS client needs. Install pyOpenSSL, ndg-httpsclient , and pyasn1 so it does the Right Thing™ thanks to the underlying urlib3.
  • Use Twisted 14.0 or later for TLS servers. It’s also a great WSGI container if you can’t put a reverse proxy in front of it for whatever reason. No callbacks or camelCase required.
  • uwsgi has a fairly complete custom-built HTTPS support.
  • No matter whether you are using the standard library or pyOpenSSL: if connecting to a TLS host, always verify the certificate and the hostname therein:
  • Standard libraries ssl module is not hopelessly broken since 2.7.9 thanks to PEP 466 and work done by Alex Gaynor and David Reid at Rackspace.
  • BEAST: Hope all clients have at least TLS 1.1 or 1/n-1 splitting active. If you can’t, you’ll have to deploy RC4 (ideally only for TLS 1.0 and older).
  • BREACH: Don’t use HTTP compression for secret tokens of any kind.
  • CRIME and TIME: Disable TLS compression.
  • Lucky 13: has to be fixed server-side. But that happened for all common OpenSSL-vendors. You should double-check though if in doubt.
  • Heartbleed: any server key that was exposed using an unpatched OpenSSL 1.0.1a–f has to be considered leaked and should be revoked and replaced as soon as you update your OpenSSL. This vulnerability has been exploited before it got disclosed. As a user, you should change all your passwords after the relevant services fix their servers. More on the attack by Matthew Green.

Follow These

If you want to stay up to date with all matters TLS, it’s not enough to wait until it hits the major news sources. Here’s a completely incomplete list of sources I’d suggest to tap.


Mailing Lists and Newsletters

Books & Courses



It’s sad, but SSL and TLS: Designing and Building Secure Systems from 2000 is hands down the best resource on the TLS protocol. It lacks TLS 1.1 and 1.2 and the more recent attacks for obvious reasons but is still incredibly throughout and useful.

Ignore their performance advice though.

TLS Deployments

Ivan Ristić of Qualys-fame is writing a book called Bulletproof SSL/TLS and PKI which is in parts already available for early access.

I bought it and can highly recommend it.

His previous work that’s slightly overlapping are the OpenSSL Cookbook and SSL/TLS Deployment Best Practices.



I’d like to thank Laurens Van Houtven who kindly reviewed my crypto claims so I don’t tell you complete bollocks. You should hire him if you need someone who’s actually competent in all things crypto.