本文介绍了如何列出静态链接的python版本中可用的所有openssl密码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在python 2.7.8到2.7.9升级中,ssl模块已从使用更改为

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'

_DEFAULT_CIPHERS = (
    'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:'
    'DH+HIGH:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+HIGH:RSA+3DES:ECDH+RC4:'
    'DH+RC4:RSA+RC4:!aNULL:!eNULL:!MD5'
)

我想知道这如何影响在Windows上通过python安装建立SSL/TLS连接时使用的实际有序SSL密码首选项列表".

例如,要弄清楚密码列表扩展到的有序SSL密码首选项列表",我通常使用openssl ciphers命令行(请参阅),例如,使用openssl v1.0.1k,我可以看到默认的python 2.7.8密码列表扩展为什么:

For example, to figure out what "ordered SSL cipher preference list" a cipher list expands to, I'd normally use the openssl ciphers command line (see man page) e.g with openssl v1.0.1k I can see what that default python 2.7.8 cipher list expands to:

$ openssl ciphers -v 'DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2'
ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH     Au=RSA  Enc=AESGCM(256) Mac=AEAD
ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AESGCM(256) Mac=AEAD
ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH     Au=RSA  Enc=AES(256)  Mac=SHA384
ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AES(256)  Mac=SHA384
ECDHE-RSA-AES256-SHA    SSLv3 Kx=ECDH     Au=RSA  Enc=AES(256)  Mac=SHA1
ECDHE-ECDSA-AES256-SHA  SSLv3 Kx=ECDH     Au=ECDSA Enc=AES(256)  Mac=SHA1
SRP-DSS-AES-256-CBC-SHA SSLv3 Kx=SRP      Au=DSS  Enc=AES(256)  Mac=SHA1
SRP-RSA-AES-256-CBC-SHA SSLv3 Kx=SRP      Au=RSA  Enc=AES(256)  Mac=SHA1
...
snip!

当在python动态加载openssl ciphers使用的相同OpenSSL库的Linux上运行时效果很好.

That works great when on Linux where python is dynamically loading the same OpenSSL library that openssl ciphers uses:

$ ldd /usr/lib/python2.7/lib-dynload/_ssl.x86_64-linux-gnu.so | grep libssl
        libssl.so.1.0.0 => /lib/x86_64-linux-gnu/libssl.so.1.0.0 (0x00007ff75d6bf000)
$ ldd /usr/bin/openssl | grep libssl
        libssl.so.1.0.0 => /lib/x86_64-linux-gnu/libssl.so.1.0.0 (0x00007fa48f0fe000)

但是,在Windows上,Python版本似乎可以静态链接OpenSSL库.这意味着openssl ciphers命令无法帮助我,因为它使用了不同版本的库,该库可能支持与python内置库不同的密码.

However, on Windows the Python build appears to statically link the OpenSSL library. This means that the openssl ciphers command cannot help me, because it uses a different version of the library, which may have support for different ciphers than the library built into python.

我可以很容易地找出使用哪个版本的OpenSSL轻松构建两个python版本:

I can find out what version of OpenSSL was used to build each of the two python releases easily enough:

$ python-2.7.8/python -c 'import ssl; print ssl.OPENSSL_VERSION'
OpenSSL 1.0.1h 5 Jun 2014

$ python-2.7.9/python -c 'import ssl; print ssl.OPENSSL_VERSION'
OpenSSL 1.0.1j 15 Oct 2014

但是,即使我可以找到并下载用于1.0.1h和1.0.1j发行版的openssl命令行版本,也无法确定它们使用与内置于python中的lib相同的选项进行编译,并且从手册页中我们知道

But even if I could find and download a build of the openssl command line for both the 1.0.1h and 1.0.1j releases, I cannot be sure that they were compiled with the same options as the lib built into python, and from the man page we know that

那么,有没有办法让python的ssl模块为我提供类似于openssl ciphers -v命令的输出?

So, is there a way to get python's ssl module to give me output similar to that from the openssl ciphers -v command?

推荐答案

您可能想在 https://github.com/openssl/openssl/blob/master/apps/ciphers.c

关键步骤似乎是:

  1. meth = SSLv23_server_method();
  2. ctx = SSL_CTX_new(meth);
  3. SSL_CTX_set_cipher_list(ctx, ciphers),而ciphers是您的字符串
  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)); }
  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)); }

在Python 3.4中,_ssl的set_ciphers方法中为上下文调用了SSL_CTX_set_cipher_list函数.您可以使用以下方法实现相同的目的:

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')

下一步将调用SSL_get1_supported_ciphers(),不幸的是,该SSL_get1_supported_ciphers()在Python的 _ssl.c .您可以获得的最接近的是SSLSocket实例的shared_ciphers()方法. (当前的)实现是

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;
}

也就是说,此循环与上述ciphers.c实现中的循环非常相似,并以与ciphers.c中的循环相同的顺序返回Python密码列表.

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.

继续上面的sslsock = SSLSocket(...)示例,您不能在连接套接字之前调用sslsock.shared_ciphers().否则,Python的_ssl模块不会创建读取密码所需的低级OpenSSL SSL对象.这与ciphers.c中的实现不同,该实现无需连接即可创建低级SSL对象.

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.

这篇关于如何列出静态链接的python版本中可用的所有openssl密码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-26 16:22