Windows下Python ssl.SSLContext()无法获取对等证书问题求助
解决无法获取TLS对等方证书的问题
嘿,我之前手动配置SSLContext时也踩过类似的坑,尤其是在搭配自签名证书的场景下。结合你的环境(Windows + Python 3.6.5 + OpenSSL 1.0.2k),咱们一步步来排查解决:
核心问题分析
手动创建SSLContext和用create_default_context()的默认行为差异很大——默认上下文会自动配置证书信任、开启证书验证逻辑,而手动创建的上下文需要你显式设置证书相关参数,否则可能导致无法正确请求或获取对等方证书。
解决方案步骤
1. 正确配置证书验证模式
无论是否验证自签名证书的有效性,你都需要明确告诉上下文要请求证书:
- 安全场景:加载自签名CA证书到信任列表,开启强制验证(即使是自签名,也确保是你信任的证书)
- 测试场景:仅获取证书不做严格验证(方便调试,但生产环境不推荐)
2. 显式指定TLS版本和密码套件
注意你的OpenSSL 1.0.2k不支持TLS 1.3,只能选TLSv1/TLSv1_1/TLSv1_2;密码套件要使用OpenSSL支持的格式(可以用openssl ciphers命令查看当前支持的套件列表)。
3. 连接后正确调用证书获取方法
在SSL套接字建立连接后,调用getpeercert(binary_form=False)获取可读的证书结构;如果需要原始二进制证书,设置binary_form=True即可。
完整代码示例
import ssl import socket # 自定义配置参数 TLS_VERSION = ssl.PROTOCOL_TLSv1_2 # 服务器支持的版本,OpenSSL 1.0.2k最高支持到TLSv1_2 CIPHER_SUITES = 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256' SELF_SIGNED_CA_PATH = r'C:\your\path\self-signed-ca.crt' # 你的自签名CA证书路径 SERVER_HOST = 'your-server-domain-or-ip' SERVER_PORT = 443 # 创建自定义SSLContext context = ssl.SSLContext(TLS_VERSION) # 方式1:信任指定自签名证书(推荐生产用) context.load_verify_locations(SELF_SIGNED_CA_PATH) context.verify_mode = ssl.CERT_REQUIRED context.check_hostname = False # 若自签名证书CN与服务器主机名不匹配,需关闭此项 # 方式2:仅获取证书不验证(测试调试用) # context.verify_mode = ssl.CERT_OPTIONAL # context.check_hostname = False # 设置自定义密码套件 context.set_ciphers(CIPHER_SUITES) # 建立连接并获取证书 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: with context.wrap_socket(sock, server_hostname=SERVER_HOST) as ssl_sock: ssl_sock.connect((SERVER_HOST, SERVER_PORT)) # 获取对等方证书 peer_cert = ssl_sock.getpeercert(binary_form=False) if peer_cert: print("成功获取对等方证书:") print(f"证书主题:{peer_cert['subject']}") print(f"证书颁发者:{peer_cert['issuer']}") print(f"有效期:{peer_cert['notBefore']} 至 {peer_cert['notAfter']}") else: print("未获取到对等方证书,请检查连接配置")
额外排查技巧
如果还是无法获取证书,可以开启SSL调试日志查看握手细节:
import logging logging.basicConfig(level=logging.DEBUG)
日志会输出SSL握手的每一步,帮助你确认是否是服务器未发送证书,或者握手过程中出现了其他问题。
内容的提问来源于stack exchange,提问作者None
相关产品推荐
相关产品推荐

