【PHP】openssl_error_string() で OpenSSL のエラー内容を取得する
PHP で openssl_sign() や openssl_verify()、openssl_pkey_get_private() などの OpenSSL 系関数を使っていると、処理が false を返して失敗することがあります。
ただ、戻り値が false だけだと、何が原因で失敗したのか分かりません。
そんなときに使うのが openssl_error_string() です。
この関数を使うと、OpenSSL 内部で発生したエラー内容を文字列として取得できます。
openssl_error_string() とは
openssl_error_string() は、OpenSSL のエラーキューに積まれているエラーメッセージを 1 件ずつ取り出す関数です。
戻り値は次のとおりです。
- エラーがある場合:
string - これ以上エラーがない場合:
false
PHP 公式マニュアル:
openssl_error_string - PHP Manual
ポイントは、1 回だけ呼べば終わりではないことです。
OpenSSL のエラーはキューに複数積まれることがあるため、通常は while で取り切ります。
基本的な使い方
OpenSSL 系の処理が失敗した直後に、次のようにエラーを回収します。
| |
実務では error_log() にそのまま流すか、配列にためてまとめて記録する形が扱いやすいです。
| |
なぜ while で読むのか
openssl_error_string() は最後のエラー 1 件だけを返す関数ではなく、キューから順番に取り出す関数です。
そのため、次のように空になるまで取得するのが基本です。
| |
特に、鍵や証明書の読み込みに失敗したときは、関連するエラーが複数件積まれることがあります。
1 件だけ見て判断すると、原因を見誤ることがあります。
よくある利用場面
openssl_error_string() は、次のような場面で役に立ちます。
- 秘密鍵や公開鍵の読み込みに失敗したとき
- PEM 形式の文字列が壊れているとき
- パスフレーズが違うとき
- 署名や検証に失敗したとき
- 暗号化や復号に失敗したとき
- 証明書や CSR の生成に失敗したとき
OpenSSL 系の API は失敗時に false しか返さないことが多いため、調査では openssl_error_string() がほぼ必須です。
エラーの具体例
実際には、環境によって次のようなエラー文字列が出ることがあります。
PEM の形式が不正なとき
| |
このエラーは、PEM 形式として読み込める開始行が見つからない場合によく出ます。
たとえば次のような原因が考えられます。
-----BEGIN PRIVATE KEY-----のようなヘッダがない- 改行が壊れている
- PEM ではない文字列を渡している
- 証明書を期待している箇所に秘密鍵を渡している
関連する例:
OpenSSL issue: no start line
別の実例:
cannot load certificate / no start line
復号に失敗したとき
| |
このエラーは、復号に必要な条件がそろっていないときによく出ます。
- パスワードが違う
- 鍵が違う
- IV が違う
- 暗号化方式が一致していない
- 暗号文が壊れている
エラー文字列の見方
OpenSSL のエラーはおおむね次のような構造です。
| |
たとえば、
| |
であれば、主に見るべき箇所は次の 3 つです。
PEM routines- どの種類の内部処理で失敗したか
get_name- どの処理の途中で失敗したか
no start line- 何が問題だったか
実務では、まず最後の reason string を見るだけでも原因をかなり絞れます。
OpenSSL 公式の関連ドキュメント:
利用時の注意点
失敗した直後に読む
後続で別の OpenSSL 関数を呼ぶと、エラーキューの内容が変わってしまうことがあります。
エラー調査をしたいなら、失敗直後に回収した方が安全です。
ユーザーに詳細をそのまま見せない
openssl_error_string() の内容は調査には有用ですが、利用者向けのエラーメッセージとしては詳細すぎます。
画面には一般的なメッセージだけ出し、詳細はログに残す運用の方が無難です。
| |
エラー文字列は環境差がある
同じコードでも、次の条件で表示内容が変わることがあります。
- OpenSSL のバージョン
- PHP のビルド差
- OS やディストリビューション差
そのため、ネット上で見つけた文言と完全一致しなくても、bad decrypt や no start line のような理由部分が近ければ、同系統の問題である可能性が高いです。
まとめ
openssl_error_string() は、PHP で OpenSSL 関連処理の失敗原因を調べるための基本関数です。
押さえておきたいポイントは次のとおりです。
- OpenSSL のエラー内容を文字列で取得できる
- エラーはキューに積まれるので
whileで取り切る - 失敗した直後に読む
- 詳細は画面表示ではなくログに残す
- エラー文言は環境によって多少変わる
OpenSSL 周りは false だけでは原因が分かりにくいので、失敗時はまず openssl_error_string() を確認する癖をつけておくと調査がかなり楽になります。