Python';ssl';共享密码()是否未按文档记录?

Python';ssl';共享密码()是否未按文档记录?,python,python-3.x,ssl,Python,Python 3.x,Ssl,根据Python 3: SSLSocket.shared_密码() 返回握手期间客户端共享的密码列表 我认为这意味着将返回来自TLS CLIENT_HELLO数据包(握手的第一个数据包)的“密码套件”块。给定以下openssl命令: openssl s_client -connect 172.16.30.3:443 -cipher ECDHE-RSA-AES128-SHA wireshark中显示的在线数据包使用该单一密码(以及重新协商的伪密码)显示: 但是,当我的服务器代码在握手后调用sh

根据Python 3:

SSLSocket.shared_密码()

返回握手期间客户端共享的密码列表

我认为这意味着将返回来自TLS CLIENT_HELLO数据包(握手的第一个数据包)的“密码套件”块。给定以下openssl命令:

openssl s_client -connect 172.16.30.3:443 -cipher ECDHE-RSA-AES128-SHA
wireshark中显示的在线数据包使用该单一密码(以及重新协商的伪密码)显示:

但是,当我的服务器代码在握手后调用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
#
问题:

  • 我可能会误读文档吗
  • 考虑到下面的服务器代码,我是否做了任何错误的事情,从而得到了不正确的结果
  • 是否有一个合适的论坛,我可以报告这是一个潜在的错误?(似乎是该模块的权威来源,但我在那里没有看到报道的论坛。不过我的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)
    
    这是一个错误

    通过查看,可以看到和都是通过使用实现的,尽管一个使用上下文作为基础,另一个使用来自当前连接的SSL对象。和
    SSL\u get\u ciphers
    从SSL或上下文对象访问
    cipher\u list
    属性,该对象似乎是最初配置的密码列表

    我认为获得共享密码的正确功能实际上是。此函数访问
    ssl->session->ciphers
    ,与名称更清晰(但未记录)的
    ssl\u get\u shared\u ciphers
    函数相同
    SSL\u get\u client\u ciphers
    仅在OpenSSL 1.1.0之后可用,因此对于较旧版本,需要直接访问
    SSL->session->ciphers

    看起来OpenSSL根本不提供这种功能,因此Python也不能真正提供这种功能。
    SSL\u-get\u-shared\u-ciphers
    和访问
    SSL->session->ciphers
    功能都提供了对客户端提供的密码的访问,也就是说,
    SSL\u-get\u-client\u-ciphers
    的名称确切含义和
    SSL\u-get\u-shared\u-ciphers
    的含义相反。此信息与服务器端的
    cipher\u列表
    结合在一起,该列表位于选择常用密码的内部
    ssl3\u choose\u cipher
    函数中。获取实际共享的密码(还受到使用何种证书的限制)意味着重新实现此函数的主要部分

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

     STACK_OF(SSL_CIPHER) *ciphers; /* shared ciphers? */
    
    基于此,他们似乎(错误地)认为此结构包含共享密码,但他们不确定



    注意,我已经为Python提交了一个错误实现功能的bug:。根据OpenSSL提供的信息,我猜测应该完全从Python中删除该函数,而不是返回错误的数据。我还为OpenSSL提交了一个错误,关于SSL\u get\u shared\u密码的误导性名称:

    出色的侦查(但是,嗯,“啊”)。查看源代码注释,我还认为有两种方法可以解释“共享”(“客户端与服务器共享的内容”和“客户端与服务器之间共享的子集是什么”),两者都不符合这种行为。@gowenfawr:将
    SSL\u get\u shared\u密码
    视为客户端与服务器共享的密码是一个有趣的论点。但是,考虑到著名的“无共享密码”SSL问题显然意味着客户端和服务器不共享相同的密码,我认为SSL上下文中的“共享密码”应该始终意味着客户端和服务器具有相同的密码。