title: python3 and requests: still getting 'sslv3 alert handshake failure'
body: <p>I have been trying to perform an HTTPS request in Python 3 using <code>requests</code> and aggregating pretty much all the knowledge from the prior attempts documented on StackOverflow. I cannot for the life of me seem to get out of the <code>sslv3 alert handshake failure</code> rabbit hole.</p>
  
  <p>This is my environment:</p>
  
  <ul>
  <li>macOS 10.13.6</li>
  <li>Python 3.7.0 (installed via Homebrew along with openssl)</li>
  <li>OpenSSL 1.0.2p  14 Aug 2018 (output of <code>print(ssl.OPENSSL_VERSION)</code>)</li>
  <li>requests 2.19.1 (output of <code>print(requests.__version__)</code>) installed via <code>pip install requests[security]</code></li>
  <li>even cryptography 2.3.1 is installed</li>
  </ul>
  
  <p>This is the bare-bone failing code:</p>
  
  <pre><code>&gt;&gt;&gt; import requests
  &gt;&gt;&gt; requests.get('https://iris.nuigalway.ie')
  </code></pre>
  
  <p>And this is the output:</p>
  
  <pre><code>Traceback (most recent call last):
    File "/usr/local/lib/python3.7/site-packages/urllib3-1.23-py3.7.egg/urllib3/contrib/pyopenssl.py", line 444, in wrap_socket
      cnx.do_handshake()
    File "/usr/local/lib/python3.7/site-packages/pyOpenSSL-18.0.0-py3.7.egg/OpenSSL/SSL.py", line 1907, in do_handshake
      self._raise_ssl_error(self._ssl, result)
    File "/usr/local/lib/python3.7/site-packages/pyOpenSSL-18.0.0-py3.7.egg/OpenSSL/SSL.py", line 1639, in _raise_ssl_error
      _raise_current_error()
    File "/usr/local/lib/python3.7/site-packages/pyOpenSSL-18.0.0-py3.7.egg/OpenSSL/_util.py", line 54, in exception_from_error_queue
      raise exception_type(errors)
  OpenSSL.SSL.Error: [('SSL routines', 'ssl3_read_bytes', 'sslv3 alert handshake failure')]
  </code></pre>
  
  <p>Needless to say it works with cURL, browsers etc.</p>
  
  <pre><code>curl --verbose "https://iris.nuigalway.ie"
  </code></pre>
  
  <p>Here's a handshake snippet of the ouput:</p>
  
  <pre><code>* ALPN, offering h2
  * ALPN, offering http/1.1
  * Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
  * successfully set certificate verify locations:
  *   CAfile: /etc/ssl/cert.pem
    CApath: none
  * TLSv1.2 (OUT), TLS handshake, Client hello (1):
  * TLSv1.0 (IN), TLS handshake, Server hello (2):
  * TLSv1.0 (IN), TLS handshake, Certificate (11):
  * TLSv1.0 (IN), TLS handshake, Server finished (14):
  * TLSv1.0 (OUT), TLS handshake, Client key exchange (16):
  * TLSv1.0 (OUT), TLS change cipher, Client hello (1):
  * TLSv1.0 (OUT), TLS handshake, Finished (20):
  * TLSv1.0 (IN), TLS change cipher, Client hello (1):
  * TLSv1.0 (IN), TLS handshake, Finished (20):
  * SSL connection using TLSv1.0 / DES-CBC3-SHA
  * ALPN, server did not agree to a protocol
  </code></pre>
  
  <p>Now the cipher used by cURL does not indeed seem to be among the default ciphers of <code>urllib3</code> 1.23 (seemingly used by <code>requests</code>) as per <a href="https://github.com/urllib3/urllib3/blob/1.23/urllib3/util/ssl_.py" rel="nofollow noreferrer">https://github.com/urllib3/urllib3/blob/1.23/urllib3/util/ssl_.py</a></p>
  
  <p>So I tried adding it using the advice given at <a href="https://stackoverflow.com/a/40741362">https://stackoverflow.com/a/40741362</a> like this:</p>
  
  <pre><code>&gt;&gt;&gt; requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += 'DES-CBC3-SHA'
  </code></pre>
  
  <p>and even setting it to <code>ALL</code>. I even tried not to verify the certificate, all to no avail.</p>
  
  <pre><code>&gt;&gt;&gt; requests.get('https://iris.nuigalway.ie', verify=False)
  </code></pre>
  
  <p>A check with <code>s_client</code> on the server:</p>
  
  <pre><code>$ openssl s_client -connect iris.nuigalway.ie:443
  </code></pre>
  
  <p>reveals the following TLS version and cipher:</p>
  
  <pre><code>New, TLSv1/SSLv3, Cipher is RC4-SHA
  Server public key is 2048 bit
  Secure Renegotiation IS supported
  Compression: NONE
  Expansion: NONE
  No ALPN negotiated
  SSL-Session:
      Protocol  : TLSv1
      Cipher    : RC4-SHA
  </code></pre>
  
  <p>What options could I possibly have not tried yet?</p>
  
  <p>Many Thanks</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>The values of <code>ssl.OPENSSL_VERSION</code> <code>OpenSSL.SSL.SSLeay_version(0)</code> revealed two different versions of OpenSSL used by <code>ssl</code> and <code>pyOpenSSL</code> respectively, the latter being a more recent <code>OpenSSL 1.1.0i 14 Aug 2018</code> that has most likely dropped support for the <code>DES-CBC3-SHA</code> cipher.</p>
  
  <p>Below is the temporary solution I have adopted:</p>
  
  <ol>
  <li>uninstall <code>cryptography</code></li>
  <li>injecting only the required cipher, like this:</li>
  </ol>
  
  <p>(Note that it is no longer a concatenation)</p>
  
  <pre><code>requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS = 'DES-CBC3-SHA'
  </code></pre>
  
  <p>I appreciate that this solution may be sub-optimal and not applicable to many cases, but at least the lesson learnt is that different versions of OpenSSL may be at play from one package to another.</p>
  
  <p>I will be happy to know of a more flexible solution if any.</p>