如何列出静态链接的python版本中可用的所有openssl密码? [英] How to list all openssl ciphers available in statically linked python releases?
问题描述
在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
命令行(请参阅
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
某些OpenSSL的编译版本可能未包含此处列出的所有密码,因为某些密码在编译时已被排除.
Some compiled versions of OpenSSL may not include all the ciphers listed here because some ciphers were excluded at compile time.
那么,有没有办法让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?
推荐答案
您可能想在关键步骤似乎是:
-
meth = SSLv23_server_method();
-
ctx = SSL_CTX_new(meth);
-
SSL_CTX_set_cipher_list(ctx, ciphers)
,而ciphers
是您的字符串 -
ssl = SSL_new(ctx);
-
sk = SSL_get1_supported_ciphers(ssl);
-
for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) { print SSL_CIPHER_get_name(sk_SSL_CIPHER_value(sk, i)); }
meth = SSLv23_server_method();
ctx = SSL_CTX_new(meth);
SSL_CTX_set_cipher_list(ctx, ciphers)
, whereasciphers
is your stringssl = SSL_new(ctx);
sk = SSL_get1_supported_ciphers(ssl);
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密码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!