Upgrading to TLS 1.2

Oct. 26, 2016

I am in the process of implementing a secure means of credit card payments from a website through a third party service provider. We are using a custom django application to integrate with the payment service provider's application programming interfaces (APIs). One of the challenges I have to deal with is the migration from SHA-1 to SHA-2 and SSL to TLS (SHA = Secure Hash Algorithm, SSL = Secure Socket Layer, TLS = Transport Layer Security ). This post is not intended to be a primer on SHA or TLS as it is way too complicated and I don't claim to be a cryptographic expert. Very high level, SHA is a hash algorithm used to digitally sign certificates and TLS is the latest transport protocol. So SHA secures the message and TLS is responsible for securely delivering the message. An analogy is secured valuables that are transported by an armored car from a source to a destination.

The SHA-1 standard was developed by the National Security Agency (NSA) in 1995 and a number of significant vulnerabilities have been exposed. For that reason the internet is moving to the SHA-2 standard (SHA-3 is still likely 4-5 years away), and companies have no choice but to upgrade to SHA-2...and TLS 1.2 since that is the only transport protocol at this time that supports SHA-2.

I thought upgrading to TLS 1.2 would be a simple process, but it proved to be a vexing challenge. I'm a big fan of the Homebrew package manager so I ran the following commands:

# I often use openssl to generate SSH keys for AWS,  GitHub, etc. so I installed the latest version
brew intall openssl

# Python uses the openssl libraries so just installing openssl won't do us any good. Let's install the 
# latest version of python3 and instruct brew to use the latest openssl version which supports TLS 1.2
brew install python3 --with-brewed-openssl

You should now have the latest version of Python installed that supports TLS 1.2. However, don't be surprised... and don't panic...if the following command

$ python3 -c "import ssl; print(ssl.OPENSSL_VERSION)"

returns OpenSSL 0.9.8zh 14 Jan 2016

This means you more than likely have a path issue to your latest version of python3. The Apple-provided build of Python is installed in /System/Library/Frameworks/Python.framework and /usr/bin/python, respectively. You should never modify or delete these, as they are Apple-controlled and are used by Apple- or third-party software. Remember that if you choose to install a newer Python version from python.org, you will have two different but functional Python installations on your computer, so it will be important that your paths and usages are consistent with what you want to do.

You can either install python3 by downloading it directly from the official Python download site at https://www.python.org/downloads/ or using the Homebrew package manager. I actually installed both versions. The Python installer does a great job updating symbolic links so the newest version becomes the executable. Keep in mind that Python3 will get installed in separate paths depending on the installation method you use:

Installer from Python download site: /Library/Frameworks/Python.framework/... Homebrew: /usr/local/Cellar/python3/ # Homebrew installs all software to /usr/local/Cellar

You can check which version of Python3 you are running by typing the command which python3 which will return the path to the executable. Normally you will want to run the executable from /usr/local/bin but you are free to do whatever you want. I was in a hurry so I modified my .bash_profile path with the following commands:

cd ~ # Change to my home directory
vim .bash_profile # Open .bash_profile for editing
# Enter insert mode and add the following line to the end of the file
# Make sure the latest version will be found first
export PATH="/usr/local/Cellar/python3/3.5.2_1/bin:$PATH" 
# Exit insert mode and save the file
. .bash_profile # Reload my environment with the new settings (or you can exit and open a new shell)

Now the command should python3 -c "import ssl; print(ssl.OPENSSL_VERSION)" should return OpenSSL 1.0.2h 3 May 2016 Now all you have to do is rebuild your virtual environments as necessary and you are up and running with TLS 1.2!

Comment Enter a new comment:

On Jan. 22, 2017 nbacchus wrote: Reply

I'm so glad I found this blog. I spent hours trying to do something similar and I couldn't get it to work. It took me 10 minutes once I followed the instructions in your blog!