python / cpython

The Python programming language
https://www.python.org/
Other
61.27k stars 29.54k forks source link

ssl.get_server_certificate should allow specifying certificate / key type #76073

Open f1c7752f-9b0d-4783-9df2-62dcbfbc032d opened 6 years ago

f1c7752f-9b0d-4783-9df2-62dcbfbc032d commented 6 years ago
BPO 31892
Nosy @tiran, @alex, @dstufft, @hannob

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields: ```python assignee = None closed_at = None created_at = labels = ['expert-SSL', 'type-feature', '3.8'] title = 'ssl.get_server_certificate should allow specifying certificate / key type' updated_at = user = 'https://github.com/hannob' ``` bugs.python.org fields: ```python activity = actor = 'hanno' assignee = 'none' closed = False closed_date = None closer = None components = ['SSL'] creation = creator = 'hanno' dependencies = [] files = [] hgrepos = [] issue_num = 31892 keywords = [] message_count = 5.0 messages = ['305182', '305380', '305414', '305420', '415242'] nosy_count = 5.0 nosy_names = ['janssen', 'christian.heimes', 'alex', 'dstufft', 'hanno'] pr_nums = [] priority = 'normal' resolution = None stage = 'needs patch' status = 'open' superseder = None type = 'enhancement' url = 'https://bugs.python.org/issue31892' versions = ['Python 3.8'] ```

f1c7752f-9b0d-4783-9df2-62dcbfbc032d commented 6 years ago

The function ssl.get_server_certificate() from the ssl module is supposed to allow fetching the certificate of a TLS server.

However in its current form it provides no way to specify a key type. Many popular hosts (e.g. facebook, google) support both ECDSA and RSA these days, depending on the cipher suites one uses to try to connect to them.

If one wants to fetch the RSA certificate of e.g. facbeook this is not possible with the current python ssl module, as it will always output the ECDSA certificate. One can create a connection with an SSLContext that has only RSA ciphers set, but it's not possible to get the certificate out of an SSLContext. And the get_server_certificate function provides neither a way to bind it to a context nor a way to specify ciphers or key types.

I think there should be an optional parameter to get_server_certificate that allows asking for a specific key type.

tiran commented 6 years ago

Thanks for your feature request, Hanno.

It's fairly easy to implement with current API for TLS protocols up to TLS 1.2, e.g. cipher suite "DEFAULT:!aRSA:!aDSS" or "aECDSA:!NULL" for ECDSA certs.

However TLS 1.3 cipher suites no longer specify authentication and KE/KX algorithms, e.g. TLS13-AES-256-GCM-SHA384. I have to find a way to force OpenSSL's state machine to establish a connection with a specific authentication algorithm.

Memo to me: TLS 1.3 also has EdDSA.

tiran commented 6 years ago

Example implementation of get_server_certificate() with cert type: https://gist.github.com/tiran/6e7a5b00483376e164c951730db7d4e5

TLS 1.3 has a signature_algorithms extension that allows a client to have even more control over the selected certificate and signature algorithms. It defines authentication algorithm (RSA, ECDSA, EdDSA), signature scheme (PKCS#1 v1.5 or PKCS#1 v2.1 aka RSA-PSS for RSA, curve for ECDSA), and hashing algorithm (SHA-1, SHA-2 256/384/512). https://tools.ietf.org/html/draft-ietf-tls-tls13-21#section-4.2.3

I've contacted openssl maintainers and asked them for advice: https://mta.openssl.org/pipermail/openssl-users/2017-November/006834.html

tiran commented 6 years ago

Matt suggested to use https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set1_sigalgs.html The SSL_CTX_set1_sigalgs_list() function takes a string of colon-separated algorithms, e.g. "ECDSA+SHA256:RSA+SHA256" for ECDSA and PKCS#1 v1.5 RSA with both SHA256 as hashing algorithm.

f1c7752f-9b0d-4783-9df2-62dcbfbc032d commented 2 years ago

Any update? :-)