How to list all openssl ciphers available in statically linked python releases?

后端 未结 2 1358
被撕碎了的回忆
被撕碎了的回忆 2021-02-19 15:47

In the python 2.7.8 to 2.7.9 upgrade, the ssl module changed from using

_DEFAULT_CIPHERS = \'DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2\'

to

2条回答
  •  一生所求
    2021-02-19 16:43

    You might want to have a look into openssl cipher's source code at https://github.com/openssl/openssl/blob/master/apps/ciphers.c

    The crucial steps seem to be:

    1. meth = SSLv23_server_method();
    2. ctx = SSL_CTX_new(meth);
    3. SSL_CTX_set_cipher_list(ctx, ciphers), whereas ciphers is your string
    4. ssl = SSL_new(ctx);
    5. sk = SSL_get1_supported_ciphers(ssl);
    6. for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) { print SSL_CIPHER_get_name(sk_SSL_CIPHER_value(sk, i)); }

    The SSL_CTX_set_cipher_list function is called in Python 3.4 in _ssl's set_ciphers method for contexts. You can achieve the same using:

    import socket
    from ssl import SSLSocket
    sslsock = SSLSocket(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
    sslsock.context.set_ciphers('DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2')
    

    The next step would be calling SSL_get1_supported_ciphers() which, unfortunately, is not used in Python's _ssl.c. The closest you can get is the shared_ciphers() method of SSLSocket instances. The (current) implementation is

    static PyObject *PySSL_shared_ciphers(PySSLSocket *self)
    {
        [...]
        ciphers = sess->ciphers;
        res = PyList_New(sk_SSL_CIPHER_num(ciphers));
        for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
            PyObject *tup = cipher_to_tuple(sk_SSL_CIPHER_value(ciphers, i));
            [...]
            PyList_SET_ITEM(res, i, tup);
        }
        return res;
    }
    

    That is, this loop is very similar as in the ciphers.c implementation above, and returns a Python list of ciphers, in the same order as the loop in ciphers.c would.

    Continuing with the sslsock = SSLSocket(...) example from above, you cannot call sslsock.shared_ciphers() before the socket is connected. Otherwise, Python's _ssl module does not create a low-level OpenSSL SSL object, which is needed to read the ciphers. That is different from the implementation in ciphers.c, which creates a low level SSL object without requiring a connection.

    That is how far I got, I hope that helps, and maybe you can figure out what you need based on these findings.

提交回复
热议问题