Python SSL疑问:为何需将对等方证书作为CA传入?
问题分析与解决方案
问题根源
你遇到的验证失败问题,核心原因是生成服务端/客户端证书时未添加对应的扩展密钥用法(EKU),以及证书链不完整:
- Python的
ssl.create_default_context会根据指定的Purpose验证证书用途:Purpose.SERVER_AUTH要求服务端证书必须包含serverAuth(TLS Web服务器认证)扩展Purpose.CLIENT_AUTH要求客户端证书必须包含clientAuth(TLS Web客户端认证)扩展
默认用openssl x509签名的证书没有这些扩展,导致上下文验证不通过,触发"自签名证书"或"未知CA"错误。
- 服务端默认只发送自身证书,未携带CA证书,客户端无法完整构建信任链验证签名。
解决方案
1. 添加证书扩展配置
创建两个扩展配置文件,明确证书的用途:
server_ext.cnf(服务端证书扩展)
[req] req_extensions = v3_req distinguished_name = req_distinguished_name [req_distinguished_name] [v3_req] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth subjectAltName = IP:127.0.0.1 # 若用域名连接,改为DNS:your-domain.com
client_ext.cnf(客户端证书扩展)
[req] req_extensions = v3_req distinguished_name = req_distinguished_name [req_distinguished_name] [v3_req] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = clientAuth
2. 重新生成服务端/客户端证书
在证书签名步骤中添加-extfile参数指定扩展配置:
服务端证书签名
openssl x509 -CAcreateserial -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -out server.crt -extfile server_ext.cnf
客户端证书签名
openssl x509 -CAcreateserial -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -out client.crt -extfile client_ext.cnf
3. 构建服务端完整证书链(推荐)
将CA证书附加到服务端证书后,让服务端握手时发送完整信任链:
cat server.crt ca.crt > server_fullchain.crt
修改服务端代码中的证书加载部分:
ssl_context.load_cert_chain( certfile='server_fullchain.crt', keyfile='server.key' )
4. 验证证书扩展是否生效
检查服务端证书扩展:
openssl x509 -in server.crt -text -noout | grep -A 3 "Extended Key Usage"
应输出:
Extended Key Usage: TLS Web Server Authentication
检查客户端证书扩展:
openssl x509 -in client.crt -text -noout | grep -A 3 "Extended Key Usage"
应输出:
Extended Key Usage: TLS Web Client Authentication
验证修复效果
保持原有代码不变(客户端cafile='ca.crt',服务端cafile='ca.crt'),重启服务端和客户端,此时SSL握手应成功完成,无需指定对方证书作为CA。
内容的提问来源于stack exchange,提问作者mv_p
相关产品推荐
相关产品推荐

