本文へスキップ
ecdsa.com
Python ssl module (OpenSSL)Python の cryptography

エラーメッセージ

[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired

OpenSSL 1.1.1、3.0、3.5 を使う Python で表現は同じで、メッセージの後には「(_ssl.c:1082)」のようなソースの位置が続きます。有効期間がまだ始まっていない証明書では「certificate is not yet valid」になります。

Python ssl module (OpenSSL) — ssl.SSLCertVerificationError, X509_V_ERR_CERT_HAS_EXPIRED (10)

このエラーの意味

OpenSSL は、チェーン内に、有効期間がこのマシンの現在時刻より前に終了した証明書を見つけました。通常は、サーバーの証明書が更新されていないか、更新した証明書が配信されていないかのどちらかです。クライアントが古い CA バンドルにある期限切れのルートを通るパスを構築している場合や、クライアントの時計が間違っている場合もあります。

発生する理由

修正方法

  1. 1.

    配信されている証明書を確認する

    証明書を読むためだけに検証を無効にして一度だけ取得し、notAfter を確認してください(デコーダーに貼り付けます)。その検証されていない接続を、ほかの目的に使ってはいけません。

    python
    import socket, ssl
    
    # Read the served certificate without verifying it, to see its dates
    ctx = ssl.create_default_context()
    ctx.check_hostname = False
    ctx.verify_mode = ssl.CERT_NONE
    with socket.create_connection(("api.example.com", 443)) as raw:
        with ctx.wrap_socket(raw, server_hostname="api.example.com") as tls:
            der = tls.getpeercert(binary_form=True)
    print(ssl.DER_cert_to_PEM_cert(der))   # paste into a certificate decoder
  2. 2.

    certifi または OS のバンドルを更新する

    サーバー自身の証明書に問題がなければ、クライアントのルートを更新してください。certifi を使うライブラリでは pip install --upgrade certifi を、システムのバンドルでは ca-certificates パッケージを使います。

    bash
    python3 -m pip install --upgrade certifi
    python3 -c "import certifi; print(certifi.__version__, certifi.where())"
  3. 3.

    システムの時計を修正する

    クライアントで NTP を有効にしてください(コンテナーの場合はホストで有効にします)。

    bash
    date -u
    sudo timedatectl set-ntp true

関連するエラー

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