python - 如何列出静态链接的 python 版本中可用的所有 openssl 密码?

标签 python windows security python-2.7 openssl

在python 2.7.8到2.7.9升级中,ssl模块由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 命令行(参见 man page ),例如使用 openssl v1 .0.1k 我可以看到默认的 python 2.7.8 密码列表扩展为:

$ 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!

在 Linux 上,python 动态加载 openssl ciphers 使用的相同 OpenSSL 库时效果很好:

$ 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 内置库不同的密码。

我可以很容易地找出分别使用哪个版本的 OpenSSL 来构建这两个 python 版本:

$ 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 中的库,来自 man page我们知道

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 命令的输出?

最佳答案

您可能想查看 openssl cipher的源代码位于 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)); }

SSL_CTX_set_cipher_list在 _ssl 的 set_ciphers 中的 Python 3.4 中调用函数上下文的方法。您可以使用以下方法实现相同的效果:

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()不幸的是,它没有在 Python 的 _ssl.c 中使用。 .您可以获得的最接近的是 shared_ciphers() SSLSocket的方法|实例。 (当前)实现是

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 中的非常相似上面的实现,并返回一个 Python 密码列表,顺序与 ciphers.c 中的循环相同会的。

继续sslsock = SSLSocket(...)上面的示例,您不能调用 sslsock.shared_ciphers()在连接 socket 之前。否则,Python 的 _ssl 模块不会创建读取密码所需的低级 OpenSSL SSL 对象。这与 ciphers.c 中的实现不同,它创建一个低级别的 SSL 对象而不需要连接。

这就是我的进展,希望对您有所帮助,也许您可​​以根据这些发现找出您需要什么。

关于python - 如何列出静态链接的 python 版本中可用的所有 openssl 密码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28332448/

相关文章:

windows - 如何防止 Windows 中的焦点窃取?

c - Visual Studio 社区 2015 和 KMD

security - 基于ssh key 的网站访问?

python - 从 Python 脚本将数据插入 MySQL 表

python - pandas 滚动分组时间序列数据

python - 如何计算两列数据框中的真值和假值?

python - 如何以编程方式跨平台发现 git 使用的编辑器?

windows - 从 Linux 告诉 Windows(通过网络)

security - 如何安全登录gitlab中的私有(private)docker注册表?

mysql - 在MySQL 5.x中,是否可以根据条件授予权限(不使用 View )?