本文へスキップ
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 に加えて、AES-GCM または ChaCha20-Poly1305 と ECDHE を組み合わせた 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;

関連するエラー

署名エラーデータベースをすべて見る