エラーメッセージ
SSL operation failed with code 1. OpenSSL Error messages:
別の表記
- Warning: file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages:
PHP はこの警告を 2 行で出力します。「SSL operation failed with code 1. OpenSSL Error messages:」の後に、1 つまたは複数の OpenSSL のエラーが続きます。OpenSSL 1.1.1 のビルドでは、代わりに「error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed」と表示されます。
PHP streams (file_get_contents, fopen, stream_socket_client, SoapClient, mail libraries) — openssl stream wrapper
このエラーの意味
PHP のストリーム(file_get_contents、fopen、SoapClient、stream_socket_client、およびこれらを基盤とするメールや FTP のライブラリ)で TLS ハンドシェイクが失敗しました。コード 1 は OpenSSL のエラーコード SSL_ERROR_SSL で、実際の理由は次の行に示されます。最も多いのは「error:0A000086:SSL routines::certificate verify failed」です。その後に PHP が「Failed to enable crypto」と「Failed to open stream: operation failed」を追加しますが、これらは原因ではなく結果です。
発生する理由
サーバーの CA が信頼されていない
よくあるプライベート CA やプロキシの CA、または中間証明書を送信していないサーバーが該当します。
PHP のストリームに使用できる CA バンドルがない
よくあるOpenSSL のデフォルトのパスにバンドルがないシステム(Windows、最小構成のイメージ)で、openssl.cafile が設定されていません。
プロトコルまたは暗号スイートが原因の失敗
ときどき2 行目にほかの理由(「unsupported protocol」「alert handshake failure」)が表示される場合は、サーバーと PHP の間に共通の TLS バージョンや暗号スイートがありません。
修正方法
- 1.
続く OpenSSL の行を確認する
「certificate verify failed」は信頼関係か日付の問題を示し、プロトコルのエラーはサーバーの TLS 設定の問題を示します。
text Warning: file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages: error:0A000086:SSL routines::certificate verify failed <- trust/chain/date problem Warning: file_get_contents(): Failed to enable crypto <- consequence, not the cause - 2.
openssl.cafile を設定する
PHP のストリームは openssl.cafile(または openssl.capath)を使い、ext-curl は curl.cainfo を使います。そのため、両方を設定してください。
ini ; php.ini — CA bundle for PHP streams (file_get_contents, SoapClient, stream_socket_client) openssl.cafile = "/etc/ssl/certs/ca-certificates.crt" - 3.
1 つのリクエストだけに CA を渡す
ssl.cafile を指定したストリームコンテキストを使うと、ほかの通信の検証を弱めることなく、プライベート CA を信頼できます。
php // One request with a private CA; verification stays on $context = stream_context_create(['ssl' => [ 'cafile' => '/etc/ssl/private-ca/corp-root-ca.pem', 'verify_peer' => true, 'verify_peer_name' => true, ]]); $body = file_get_contents('https://api.example.com/', false, $context);