Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】openssl_cms_verify()関数の使い方

openssl_cms_verify関数の使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

openssl_cms_verify関数は、Cryptographic Message Syntax (CMS) 形式で署名されたデータの電子署名を検証する関数です。CMSは、電子署名や暗号化されたメッセージの構造を定義する国際的な標準規格です。この関数を利用すると、受け取ったデータが途中で改ざんされていないか(データの完全性)、そしてそのデータが本当に信頼できる署名者によって署名されたものか(署名者の真正性)を確認することができます。

具体的には、検証したいCMS署名データが格納されているファイルパスを指定します。さらに、署名を検証するために必要な証明書や、失効した証明書のリスト(CRL)が格納されたファイルパスをオプションで指定できます。検証の振る舞いを細かく制御するためのフラグも設定可能です。検証が成功した場合、この関数はブール値のtrueを返し、元の署名されたデータを取り出すこともできます。検証に失敗した場合はfalseを返します。

この関数は、ソフトウェアの配布におけるファイルの信頼性チェックや、セキュアな通信で送受信されるメッセージの真正性保証など、電子署名によってデータの信頼性をプログラムで確認する様々なシーンで重要な役割を果たします。システムエンジニアにとって、データのセキュリティと完全性を確保するための基本的なツールの一つと言えます。

構文(syntax)

1<?php
2
3openssl_cms_verify(
4    string $input_filename,
5    int $flags = 0,
6    ?string $ca_info = null,
7    array $untrusted_certificates = [],
8    ?string $certs_file = null,
9    ?string $output_filename = null
10): bool

引数(parameters)

string $input_filename, int $flags, ?string $certificates = null, array $ca_info = [], ?string $untrusted_certificates_filename = null, ?string $content = null, ?string $pk7 = null, ?string $sigfile = null, int $encoding = OPENSSL_CMS_BINARY

  • string $input_filename: 検証するCMS(Cryptographic Message Syntax)データのファイルパス
  • int $flags: 検証の動作を制御するフラグ
  • ?string $certificates: 検証に使用する署名者の証明書(PEM形式)または証明書チェーン(PEM形式)のパス
  • array $ca_info: CA(認証局)証明書のディレクトリパス、または個々のCA証明書(PEM形式)のパスの配列
  • ?string $untrusted_certificates_filename: untrusted証明書(信頼されていない証明書)のファイルパス
  • ?string $content: 検証するCMSデータのコンテンツ(バイナリデータ)
  • ?string $pk7: 検証するPKCS#7データ(バイナリデータ)
  • ?string $sigfile: 検証する署名ファイル(バイナリデータ)
  • int $encoding = OPENSSL_CMS_BINARY: 入力データのエンコーディングを指定するフラグ

戻り値(return)

bool

openssl_cms_verify関数は、CMSメッセージの検証が成功した場合はtrueを、失敗した場合はfalseを返します。

サンプルコード

PHP openssl_cms_verify でCMS署名を検証する

1<?php
2
3/**
4 * Demonstrates how to use openssl_cms_verify to verify a CMS signature.
5 *
6 * This function first generates a private key and a self-signed certificate.
7 * It then creates sample data, signs it using openssl_cms_sign (creating a CMS detached signature),
8 * and finally verifies the generated CMS signature using openssl_cms_verify.
9 *
10 * This example is self-contained and cleans up temporary files after execution.
11 *
12 * @return bool True if the verification is successful, false otherwise.
13 */
14function verifyCmsSignatureExample(): bool
15{
16    // --- 1. Define file paths for temporary assets ---
17    $privateKeyFile = 'temp_private_key.pem';
18    $certificateFile = 'temp_certificate.crt';
19    $dataFile = 'temp_data.txt';
20    $signedCmsFile = 'temp_signed.cms'; // This file will contain the CMS signature
21
22    // Ensure OpenSSL extension is enabled
23    if (!extension_loaded('openssl')) {
24        echo "Error: The OpenSSL extension is not enabled. Please enable it in your php.ini.\n";
25        return false;
26    }
27
28    // --- 2. Generate a private key and a self-signed certificate ---
29    echo "Generating private key and self-signed certificate...\n";
30    $privateKey = openssl_pkey_new([
31        'private_key_bits' => 2048,
32        'private_key_type' => OPENSSL_KEYTYPE_RSA,
33    ]);
34
35    if (!$privateKey) {
36        echo "Failed to generate private key: " . openssl_error_string() . "\n";
37        return false;
38    }
39
40    // Export private key to file
41    openssl_pkey_export($privateKey, $privateKeyContent);
42    file_put_contents($privateKeyFile, $privateKeyContent);
43
44    // Create a Certificate Signing Request (CSR)
45    $csr = openssl_csr_new([
46        'countryName' => 'US',
47        'stateOrProvinceName' => 'CA',
48        'localityName' => 'Anytown',
49        'organizationName' => 'Example Corp',
50        'commonName' => 'localhost',
51        'emailAddress' => 'admin@example.com',
52    ], $privateKey);
53
54    if (!$csr) {
55        echo "Failed to create CSR: " . openssl_error_string() . "\n";
56        return false;
57    }
58
59    // Self-sign the CSR to create a certificate
60    $certificate = openssl_csr_sign($csr, null, $privateKey, 365, ['digest_alg' => 'sha256']);
61
62    if (!$certificate) {
63        echo "Failed to self-sign certificate: " . openssl_error_string() . "\n";
64        return false;
65    }
66
67    // Export certificate to file
68    openssl_x509_export($certificate, $certificateContent);
69    file_put_contents($certificateFile, $certificateContent);
70    echo "Private key and certificate generated successfully.\n";
71
72    // --- 3. Create sample data to be signed ---
73    $sampleData = "This is a confidential message that needs a CMS signature.";
74    file_put_contents($dataFile, $sampleData);
75    echo "Sample data created: '{$dataFile}'\n";
76
77    // --- 4. Sign the data using openssl_cms_sign ---
78    // We create a detached signature, meaning the original data ($dataFile) is NOT embedded
79    // into the signature file ($signedCmsFile). This requires providing the original data
80    // again during verification.
81    echo "Signing data using openssl_cms_sign...\n";
82    $signResult = openssl_cms_sign(
83        $dataFile,                          // Input file containing the data to sign
84        $signedCmsFile,                     // Output file for the CMS signature
85        $certificateFile,                   // Signer's certificate
86        $privateKeyFile,                    // Signer's private key
87        null,                               // Extra headers (not used here)
88        OPENSSL_CMS_BINARY | OPENSSL_CMS_DETACHED // Flags: output binary format and detached signature
89    );
90
91    if (!$signResult) {
92        echo "Failed to sign data with openssl_cms_sign.\n";
93        while ($msg = openssl_error_string()) { echo "OpenSSL Error: " . $msg . "\n"; }
94        return false;
95    }
96    echo "Data signed successfully. CMS signature stored in: '{$signedCmsFile}'\n";
97
98    // --- 5. Verify the CMS signature using openssl_cms_verify ---
99    echo "Verifying CMS signature using openssl_cms_verify...\n";
100
101    // For verification, we need to provide:
102    // - The CMS signature file ($signedCmsFile) as input_filename.
103    // - The signer's certificate ($certificateFile) to retrieve the public key for verification.
104    // - CA certificates ($caInfo) to trust the signer's certificate. Since we used a self-signed
105    //   certificate, we trust itself by adding it to the CA info.
106    // - The original content file ($dataFile) because it was a detached signature.
107    $caInfo = [$certificateFile]; // Trust our self-signed certificate for verification
108
109    $verifyResult = openssl_cms_verify(
110        $signedCmsFile,           // input_filename: The CMS signature file
111        OPENSSL_CMS_BINARY,       // flags: Binary format as the signature was created in binary.
112        $certificateFile,         // certificates: File containing the signer's certificate
113        $caInfo,                  // ca_info: Array of CA certificate filenames for trusting the signer
114        null,                     // untrusted_certificates_filename: Not needed for this example
115        $dataFile,                // content: The original content file (crucial for detached signatures)
116        null,                     // pk7: Alternative to input_filename, not used
117        null,                     // sigfile: Alternative to input_filename, not used
118        OPENSSL_CMS_BINARY        // encoding: Encoding for the input file, consistent with flags
119    );
120
121    if ($verifyResult) {
122        echo "Verification successful! The CMS signature is VALID for the given data and certificate.\n";
123    } else {
124        echo "Verification FAILED! The CMS signature is NOT valid.\n";
125        while ($msg = openssl_error_string()) { echo "OpenSSL Error: " . $msg . "\n"; }
126    }
127
128    // --- 6. Clean up temporary files ---
129    echo "Cleaning up temporary files...\n";
130    @unlink($privateKeyFile);
131    @unlink($certificateFile);
132    @unlink($dataFile);
133    @unlink($signedCmsFile);
134
135    return (bool)$verifyResult;
136}
137
138// Execute the demonstration function
139verifyCmsSignatureExample();
140
141?>

PHPのopenssl_cms_verify関数は、デジタル署名技術の一つであるCMS(Cryptographic Message Syntax)形式の署名を検証するために使用されます。この関数を使うことで、特定のデータが正規の提供者によって署名され、かつ途中で改ざんされていないことを確認できます。

引数としては、検証したいCMS署名が含まれるファイルパスを$input_filenameで指定します。署名が分離署名形式(元のデータと署名が別々)である場合は、元のデータが格納されたファイルパスを$content引数で別途提供する必要があります。また、署名者の公開鍵が含まれる証明書のファイルパスを$certificatesで、その証明書を信頼するためのCA(認証局)証明書のファイルパス群を$ca_infoで指定します。これにより、署名者の身元と証明書の正当性を確認します。$flags$encodingは、署名ファイルの形式などを指定する際に用います。

この関数は、検証が成功した場合にはtrueを、失敗した場合にはfalseをブール値で返します。サンプルコードでは、まず秘密鍵と証明書を生成し、それらを用いてデータにCMS分離署名を作成します。その後、作成された署名ファイルと元のデータ、そして生成した証明書を元にopenssl_cms_verify関数で署名の検証を行い、その正当性を確認する一連の流れが示されています。

この関数は、CMS署名が本物で改ざんされていないかを確認するために使われます。サンプルコードでは分離署名(Detached Signature)を作成しており、検証時には署名ファイルだけでなく、署名前の元のデータファイル(content引数)を必ず指定する必要がある点に特に注意してください。OpenSSL拡張がPHPにロードされていることを確認してください。本番環境で利用する際は、サンプルで一時生成している自己署名証明書ではなく、適切に発行・管理された証明書と秘密鍵を使用し、信頼できるCA証明書をca_infoに指定することがセキュリティ上非常に重要です。署名時と検証時のflagsencodingの指定は一致させてください。エラーが発生した場合はopenssl_error_string()で詳細を確認できます。

PHP openssl_cms_verifyでCMS署名を検証する

1<?php
2
3/**
4 * openssl_cms_verify 関数のサンプルコード
5 *
6 * この関数は、CMS (Cryptographic Message Syntax) 形式で署名されたメッセージの署名を検証します。
7 * 主に、データが改ざんされていないこと、および信頼できるエンティティによって署名されたことを確認するために使用されます。
8 *
9 * システムエンジニアを目指す初心者の方へ:
10 * 実際の環境でこの関数を使用するには、事前に有効なファイルが必要です。
11 * 1. 署名されたCMSファイル(例: signed_data.cms)
12 * 2. 署名に使用されたエンティティの公開鍵証明書ファイル(例: signer.crt)
13 * 3. その証明書を発行したCA (認証局) の証明書ファイルまたはCA証明書が格納されたディレクトリ
14 *
15 * このサンプルコードは、これらのファイルが存在しない場合でも単体で実行できるように、
16 * ダミーのファイルパスを使用しています。そのため、実行結果は通常「検証失敗」となります。
17 * 関数の引数の使い方と、エラー発生時の一般的な挙動を理解することを目的としています。
18 * 実際の検証を行うには、コメントの指示に従って有効なファイルパスに置き換えてください。
19 */
20
21/**
22 * 指定されたCMS署名ファイルの検証を試みる関数
23 *
24 * @param string $inputFilename 検証対象のCMS署名ファイルへのパス。
25 * @param string $certificatesFilename 署名者の証明書ファイルへのパス。
26 * @param array $caInfo 信頼できるCA証明書ファイルへのパスの配列、またはCA証明書が格納されたディレクトリへのパス。
27 *                      例: ['/etc/ssl/certs', '/path/to/my_custom_ca.crt']
28 * @return bool 署名が正常に検証された場合は true、それ以外の場合は false。
29 */
30function verifyCmsSignature(string $inputFilename, string $certificatesFilename, array $caInfo = []): bool
31{
32    // openssl_cms_verify 関数の引数として使用する変数群を初期化します。
33
34    // 検証フラグ:
35    // OPENSSL_CMS_DETACHED: 署名されたメッセージのコンテンツが署名とは別に提供されることを示します。
36    //                       このフラグがない場合、コンテンツは署名ファイル内に埋め込まれていると仮定されます。
37    // OPENSSL_CMS_BINARY: バイナリモードで処理することを指定します。
38    $flags = OPENSSL_CMS_DETACHED | OPENSSL_CMS_BINARY;
39
40    // 検証成功時に抽出されたコンテンツが格納される変数 (参照渡しのため、事前に初期化が必要です)
41    $content = '';
42
43    // 検証成功時に抽出されたPKCS#7 (またはCMS) 構造が格納される変数 (参照渡しのため、事前に初期化が必要です)
44    $pk7 = '';
45
46    // 検証成功時に抽出された署名データが格納される変数 (参照渡しのため、事前に初期化が必要です)
47    $sigfile = '';
48
49    // 信頼できない証明書ファイルへのパス。この例では使用しないため null。
50    $untrustedCertificatesFilename = null;
51
52    echo "--- openssl_cms_verify 試行開始 ---\n";
53    echo "検証対象CMSファイル: {$inputFilename}\n";
54    echo "署名者証明書ファイル: {$certificatesFilename}\n";
55    echo "CA情報: " . (empty($caInfo) ? 'なし' : implode(', ', $caInfo)) . "\n";
56
57    // openssl_cms_verify 関数を呼び出して署名を検証します。
58    // 第1引数: 検証対象のCMS署名ファイルパス
59    // 第2引数: 検証フラグ
60    // 第3引数: 署名者の証明書ファイルパス
61    // 第4引数: 信頼できるCA証明書情報 (配列またはディレクトリパス)
62    // 第5引数: 信頼できない証明書ファイルパス
63    // 第6引数: 抽出されたコンテンツを格納する変数 (参照渡し)
64    // 第7引数: 抽出されたPKCS#7/CMSデータを格納する変数 (参照渡し)
65    // 第8引数: 抽出された署名データを格納する変数 (参照渡し)
66    $result = openssl_cms_verify(
67        $inputFilename,
68        $flags,
69        $certificatesFilename,
70        $caInfo,
71        $untrustedCertificatesFilename,
72        $content,
73        $pk7,
74        $sigfile
75    );
76
77    if ($result === true) {
78        echo "\nCMS署名の検証に成功しました!\n";
79        echo "抽出されたコンテンツの長さ: " . strlen($content) . " バイト\n";
80        // 実際のコンテンツを表示することも可能ですが、ここでは省略します。
81        // echo "コンテンツ:\n" . $content . "\n";
82    } else {
83        echo "\nCMS署名の検証に失敗しました。\n";
84        // openssl_error_string() は、OpenSSL関数の直近のエラーメッセージを取得します。
85        // エラーがない場合は false を返すため、不明なエラーとして処理します。
86        echo "エラー情報: " . (openssl_error_string() ?: "不明なエラー") . "\n";
87        echo "ヒント: ファイルパスが正しいか、ファイルが有効なCMS形式であるか、証明書が信頼されているかを確認してください。\n";
88    }
89
90    echo "--- openssl_cms_verify 試行終了 ---\n\n";
91
92    return $result;
93}
94
95// --- サンプル実行 ---
96
97// 注意: ここで指定されているファイルパスは、単体で動作させるためのダミーです。
98// 通常、これらのファイルは事前に作成されている必要があります。
99// 実際の検証を行うには、ご自身の環境に合わせて有効なファイルパスに置き換えてください。
100$dummyCmsFile = __DIR__ . '/dummy_signed_message.cms'; // 存在しないCMS署名ファイル
101$dummyCertFile = __DIR__ . '/dummy_signer.crt';         // 存在しない署名者証明書ファイル
102// ダミーCA情報の例(必要に応じて実際のパスを設定してください)
103$dummyCaInfo = []; // 例: ['/etc/ssl/certs', __DIR__ . '/my_ca.crt']
104
105// サンプル関数を呼び出してCMS署名の検証を試みます
106verifyCmsSignature($dummyCmsFile, $dummyCertFile, $dummyCaInfo);
107
108?>

PHPのopenssl_cms_verify関数は、CMS (Cryptographic Message Syntax) 形式で署名されたメッセージの署名を検証するために使用されます。これにより、データが途中で改ざんされていないことや、メッセージが信頼できるエンティティによって署名されたことを確認できます。

この関数は、検証対象のCMS署名ファイルパスを第一引数として受け取ります。第二引数には、OPENSSL_CMS_DETACHEDのような検証動作を制御するフラグを渡します。第三引数には署名者の証明書ファイルを、第四引数には信頼できる認証局(CA)の証明書情報(ファイルパスの配列やディレクトリパス)を指定します。さらに、検証成功時に抽出されたコンテンツやPKCS#7構造などを格納するための変数を参照渡しで指定する引数もあります。

検証が成功するとtrueを、失敗するとfalseを返します。検証失敗時には、openssl_error_string()関数を使って詳細なエラー情報を取得することができます。サンプルコードは、単体で動作を理解するためにダミーのファイルパスを使用しているため、通常は検証に失敗します。実際に署名を検証するには、有効なCMS署名ファイル、署名者の証明書、そして信頼できるCA証明書を事前に用意し、適切なファイルパスに置き換える必要があります。この関数は、データの完全性と信頼性を確保する上で重要な役割を果たします。

このサンプルコードは、ダミーのファイルパスを使用しているため、そのまま実行すると通常は検証失敗となります。実際に署名検証を成功させるには、有効なCMS署名ファイル、署名者の公開鍵証明書ファイル、信頼できるCA証明書ファイルまたはCA証明書が格納されたディレクトリを事前に用意し、それぞれのパスを正確に指定する必要があります。特に、$contentなどの参照渡しされる引数は、関数呼び出し前に変数を初期化しておくことが重要です。エラーが発生した場合は、openssl_error_string()関数で詳細なエラーメッセージを確認し、ファイルパスやファイルの内容、証明書の信頼性を確認してください。署名されたコンテンツが署名ファイルとは別に提供される場合は、OPENSSL_CMS_DETACHEDフラグを必ず使用してください。これらのファイルが正しく、かつ信頼できるものであることがセキュリティ上非常に重要です。

関連コンテンツ

関連IT用語

関連プログラミング言語