gpt4 book ai didi

Python 'ssl' shared_ciphers() 没有记录在案?

转载 作者:太空宇宙 更新时间:2023-11-04 04:49:29 25 4
gpt4 key购买 nike

根据 Python 3 documentation :

SSLSocket.shared_ciphers()

Return the list of ciphers shared by the client during the handshake.

我将其解释为 TLS CLIENT_HELLO 数据包中的“密码套件” block (握手的第一个数据包)将被返回。给定以下 openssl 命令:

openssl s_client -connect 172.16.30.3:443 -cipher ECDHE-RSA-AES128-SHA

电线上的数据包,如 wireshark 中所示,显示为带有该单一密码(和 RENEGOTIATION 伪密码):

Wireshark view of TLS CLIENT_HELLO Cipher Suites

但是,当我的服务器代码在握手后调用 shared_ciphers() 时,返回的是服务器的整个密码套件,而不是客户端在握手中发送的密码。这是服务器打印的内容:

# ./shared_ciphers_test.py 
Server Cipher Suite from get_ciphers():
ECDHE-ECDSA-AES128-SHA256
ECDHE-RSA-AES128-SHA
ECDHE-ECDSA-AES128-SHA
ECDHE-RSA-RC4-SHA
Listening...
Connection accepted from ('172.16.30.4', 32888)
Client Cipher Suite from shared_ciphers():
ECDHE-ECDSA-AES128-SHA256
ECDHE-RSA-AES128-SHA
ECDHE-ECDSA-AES128-SHA
ECDHE-RSA-RC4-SHA
#

问题:

  1. 我会不会误解文档?
  2. 鉴于下面的服务器代码,我是否做错了什么会给我这个错误的结果?
  3. 是否有合适的论坛供我将此作为潜在错误进行报告? (Github 似乎是该模块的权威来源,但我没有看到在那里报告的论坛。不过我的 git-fu 很糟糕。)

这是服务器代码:

#!/usr/bin/python3

import socket, ssl, sys, time

listener = socket.socket()
listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listener.bind(('0.0.0.0', 443))
listener.listen(5)

context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain(certfile='certchain.pem', keyfile='keyfile.pem')
context.set_ciphers('ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-RC4-SHA')

print('Server Cipher Suite from get_ciphers():')
for item in context.get_ciphers():
print(' {}'.format(item['name']))

print('Listening...')
newsocket, fromaddr = listener.accept()
connstream = context.wrap_socket(newsocket, server_side=True)
print('Connection accepted from {}'.format(connstream.getpeername()))
print('Client Cipher Suite from shared_ciphers():')
for item in connstream.shared_ciphers():
print(' {}'.format(item[0]))
sys.exit(0)

最佳答案

这是一个错误。

查看the C implementation for the ssl module可以看出两者都是get_ciphersshared_ciphers通过使用 SSL_get_ciphers 实现,尽管一个使用上下文作为基础,另一个使用来自当前连接的 SSL 对象。 SSL_get_ciphers 从 SSL 或上下文对象访问 cipher_list 属性,这似乎是最初配置的密码列表。

我认为获取共享密码的正确函数实际上是 SSL_get_client_ciphers .此函数访问 ssl->session->ciphers,与更明确命名(但未记录)的 SSL_get_shared_ciphers 函数相同。 SSL_get_client_ciphers 仅在 OpenSSL 1.1.0 之后可用,因此需要直接访问旧版本的 ssl->session->ciphers

看起来 OpenSSL 根本不提供这样的功能,因此 Python 也不能真正提供这个功能。功能SSL_get_client_ciphers , SSL_get_shared_ciphers 和对 ssl->session->ciphers 的访问都提供对客户端提供的密码的访问,即 SSL_get_client_ciphers 的名称建议与 SSL_get_shared_ciphers 建议相反。此信息与内部 ssl3_choose_cipher 函数中的服务器端 cipher_list 相结合,其中选择了通用密码。获取实际共享的密码(另外受使用证书类型的限制)将意味着重新实现此功能的主要部分。

有趣的是,看起来 OpenSSL 开发人员甚至不知道 ssl->session->ciphers 真正包含什么。从 0.9.8 天到最新版本的 OpenSSL,可以找到 ssl_session_st 结构的 ciphers 成员的以下文档:

 STACK_OF(SSL_CIPHER) *ciphers; /* shared ciphers? */

基于此,他们似乎(错误地)认为此结构包含共享密码,但他们不确定。


请注意,我已经为 Python 提交了一个关于这个错误实现的功能的错误:https://bugs.python.org/issue32813 .根据 OpenSSL 提供的内容,我的猜测是该函数应该从 Python 中完全删除,而不是返回错误的数据。我还为 OpenSSL 提交了一个关于 SSL_get_shared_ciphers 的误导性名称的错误:https://github.com/openssl/openssl/issues/5317 .

关于Python 'ssl' shared_ciphers() 没有记录在案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48717497/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com