I'm stuck on a persistent SSL verification issue.
SSL: CERTIFICATE_VERIFY_FAILED
I discovered the error while building a Django app that had users authenticate using Mozilla Persona.
(python3.4)> import requests
(python3.4)> requests.get('https://verifier.login.persona.org')
I get a SSL: CERTIFICATE_VERIFY_FAILED
tracing back from requests
to urllib3
to ssl
:
...
"/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/ssl.py", line 805, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:598)
...
"/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/requests-2.4.1-py3.4.egg/requests/packages/urllib3/connectionpool.py", line 543, in urlopen
raise SSLError(e)
requests.packages.urllib3.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:598)
...
"/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/requests-2.4.1-py3.4.egg/requests/adapters.py", line 420, in send
raise SSLError(e, request=request)
requests.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:598)
Difference between python3 and python2
Here's where it starts to get interesting: I don't get the same issue when using python2.7:
(python2.7)> import requests
(python2.7)> requests.get('https://verifier.login.persona.org')
<Response [200]>
My first thought was that the two versions of requests
might be using different certs[1], so I was pretty surprised to find the two files were exactly the same:
(bash)$ diff `python3.4 -c "import requests; print(requests.certs.where())"` \
`python2.7 -c "import requests; print requests.certs.where()"`
# no diff
Error recreated in openssl and solved using -CAFile
Interestingly, the issue is not limited to python3.4[2].
(bash)$ openssl s_client -connect github.com:443
...
Verify return code: 20 (unable to get local issuer certificate)
Edit A comment from Steffen informed me that this "debugging" method isn't actually informative, as s_client
expects a -CApath in order to verify. However, the fact that I can specify the same certificate that the requests
package is using and I don't get the same error is still interesting:
(bash)$ openssl s_client -connect github.com:443 \
-CAfile `python3 -c 'import requests; print(requests.certs.where())'`
...
Verify return code: 0 (ok)
At this point, I'm completely out of my element. I don't know is if this is really an openssl
issue, or something about OSX Mavericks[3]. Here's the version of openssl I'm using:
(bash)$ openssl version
OpenSSL 1.0.1f 6 Jan 2014
Mavericks KeyChain.app
For OS-specific solutions, I've tried clearing my login KeyChain[4], to no avail.
Issues with pip
There's one last bit of evidence that may or may not be relevant. python3.4 ships with pip intact. However, the pip3 command is useless to me. No matter what I try to install:
(bash)$ pip3 install [new-lib] # pip 1.5.6
I get:
Downloading/unpacking [new-lib]
Cannot fetch index base URL https://pypi.python.org/simple/
Could not find any downloads that satisfy the requirement [new-lib]
Cleaning up...
No distributions at all found for [new-lib]
Storing debug log for failure in ~/.pip/pip.log
Although this isn't (explicitly) an SSL error, it seems similar[5] and a successful workaround has been to install an older version of pip using easy_install
in my virtualenv
s[5]. I'm crossing my fingers that the two issues are related.
Recap:
- Seeking possible solutions for SSL certificate failure error (without using
verify = False
in therequests
calls). - I get the error in python3.4 but not python2.7 even though the cert.pem used in both cases is exactly the same.
- Though I can recreate an SSL error using
openssl s_client -connect
I can avoid it by specifying-CAFile
to the cert.pem used by the requests library. - My best guess is that this is an issue particular to Mavericks, but I have no idea how to proceed.
- I'm hoping to find a solution that also allows me to use pip3 to install python3.4 packages as expected.
Thanks for your help!
[1]: python2.7 on my machine was installed using Enthought. But installing a system version of python2.7 and the requests library works too.
[2]: See openssl, python requests error: "certificate verify failed" for a similar problem using python 2.7
[3]: It seems Mavericks introduced a change in openssl? http://curl.haxx.se/mail/archive-2013-10/0036.html
[4]: Clearning KeyChain.app from here: https://superuser.com/a/721629/261875
[5]: SSL error with pip3: https://stackoverflow.com/a/22051466/2506078