pyopenssl 的 get_client_ca_list() 在 TLS1.3

问题描述

问题和标题于 2021 年 4 月 2 日更新:

我发布了关于如何获取给定 https 服务器允许的 CA 列表的question 有人建议使用 pyopenssl,这帮助我解决了当时的问题。

所以我尝试了以下代码

import socket
from OpenSSL import SSL

def get_client_cert_cas(hostname,port):
    ctx = SSL.Context(SSL.SSLv23_METHOD)
    sock = SSL.Connection(ctx,socket.socket(socket.AF_INET,socket.soCK_STREAM))
    # next line for SNI
    sock.set_tlsext_host_name(hostname.encode("utf-8"))
    sock.connect((hostname,port))
    return sock.get_client_ca_list()

它总是不返回任何结果。 经过一番玩耍后,我想出了以下解决方案: 在调用 sock.get_client_ca_list()) 之前,我与 sock.do_handshake()

握手

这适用于我目前遇到的所有网络服务器。

但是现在我遇到了一个 https 服务器,其中 SSL 端点位于 F5 现在是代码

def get_client_cert_cas(hostname,port))
    sock.do_handshake() # Now client_ca_list will not be empty
    return sock.get_client_ca_list()

返回一个空结果。

openssl 命令 openssl s_client -connect <hostname>:<port> -servername <hostname> 返回正确的结果。

经过进一步调查,我发现 F5 使用 TLSv1.3,而“工作”服务器使用 TLSv1.2

现在我最后一个有效的修复是强制使用 TLSv1.2

def get_client_cert_cas(hostname,port):
    ctx = SSL.Context(SSL.SSLv23_METHOD)
    # It seems I must ensure to not use TLSV1.3
    ctx.set_options(SSL.OP_NO_TLSv1_3)
    sock = SSL.Connection(ctx,port))
    sock.do_handshake() # Now client_ca_list will not be empty
    return sock.get_client_ca_list()

是否可以预料,get_client_ca_list() 不适用于 TLSV1.3,还是在 TLS1.3 情况下需要执行其他操作才能获得 get_client_ca_list() 的结果?

请注意,我并不坚持 pyopenssl 这只是我目前找到的唯一解决方案。

如果问题可以用 cryptography 或任何其他包解决,那么这对我来说也很好。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)