Copy & Paste Engineer

2026/3/20

【PHP】openssl_error_string で OpenSSL のエラー内容を取得する

【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 件ずつ取り出す関数です。

戻り値は次のとおりです。

PHP 公式マニュアル: openssl_error_string - PHP Manual

ポイントは、1 回だけ呼べば終わりではないことです。 OpenSSL のエラーはキューに複数積まれることがあるため、通常は while で取り切ります。

基本的な使い方

OpenSSL 系の処理が失敗した直後に、次のようにエラーを回収します。

<?php

$privateKey = openssl_pkey_get_private($pem, $passphrase);

if ($privateKey === false) {
    while (($error = openssl_error_string()) !== false) {
        error_log($error);
    }
}

実務では error_log() にそのまま流すか、配列にためてまとめて記録する形が扱いやすいです。

<?php

$signature = '';
$result = openssl_sign($data, $signature, $privateKey, OPENSSL_ALGO_SHA256);

if ($result === false) {
    $errors = [];

    while (($error = openssl_error_string()) !== false) {
        $errors[] = $error;
    }

    error_log('[OpenSSL] ' . implode(' | ', $errors));
}

なぜ while で読むのか

openssl_error_string() は最後のエラー 1 件だけを返す関数ではなく、キューから順番に取り出す関数です。

そのため、次のように空になるまで取得するのが基本です。

<?php

while (($error = openssl_error_string()) !== false) {
    echo $error, PHP_EOL;
}

特に、鍵や証明書の読み込みに失敗したときは、関連するエラーが複数件積まれることがあります。 1 件だけ見て判断すると、原因を見誤ることがあります。

よくある利用場面

openssl_error_string() は、次のような場面で役に立ちます。

OpenSSL 系の API は失敗時に false しか返さないことが多いため、調査では openssl_error_string() がほぼ必須です。

エラーの具体例

実際には、環境によって次のようなエラー文字列が出ることがあります。

PEM の形式が不正なとき

error:0909006C:PEM routines:get_name:no start line

このエラーは、PEM 形式として読み込める開始行が見つからない場合によく出ます。

たとえば次のような原因が考えられます。

関連する例: OpenSSL issue: no start line

別の実例: cannot load certificate / no start line

復号に失敗したとき

error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt

このエラーは、復号に必要な条件がそろっていないときによく出ます。

実例: bad decrypt の実行例

エラー文字列の見方

OpenSSL のエラーはおおむね次のような構造です。

error:[error code]:[library name]:[function name]:[reason string]

たとえば、

error:0909006C:PEM routines:get_name:no start line

であれば、主に見るべき箇所は次の 3 つです。

実務では、まず最後の reason string を見るだけでも原因をかなり絞れます。

OpenSSL 公式の関連ドキュメント:

利用時の注意点

失敗した直後に読む

後続で別の OpenSSL 関数を呼ぶと、エラーキューの内容が変わってしまうことがあります。 エラー調査をしたいなら、失敗直後に回収した方が安全です。

ユーザーに詳細をそのまま見せない

openssl_error_string() の内容は調査には有用ですが、利用者向けのエラーメッセージとしては詳細すぎます。

画面には一般的なメッセージだけ出し、詳細はログに残す運用の方が無難です。

<?php

if ($result === false) {
    $errors = [];

    while (($error = openssl_error_string()) !== false) {
        $errors[] = $error;
    }

    error_log('[OpenSSL] ' . implode(' | ', $errors));

    echo '署名処理に失敗しました。';
}

エラー文字列は環境差がある

同じコードでも、次の条件で表示内容が変わることがあります。

そのため、ネット上で見つけた文言と完全一致しなくても、bad decryptno start line のような理由部分が近ければ、同系統の問題である可能性が高いです。

まとめ

openssl_error_string() は、PHP で OpenSSL 関連処理の失敗原因を調べるための基本関数です。

押さえておきたいポイントは次のとおりです。

OpenSSL 周りは false だけでは原因が分かりにくいので、失敗時はまず openssl_error_string() を確認する癖をつけておくと調査がかなり楽になります。

参考