requests: POST to CA fails using TLS

Hello i’m facing a issue using requests lib to post to a CA with self-signed certificate Everything goes well when I POST from curl:

curl --cacert "./ca-cert.pem" https://ca.goledger.com:7054/api/v1/cainfo -X POST

I get my response with CAChain

If I try using requests lib it fails

Expected Result

A response containing CAChain from CA at ca.goledger.com

Actual Result

The command fails throwing a strange SSLError (BAD_ECC_CERT)

 Traceback (most recent call last):
    File "/usr/local/lib/python3.5/dist-packages/urllib3-1.22-py3.5.egg/urllib3/connectionpool.py", line 601, in urlopen
        chunked=chunked)
    File "/usr/local/lib/python3.5/dist-packages/urllib3-1.22-py3.5.egg/urllib3/connectionpool.py", line 346, in _make_request
        self._validate_conn(conn)
    File "/usr/local/lib/python3.5/dist-packages/urllib3-1.22-py3.5.egg/urllib3/connectionpool.py", line 850, in _validate_conn
        conn.connect()
    File "/usr/local/lib/python3.5/dist-packages/urllib3-1.22-py3.5.egg/urllib3/connection.py", line 326, in connect
        ssl_context=context)
    File "/usr/local/lib/python3.5/dist-packages/urllib3-1.22-py3.5.egg/urllib3/util/ssl_.py", line 329, in ssl_wrap_socket
        return context.wrap_socket(sock, server_hostname=server_hostname)
    File "/usr/lib/python3.5/ssl.py", line 377, in wrap_socket
        _context=self)
    File "/usr/lib/python3.5/ssl.py", line 752, in __init__
        self.do_handshake()
    File "/usr/lib/python3.5/ssl.py", line 988, in do_handshake
        self._sslobj.do_handshake()
    File "/usr/lib/python3.5/ssl.py", line 633, in do_handshake
        self._sslobj.do_handshake()
    ssl.SSLError: [SSL: BAD_ECC_CERT] bad ecc cert (_ssl.c:645)

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
    File "/usr/local/lib/python3.5/dist-packages/requests-2.18.4-py3.5.egg/requests/adapters.py", line 440, in send
        timeout=timeout
    File "/usr/local/lib/python3.5/dist-packages/urllib3-1.22-py3.5.egg/urllib3/connectionpool.py", line 639, in urlopen
        _stacktrace=sys.exc_info()[2])
    File "/usr/local/lib/python3.5/dist-packages/urllib3-1.22-py3.5.egg/urllib3/util/retry.py", line 388, in increment
        raise MaxRetryError(_pool, url, error or ResponseError(cause))
    urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='ca.goledger.com', port=7054): Max retries exceeded with url: /api/v1/cainfo (Caused by SSLError(SSLError(1, '[SSL: BAD_ECC_CERT] bad ecc cert (_ssl.c:645)'),))

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "/usr/local/lib/python3.5/dist-packages/requests-2.18.4-py3.5.egg/requests/api.py", line 112, in post
        return request('post', url, data=data, json=json, **kwargs)
    File "/usr/local/lib/python3.5/dist-packages/requests-2.18.4-py3.5.egg/requests/api.py", line 58, in request
        return session.request(method=method, url=url, **kwargs)
    File "/usr/local/lib/python3.5/dist-packages/requests-2.18.4-py3.5.egg/requests/sessions.py", line 508, in request
        resp = self.send(prep, **send_kwargs)
    File "/usr/local/lib/python3.5/dist-packages/requests-2.18.4-py3.5.egg/requests/sessions.py", line 618, in send
        r = adapter.send(request, **kwargs)
    File "/usr/local/lib/python3.5/dist-packages/requests-2.18.4-py3.5.egg/requests/adapters.py", line 506, in send
        raise SSLError(e, request=request)
    requests.exceptions.SSLError: HTTPSConnectionPool(host='ca.goledger.com', port=7054): Max retries exceeded with url: /api/v1/cainfo (Caused by SSLError(SSLError(1, '[SSL: BAD_ECC_CERT] bad ecc cert (_ssl.c:645)'),))

Reproduction Steps

import requests
requests.post(url='https://ca.goledger.com:7054/api/v1/cainfo', verify='./ca-cert.pem')

System Information

{
  "chardet": {
    "version": "3.0.4"
  },
  "cryptography": {
    "version": ""
  },
  "idna": {
    "version": "2.6"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.5.2"
  },
  "platform": {
    "release": "4.10.0-38-generic",
    "system": "Linux"
  },
  "pyOpenSSL": {
    "openssl_version": "",
    "version": null
  },
  "requests": {
    "version": "2.18.4"
  },
  "system_ssl": {
    "version": "1000207f"
  },
  "urllib3": {
    "version": "1.22"
  },
  "using_pyopenssl": false
}

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 16 (7 by maintainers)

Most upvoted comments

Python 3.5 can handle ECC certs just fine with modern OpenSSL.

Python 3.5.4 (default, Dec  6 2017, 16:39:49) 
[GCC 7.2.1 20170915 (Red Hat 7.2.1-2)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ssl, socket
>>> s = socket.create_connection(('ecc384.badssl.com', 443))
>>> tls = ssl.create_default_context().wrap_socket(s, server_hostname='ecc384.badssl.com')
>>> tls.cipher()
('ECDHE-ECDSA-AES128-GCM-SHA256', 'TLSv1.2', 128)

@vieiramanoel what’s your OpenSSL version? Which ECC curves and signing algorithm does your service use? In general only named ANSI curves are supported well, e.g. secp384r1 and prime256v1.

>>> import ssl
>>> ssl.OPENSSL_VERSION
'OpenSSL 1.1.0g-fips  2 Nov 2017'