Haris
Haris

Reputation: 12272

Python ssl get ciphers supported

I was wondering why isn't there a simple way to find the ciphers supported by a particular ssl context? (Or did I miss it)

I know we can use socket.cipher() to get the one being used for the connection for that particular socket, but why not something to get all supported ciphers?

Another things is,

I have a server which is running openssl library with the cipher string "HIGH+TLSv1.2:!MD5:!SHA1". The client is a python file using the ssl library, with default options, and after the connection is established the socket.cipher() shows the below tuple

('DHE-RSA-AES256-GCM-SHA384', 'TLSv1/SSLv3', 256)

How is the connection established with TLSv1, when I explicitly mentioned TLSv1.2, and how is it using SHA384, when TLSv1 doesn't have support for anything higher then SHA1?

Upvotes: 3

Views: 7438

Answers (2)

Xiong Chiamiov
Xiong Chiamiov

Reputation: 13754

SSLContext.get_ciphers() was added in Python 3.4.

Python 3.11.6 (main, Oct  2 2023, 13:45:54) [Clang 15.0.0 (clang-1500.0.40.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import ssl
>>> from pprint import pprint
>>> pprint(ssl.create_default_context().get_ciphers()[0])
{'aead': True,
 'alg_bits': 256,
 'auth': 'auth-any',
 'description': 'TLS_AES_256_GCM_SHA384         TLSv1.3 Kx=any      Au=any   '
                'Enc=AESGCM(256)            Mac=AEAD',
 'digest': None,
 'id': 50336514,
 'kea': 'kx-any',
 'name': 'TLS_AES_256_GCM_SHA384',
 'protocol': 'TLSv1.3',
 'strength_bits': 256,
 'symmetric': 'aes-256-gcm'}
>>> pprint(sorted([cipher['name'] for cipher in ssl.create_default_context().get_ciphers()]))
['DHE-RSA-AES128-GCM-SHA256',
 'DHE-RSA-AES128-SHA256',
 'DHE-RSA-AES256-GCM-SHA384',
 'DHE-RSA-AES256-SHA256',
 'ECDHE-ECDSA-AES128-GCM-SHA256',
 'ECDHE-ECDSA-AES128-SHA256',
 'ECDHE-ECDSA-AES256-GCM-SHA384',
 'ECDHE-ECDSA-AES256-SHA384',
 'ECDHE-ECDSA-CHACHA20-POLY1305',
 'ECDHE-RSA-AES128-GCM-SHA256',
 'ECDHE-RSA-AES128-SHA256',
 'ECDHE-RSA-AES256-GCM-SHA384',
 'ECDHE-RSA-AES256-SHA384',
 'ECDHE-RSA-CHACHA20-POLY1305',
 'TLS_AES_128_GCM_SHA256',
 'TLS_AES_256_GCM_SHA384',
 'TLS_CHACHA20_POLY1305_SHA256']
>>>

Upvotes: 1

Steffen Ullrich
Steffen Ullrich

Reputation: 123541

I was wondering why isn't there a simple way to find the ciphers supported by a particular ssl context? (Or did I miss it)

Only OpenSSL 1.1.0 added a function SSL_CTX_get_ciphers to access this list and this functionality is not yet available in Python.

('DHE-RSA-AES256-GCM-SHA384', 'TLSv1/SSLv3', 256)

How is the connection established with TLSv1, when I explicitly mentioned TLSv1.2, and how is it using SHA384, when TLSv1 doesn't have support for anything higher then SHA1?

According to the source code Python is using SSL_CIPHER_get_version to find out the version string. The matching OpenSSL documentation says for OpenSSL 1.0.2:

SSL_CIPHER_get_version() returns string which indicates the SSL/TLS protocol version that first defined the cipher. This is currently SSLv2 or TLSv1/SSLv3. In some cases it should possibly return "TLSv1.2" but does not; use SSL_CIPHER_description()

Thus it is a bug in OpenSSL which according to the documentation of the same function in OpenSSL 1.1.0 was fixed in the latest OpenSSL version.

Upvotes: 2

Related Questions