【PHP8.x】openssl_x509_verify()関数の使い方
openssl_x509_verify関数の使い方について、初心者にもわかりやすく解説します。
基本的な使い方
openssl_x509_verify関数は、X.509形式のデジタル証明書が信頼できるものであるか、その正当性を検証する関数です。この関数は、インターネット上でのセキュアな通信や、デジタル署名の確認において、通信相手や情報の提供元が偽装されていないこと、またその証明書が改ざんされていないことを保証するために利用されます。
具体的には、与えられた証明書の署名が有効であるか、証明書の有効期限が切れていないか、そしてその証明書を発行した認証局(CA)が信頼できるものであるかを確認します。通常、検証したい証明書と、その証明書を発行したCAの証明書、または信頼する証明書が格納されたファイルやディレクトリのパスを引数として指定して呼び出します。
検証が成功した場合は整数値の1を返し、検証に失敗した場合は0を返します。何らかのシステムエラーや不正な引数が渡された場合には-1を返します。この関数は、例えばウェブサーバーがクライアント証明書を検証する際や、クライアントがサーバー証明書の信頼性を確認する際など、暗号化通信のセキュリティを確立するために不可欠な役割を担っています。システムエンジニアにとって、安全なアプリケーションを構築する上で、証明書の検証メカニズムを理解することは非常に重要です。
構文(syntax)
1<?php 2$is_verified = openssl_x509_verify( 3 $certificate_string_or_OpenSSLCertificate, 4 $signature_source_string, 5 $public_key_string_or_OpenSSLAsymmetricKey_or_OpenSSLCertificate, 6 $optional_algorithms_array 7); 8?>
引数(parameters)
OpenSSLCertificate|string $certificate, OpenSSLAsymmetricKey|OpenSSLCertificate|string $public_key
- OpenSSLCertificate|string $certificate: 検証する証明書オブジェクトまたは証明書を表す文字列
- OpenSSLAsymmetricKey|OpenSSLCertificate|string $public_key: 証明書を検証するための公開鍵オブジェクト、証明書オブジェクト、または公開鍵を表す文字列
戻り値(return)
int
openssl_x509_verify 関数は、指定された証明書が署名者によって検証されたかどうかを示す整数値を返します。返される値は、検証の成功、失敗、またはエラー状況を示します。
サンプルコード
PHP openssl_x509_verifyで証明書を検証する
1<?php 2 3/** 4 * openssl_x509_verify関数の使用例を示すスクリプト。 5 * このスクリプトは、自己署名証明書を生成し、その証明書が自身の公開鍵で 6 * 正しく署名されているか(つまり、証明書自体が破損していないかなど)を検証します。 7 * 8 * システムエンジニアを目指す初心者の方へ: 9 * openssl_x509_verifyは、X.509形式のデジタル証明書が、指定された公開鍵によって 10 * 正しく署名されているかを確認するために使われます。 11 * 例えば、ウェブサイトのSSL証明書が、信頼できる認証局(CA)の公開鍵で 12 * 署名されているかを検証する際などに利用されます。 13 * この例では、最もシンプルなケースとして「自己署名証明書」とその「自身の公開鍵」を 14 * 用いて検証を行っています。 15 */ 16 17// 1. 秘密鍵を生成します。 18// これは、証明書を署名するために使用される秘密の鍵です。 19$privateKey = openssl_pkey_new([ 20 "private_key_bits" => 2048, // 鍵のビット長(強度) 21 "private_key_type" => OPENSSL_KEYTYPE_RSA, // 鍵の種類(RSA) 22]); 23 24if ($privateKey === false) { 25 die("エラー: 秘密鍵の生成に失敗しました。" . openssl_error_string()); 26} 27echo "ステップ1: 秘密鍵を生成しました。\n"; 28 29// 2. 証明書署名要求 (CSR) を生成します。 30// CSRは、証明書を発行してもらうために認証局に送る情報を含んでいます。 31// この例では自己署名証明書なので、認証局には送りません。 32$csr = openssl_csr_new([ 33 "countryName" => "JP", // 国名 34 "stateOrProvinceName" => "Tokyo", // 都道府県名 35 "localityName" => "Shinjuku", // 市区町村名 36 "organizationName" => "Example Corp", // 組織名 37 "commonName" => "localhost", // コモンネーム(ホスト名など) 38], $privateKey); 39 40if ($csr === false) { 41 die("エラー: CSRの生成に失敗しました。" . openssl_error_string()); 42} 43echo "ステップ2: 証明書署名要求 (CSR) を生成しました。\n"; 44 45// 3. 自己署名証明書を生成します。 46// 生成したCSRと秘密鍵を使って、有効期間365日の証明書を作成します。 47// 第二引数に 'null' を指定すると、自己署名証明書になります。 48// $certificate オブジェクトには、証明書データと公開鍵情報が含まれます。 49$certificate = openssl_csr_sign($csr, null, $privateKey, 365, [ 50 'digest_alg' => 'sha256', // 署名に使用するハッシュアルゴリズム 51]); 52 53if ($certificate === false) { 54 die("エラー: 自己署名証明書の生成に失敗しました。" . openssl_error_string()); 55} 56echo "ステップ3: 自己署名証明書を生成しました。\n"; 57 58// 4. openssl_x509_verify 関数を使用して証明書を検証します。 59// 第一引数: 検証したい証明書オブジェクト ($certificate)。 60// 第二引数: 署名に使用された公開鍵。 61// 自己署名証明書の場合、証明書自体が公開鍵情報を含むため、 62// 検証対象の証明書オブジェクト自体を渡すことができます。 63// これにより、証明書が自身の公開鍵で正しく署名されているかを確認します。 64echo "\nステップ4: openssl_x509_verify関数で証明書を検証します...\n"; 65$result = openssl_x509_verify($certificate, $certificate); 66 67// 5. 検証結果を評価し、表示します。 68switch ($result) { 69 case 1: 70 echo "✅ 検証成功: 証明書は正常に検証されました。\n"; 71 break; 72 case 0: 73 echo "❌ 検証失敗: 証明書の検証に失敗しました。無効な証明書か、改ざんされている可能性があります。\n"; 74 break; 75 case -1: 76 echo "⚠️ エラー: 検証中に問題が発生しました。詳細: " . openssl_error_string() . "\n"; 77 break; 78 default: 79 echo "不明な結果: " . $result . "\n"; 80} 81 82// 最後に、生成したOpenSSLリソースはスクリプト終了時に自動的に解放されます。 83 84?>
PHPのopenssl_x509_verify関数は、X.509形式のデジタル証明書が、指定された公開鍵によって正しく署名されているかを確認するために使用されます。これにより、証明書の信頼性や改ざんされていないかを検証できます。
この関数は二つの引数を取ります。第一引数には検証したいOpenSSLCertificateオブジェクトまたはPEM形式の証明書文字列を指定します。第二引数には、その証明書を署名するために使われたOpenSSLAsymmetricKeyオブジェクト、OpenSSLCertificateオブジェクト、またはPEM形式の公開鍵文字列を指定します。このサンプルコードでは、自己署名証明書を生成しており、その証明書が自身の公開鍵で正しく署名されているかを確認するため、第一引数と第二引数に同じ$certificateオブジェクトを渡しています。
戻り値は整数値です。1が返された場合は検証成功、0が返された場合は検証失敗、-1が返された場合は検証処理中にエラーが発生したことを意味します。
サンプルコードは、まず秘密鍵と証明書署名要求(CSR)を生成し、その情報を用いて有効期間365日の自己署名証明書を作成します。その後、作成された証明書が自身の公開鍵によって正しく署名されているか、つまり証明書自体が破損していないかなどをopenssl_x509_verify関数で検証し、その結果を表示しています。これは、ウェブサイトのSSL証明書が信頼できる認証局の公開鍵で署名されているかを検証する際など、より複雑なシナリオの基礎となる重要なプロセスです。
このサンプルは自己署名証明書の検証例ですが、本番環境では信頼できる認証局(CA)の公開鍵を用いて、ウェブサイトなどの証明書が正しく署名されているかを確認します。openssl_x509_verifyの第二引数には、検証対象の証明書を署名した公開鍵を指定してください。サンプルでは自己署名のため証明書自体を渡していますが、一般的な利用ではCAの公開鍵が必要です。関数の戻り値は1が成功、0が失敗、-1は処理中のエラーを意味します。エラー時にはopenssl_error_string()で原因を確認し、検証結果に基づいた適切なセキュリティ判断とエラーハンドリングが重要です。
X.509証明書の署名検証を行う
1<?php 2 3/** 4 * openssl_x509_verify 関数の使用例 5 * CA証明書とクライアント証明書を生成し、 6 * クライアント証明書がCAによって正しく署名されているかを検証します。 7 * 8 * openssl_sign は任意のデータの署名に使われるのに対し、 9 * openssl_x509_verify はX.509証明書の署名検証に使われます。 10 * この例では、証明書の署名検証プロセスを通じて、デジタル署名の概念を示します。 11 */ 12function demonstrateOpensslX509Verify(): void 13{ 14 echo "--- OpenSSL X.509 証明書検証のデモンストレーション ---\n\n"; 15 16 // 1. CA (Certificate Authority) の秘密鍵と公開鍵を生成 17 echo "1. CAの秘密鍵と公開鍵を生成中...\n"; 18 $caPrivateKey = openssl_pkey_new([ 19 'private_key_bits' => 2048, 20 'private_key_type' => OPENSSL_KEYTYPE_RSA, 21 ]); 22 if (!$caPrivateKey) { 23 echo "エラー: CA秘密鍵の生成に失敗しました。\n"; 24 return; 25 } 26 // CAの公開鍵をPEM形式で抽出 (証明書検証時に使用) 27 $caPublicKeyDetails = openssl_pkey_get_details($caPrivateKey); 28 $caPublicKeyPem = $caPublicKeyDetails['key']; 29 echo "CA秘密鍵と公開鍵が生成されました。\n\n"; 30 31 // 2. CAの自己署名証明書を生成 32 echo "2. CAの自己署名証明書を生成中...\n"; 33 $caCsr = openssl_csr_new([ 34 'countryName' => 'JP', 35 'stateOrProvinceName' => 'Tokyo', 36 'localityName' => 'Shinjuku', 37 'organizationName' => 'My CA Inc.', 38 'organizationalUnitName' => 'Certificate Authority', 39 'commonName' => 'My Root CA', 40 'emailAddress' => 'ca@example.com', 41 ], $caPrivateKey); 42 if (!$caCsr) { 43 echo "エラー: CA CSRの生成に失敗しました。\n"; 44 openssl_pkey_free($caPrivateKey); 45 return; 46 } 47 48 // CA自身でCSRに署名し、CA証明書を生成 49 $caCert = openssl_csr_sign($caCsr, null, $caPrivateKey, 365, ['digest_alg' => 'sha256']); 50 if (!$caCert) { 51 echo "エラー: CA証明書の生成に失敗しました。\n"; 52 openssl_pkey_free($caPrivateKey); 53 return; 54 } 55 // PEM形式でCA証明書を取得 56 openssl_x509_export($caCert, $caCertPem); 57 echo "CA自己署名証明書が生成されました。\n\n"; 58 59 // 3. クライアントの秘密鍵を生成 60 echo "3. クライアントの秘密鍵を生成中...\n"; 61 $clientPrivateKey = openssl_pkey_new([ 62 'private_key_bits' => 2048, 63 'private_key_type' => OPENSSL_KEYTYPE_RSA, 64 ]); 65 if (!$clientPrivateKey) { 66 echo "エラー: クライアント秘密鍵の生成に失敗しました。\n"; 67 openssl_pkey_free($caPrivateKey); 68 openssl_x509_free($caCert); 69 return; 70 } 71 echo "クライアント秘密鍵が生成されました。\n\n"; 72 73 // 4. クライアントのCSR (Certificate Signing Request) を生成 74 echo "4. クライアントのCSRを生成中...\n"; 75 $clientCsr = openssl_csr_new([ 76 'countryName' => 'JP', 77 'stateOrProvinceName' => 'Tokyo', 78 'localityName' => 'Shinjuku', 79 'organizationName' => 'My Client Co.', 80 'organizationalUnitName' => 'Web Team', 81 'commonName' => 'client.example.com', 82 'emailAddress' => 'client@example.com', 83 ], $clientPrivateKey); 84 if (!$clientCsr) { 85 echo "エラー: クライアント CSRの生成に失敗しました。\n"; 86 openssl_pkey_free($caPrivateKey); 87 openssl_x509_free($caCert); 88 openssl_pkey_free($clientPrivateKey); 89 return; 90 } 91 echo "クライアントCSRが生成されました。\n\n"; 92 93 // 5. CAの秘密鍵とCA証明書を使って、クライアントのCSRに署名し、クライアント証明書を生成 94 echo "5. CAでクライアント証明書に署名中...\n"; 95 $clientCert = openssl_csr_sign($clientCsr, $caCert, $caPrivateKey, 365, ['digest_alg' => 'sha256']); 96 if (!$clientCert) { 97 echo "エラー: クライアント証明書の署名に失敗しました。\n"; 98 openssl_pkey_free($caPrivateKey); 99 openssl_x509_free($caCert); 100 openssl_pkey_free($clientPrivateKey); 101 return; 102 } 103 // PEM形式でクライアント証明書を取得 104 openssl_x509_export($clientCert, $clientCertPem); 105 echo "クライアント証明書がCAによって署名され、生成されました。\n\n"; 106 107 // 6. openssl_x509_verify を使って、クライアント証明書がCAによって正しく署名されているか検証 108 echo "6. クライアント証明書の署名をCAの公開鍵で検証中...\n"; 109 // openssl_x509_verify の第2引数には、CAの公開鍵またはCA証明書を指定 110 // ここではCAの公開鍵(PEM形式文字列)を指定します。 111 $verificationResult = openssl_x509_verify($clientCertPem, $caPublicKeyPem); 112 113 echo "検証結果: "; 114 if ($verificationResult === 1) { 115 echo "成功!クライアント証明書はCAの公開鍵によって正しく署名されています。\n"; 116 } elseif ($verificationResult === 0) { 117 echo "失敗。クライアント証明書はCAの公開鍵によって署名されていません、または署名が無効です。\n"; 118 } else { // -1 はエラー発生 119 echo "エラーが発生しました。\n"; 120 while (($error = openssl_error_string()) !== false) { 121 echo "OpenSSLエラー: " . $error . "\n"; 122 } 123 } 124 125 // 生成した鍵と証明書のリソースを解放 126 openssl_pkey_free($caPrivateKey); 127 openssl_x509_free($caCert); 128 openssl_pkey_free($clientPrivateKey); 129 openssl_x509_free($clientCert); 130} 131 132// 関数を実行 133demonstrateOpensslX509Verify(); 134 135?>
openssl_x509_verify関数は、X.509証明書のデジタル署名を検証するために使用されます。これは、証明書が信頼できる認証局(CA)によって発行され、内容が改ざんされていないことを確認する重要なプロセスです。openssl_sign関数が任意のデータの署名に用いられるのに対し、openssl_x509_verifyは特に「証明書」の署名検証に特化しています。
第一引数には検証対象となる証明書(OpenSSLCertificateオブジェクトまたはPEM形式の文字列)を、第二引数にはその証明書に署名したCAの公開鍵またはCA証明書(OpenSSLAsymmetricKeyオブジェクト、OpenSSLCertificateオブジェクト、またはPEM形式の文字列)を指定します。
戻り値は整数値で、1は署名が有効であり検証に成功したことを示します。0は署名が無効または一致せず検証に失敗したことを、-1は検証処理中にエラーが発生したことを意味します。
サンプルコードでは、まずCAの秘密鍵と自己署名証明書を作成し、次にクライアントの秘密鍵と証明書署名要求(CSR)を生成します。その後、CAがこのCSRに署名してクライアント証明書を発行します。最後に、openssl_x509_verify関数を用いて、発行されたクライアント証明書が、事前に作成したCAの公開鍵によって正しく署名されているかを検証しています。この一連のプロセスにより、クライアント証明書の信頼性をプログラム的に確認することができます。
openssl_x509_verifyは、X.509証明書が信頼できる公開鍵(または別の証明書)によって正しく署名されているかを検証する専用の関数です。一般的なデータの署名検証に使うopenssl_verifyやデータの署名生成に使うopenssl_signとは目的が異なりますのでご注意ください。引数には検証したい証明書と、その署名を検証するための公開鍵(またはCA証明書)を、PEM形式の文字列またはOpenSSLのリソース型で指定できます。戻り値は「1」が検証成功、「0」が署名が無効、「-1」が関数実行中のエラーを意味します。エラー(-1)の場合は、必ずopenssl_error_string()で詳細な原因を確認してください。このサンプルコードはデモンストレーションであり、実際のシステムを構築する際は、秘密鍵の厳重な管理や、証明書チェーン全体の信頼性を検証するロジックを別途考慮し、本番環境のセキュリティ要件に合わせて設計する必要があります。