跳到主要内容
ecdsa.com
Python ssl module (OpenSSL)Python cryptography 库

错误信息

[SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] ssl/tls alert handshake failure

也可能输出为

  • [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure

原因代码始终是 SSLV3_ALERT_HANDSHAKE_FAILURE,但文本取决于 OpenSSL:OpenSSL 3.3 及更高版本为“ssl/tls alert handshake failure”,更早的版本为“sslv3 alert handshake failure”。后面跟着源代码位置,例如“(_ssl.c:1082)”。

Python ssl module (OpenSSL) — ssl.SSLError, TLS alert 40 (handshake_failure) from the server

含义

服务器以 TLS 告警 40(handshake_failure)中止了握手。它在 Python 的 ClientHello 中找不到可接受的参数,或者要求提供客户端证书而客户端没有出示。告警本身不携带任何详细信息,因此只能通过比较双方各自支持的内容,或查看服务器日志来找出原因。

原因

修复方法

  1. 1.

    比较密码套件列表

    打印这个 Python 提供的套件,并与服务器的列表(例如通过 nmap --script ssl-enum-ciphers 获取)比较。如果没有交集,说明服务器需要更新。

    python
    import ssl
    ctx = ssl.create_default_context()
    print(sorted(c["name"] for c in ctx.get_ciphers()))   # what this Python offers (TLS 1.2 names)
  2. 2.

    出示客户端证书

    对于 mTLS API,用 load_cert_chain() 把客户端证书和密钥加载到上下文中;requests 则使用 cert=("client.pem", "client.key")。

    python
    import ssl, urllib.request
    
    ctx = ssl.create_default_context()
    ctx.load_cert_chain(certfile="client.pem", keyfile="client.key")   # mutual TLS
    urllib.request.urlopen("https://mtls.example.com/", context=ctx)
  3. 3.

    服务器所有者:提供现行的密码套件

    所有仍在维护的客户端都接受 TLS 1.3,以及采用 ECDHE 搭配 AES-GCM 或 ChaCha20-Poly1305 的 TLS 1.2。

    text
    # Server side: offer TLS 1.3 and TLS 1.2 ECDHE + AEAD suites
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;

相关错误

浏览完整的签名错误库