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

【PHP8.x】SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH定数の使い方

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

作成日: 更新日:

基本的な使い方

SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH定数は、PHPのSodium拡張機能において、秘密ストリーム暗号化で使用されるメッセージタグの一種を表す定数です。この定数は、XChaCha20-Poly1305アルゴリズムを用いたストリーム暗号化を行う際に、sodium_crypto_secretstream_xchacha20poly1305_push関数によって暗号化されるデータブロックに付与されるタグとして利用されます。具体的には、ストリーム内で送信される通常のメッセージブロックや、新しいメッセージの開始点としてこのタグが指定されます。

秘密ストリーム暗号化では、連続するデータを小さなブロックに分割し、それぞれを暗号化して送信します。この際、各ブロックにはタグが付けられ、受信側はそのタグを見てメッセージの種類やストリームの状態を判断します。TAG_PUSHは、ストリームの途中で送信される一般的なデータブロックを識別するためのものです。これにより、ストリームの終了を示すTAG_FINALや、鍵を更新するTAG_REKEYなど、特別な意味を持つ他のタグと明確に区別されます。このタグを適切に利用することで、アプリケーションは暗号化されたデータの流れを正確に制御し、データが改ざんされていないか、また正しい順序で受信されているかを保証できるようになります。システムエンジニアを目指す初心者の方々にとって、安全なデータ通信を実装する上で、このようなタグがメッセージの種類を識別し、セキュリティと信頼性を高める重要な要素であることを理解することが大切です。

構文(syntax)

1<?php
2var_dump(SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH);
3?>

引数(parameters)

引数なし

引数はありません

戻り値(return)

戻り値なし

戻り値はありません

サンプルコード

PHP Libsodium sodium_crypto_box で非対称暗号化する

1<?php
2
3/**
4 * Libsodiumのsodium_crypto_box関数を使用した非対称鍵暗号化のサンプル。
5 * システムエンジニアを目指す初心者向けに、鍵ペア生成からメッセージの暗号化、復号化までを実演します。
6 *
7 * 注: SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH は、
8 * ストリーム暗号化API (sodium_crypto_secretstream_*) で使用される定数であり、
9 * この sodium_crypto_box のサンプルとは直接関連しません。
10 * このコードはキーワード「sodium_crypto_box」に焦点を当てています。
11 */
12function runCryptoBoxExample(): void
13{
14    // 1. 鍵ペアの生成
15    // Alice (送信者) と Bob (受信者) それぞれの公開鍵と秘密鍵のペアを生成します。
16    $aliceKeyPair = sodium_crypto_box_keypair();
17    $alicePublicKey = sodium_crypto_box_publickey($aliceKeyPair);
18    $aliceSecretKey = sodium_crypto_box_secretkey($aliceKeyPair);
19
20    $bobKeyPair = sodium_crypto_box_keypair();
21    $bobPublicKey = sodium_crypto_box_publickey($bobKeyPair);
22    $bobSecretKey = sodium_crypto_box_secretkey($bobKeyPair);
23
24    echo "--- 鍵ペア生成 ---" . PHP_EOL;
25    echo "Alice 公開鍵 (Hex): " . bin2hex($alicePublicKey) . PHP_EOL;
26    echo "Bob 公開鍵 (Hex):   " . bin2hex($bobPublicKey) . PHP_EOL . PHP_EOL;
27
28    // 2. 暗号化するメッセージとナンス (Nonce) の準備
29    // ナンスは各暗号化操作でユニークである必要があります。
30    // 長さは SODIUM_CRYPTO_BOX_NONCEBYTES で定義されています。
31    $message = 'Hello, secure PHP world from Alice to Bob!';
32    $nonce = random_bytes(SODIUM_CRYPTO_BOX_NONCEBYTES);
33
34    echo "--- 暗号化 ---" . PHP_EOL;
35    echo "元のメッセージ: " . $message . PHP_EOL;
36    echo "使用したナンス (Hex): " . bin2hex($nonce) . PHP_EOL . PHP_EOL;
37
38    // AliceがBobへメッセージを暗号化
39    // Aliceの秘密鍵とBobの公開鍵を使用します。
40    $cipherText = sodium_crypto_box(
41        $message,
42        $nonce,
43        $bobPublicKey,    // 受信者(Bob)の公開鍵
44        $aliceSecretKey   // 送信者(Alice)の秘密鍵
45    );
46
47    echo "暗号化されたメッセージ (Ciphertext, Hex): " . bin2hex($cipherText) . PHP_EOL . PHP_EOL;
48
49    // 3. 復号化
50    // BobがAliceからのメッセージを復号化
51    // Bobの秘密鍵とAliceの公開鍵を使用します。
52    $decryptedMessage = sodium_crypto_box_open(
53        $cipherText,
54        $nonce,
55        $alicePublicKey,  // 送信者(Alice)の公開鍵
56        $bobSecretKey     // 受信者(Bob)の秘密鍵
57    );
58
59    echo "--- 復号化 ---" . PHP_EOL;
60
61    // 4. 結果の検証
62    if ($decryptedMessage !== false) {
63        echo "復号化されたメッセージ: " . $decryptedMessage . PHP_EOL;
64        if ($decryptedMessage === $message) {
65            echo "結果: ✅ メッセージは正常に暗号化・復号化されました!" . PHP_EOL;
66        } else {
67            echo "結果: ❌ 復号化されたメッセージが元のメッセージと異なります。" . PHP_EOL;
68        }
69    } else {
70        echo "結果: ❌ 復号化に失敗しました (認証エラーの可能性)。" . PHP_EOL;
71    }
72}
73
74// サンプルコードを実行
75runCryptoBoxExample();

このサンプルコードは、PHPのLibsodium拡張が提供するsodium_crypto_box関数を用いて、非対称鍵暗号化の基本的な仕組みを実演しています。非対称鍵暗号化では、メッセージの送信者と受信者がそれぞれ異なる鍵ペア(公開鍵と秘密鍵)を持ちます。まず、AliceとBobという二人のユーザーの鍵ペアを生成し、公開鍵は共有できますが、秘密鍵は各ユーザーが厳重に保持します。

メッセージを暗号化する際、sodium_crypto_box関数を使用します。この関数は、暗号化したいメッセージ、通信ごとに一意である必要があるナンス(Nonce)、メッセージを受信する相手の公開鍵、そしてメッセージを送信する自身の秘密鍵を引数として受け取ります。これにより、指定されたメッセージがセキュアな暗号文に変換され、戻り値として暗号化されたデータが返されます。

暗号化されたメッセージを復号化するには、sodium_crypto_box_open関数を利用します。この関数には、暗号文、暗号化時に使用したナンス、メッセージを送信した相手の公開鍵、そしてメッセージを受信する自身の秘密鍵を渡します。正しく復号できた場合は元のメッセージが戻り値として返され、鍵やナンスが一致しない、またはメッセージが改ざんされた場合は認証失敗としてfalseが返されます。このサンプルは、安全なデータ通信の基礎となる非対称鍵暗号の概念を具体的に理解するのに役立ちます。

このサンプルコードは、sodium_crypto_box関数による非対称鍵暗号化の基本を説明しています。特に重要なのはナンスの扱いで、各暗号化操作で必ず異なる、予測不能なユニークな値を使用してください。同じナンスの再利用はセキュリティ上の重大な脆弱性につながります。秘密鍵は外部に漏洩しないよう厳重に管理し、決して共有しないでください。公開鍵は安全に共有できます。また、sodium_crypto_box_open関数がfalseを返した場合は、メッセージが改ざんされたか、認証に失敗したことを意味しますので、内容を信用してはいけません。なお、リファレンスにあるSODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH定数は、本サンプルで扱っているsodium_crypto_boxとは異なる、ストリーム暗号化のAPIで利用される定数です。

PHP Libsodium: Secretstream暗号化デモ

1<?php
2
3/**
4 * SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH 定数を使用して、
5 * Libsodiumのストリーム暗号化(secretstream)をデモンストレーションする関数です。
6 * この定数は、ストリーム暗号化において、メッセージの通常のチャンクをマークするために使用されます。
7 */
8function demonstrateSecretStreamEncryption(): void
9{
10    // 1. ストリーム暗号化のためのキーを生成します。
11    // このキーは、暗号化と復号化の両方に使用されます。
12    $key = sodium_crypto_secretstream_xchacha20poly1305_keygen();
13
14    // 暗号化するメッセージです。大きなメッセージを想定して複数のチャンクに分割して扱います。
15    $message = "これは非常に機密性の高いメッセージで、複数の小さなチャンクに分割されて安全に送信されます。";
16    $message .= "PHP Libsodiumのストリーム暗号化機能を使用し、SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH タグを用いてデータを転送します。";
17    $message .= "これにより、大きなデータも効率的かつ安全に処理できます。";
18
19    echo "元のメッセージの長さ: " . strlen($message) . "バイト\n";
20    echo "元のメッセージ:\n" . $message . "\n\n";
21
22    $chunkSize = 64; // メッセージを分割するチャンクの最大サイズ
23    $encryptedChunks = []; // 暗号化されたチャンクを順に格納する配列
24
25    // 2. プッシュ操作 (暗号化) の状態を初期化し、ストリームヘッダを取得します。
26    // ヘッダは一度だけ生成され、復号化側に送信する必要があります。
27    list($pushState, $header) = sodium_crypto_secretstream_xchacha20poly1305_init_push($key);
28    $encryptedChunks[] = $header; // ヘッダを暗号化データコレクションの最初の要素として追加
29
30    // 3. メッセージをチャンクに分割し、SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH タグを付けて暗号化します。
31    for ($i = 0; $i < strlen($message); $i += $chunkSize) {
32        $chunk = substr($message, $i, $chunkSize);
33        $tag = SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH;
34
35        // 通常、最後のチャンクには SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL を使用してストリームの終了を示しますが、
36        // この例では SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH の使用法をデモンストレーションするため、
37        // 全てのチャンクに同じタグを使用します。
38        // if ($i + $chunkSize >= strlen($message)) {
39        //     $tag = SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL;
40        // }
41
42        $encryptedChunk = sodium_crypto_secretstream_xchacha20poly1305_push(
43            $pushState, // 現在のプッシュ状態
44            $chunk,     // 暗号化するメッセージチャンク
45            '',         // 関連データ (AD): この例ではなし
46            $tag        // チャンクに付与するタグ
47        );
48        $encryptedChunks[] = $encryptedChunk; // 暗号化されたチャンクを配列に追加
49    }
50
51    // 暗号化された全体のバイトシーケンス(ヘッダと全てのチャンクの合計)
52    $fullCiphertext = implode('', $encryptedChunks);
53    echo "暗号化されたメッセージの合計長さ: " . strlen($fullCiphertext) . "バイト\n\n";
54
55    // 4. プル操作 (復号化) の状態を初期化します。
56    // 受信したデータからヘッダを抽出し、それを使ってプル状態を初期化します。
57    $pullHeader = array_shift($encryptedChunks); // 配列から最初の要素(ヘッダ)を取り出す
58    list($pullState) = sodium_crypto_secretstream_xchacha20poly1305_init_pull($pullHeader, $key);
59
60    $decryptedMessage = ''; // 復号化されたメッセージを格納する変数
61
62    // 5. 暗号化されたチャンクを順に復号化します。
63    foreach ($encryptedChunks as $chunkToDecrypt) {
64        // sodium_crypto_secretstream_xchacha20poly1305_pull は、復号化された平文チャンクと、元のタグを返します。
65        list($decryptedChunk, $returnedTag) = sodium_crypto_secretstream_xchacha20poly1305_pull($pullState, $chunkToDecrypt);
66        $decryptedMessage .= $decryptedChunk; // 復号化されたチャンクを結合
67        // 復号化されたチャンクのタグが期待通りか確認することもできます。
68        // echo "復号化されたチャンクのタグ: " . $returnedTag . " (期待値: " . SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH . ")\n";
69    }
70
71    echo "復号化されたメッセージの長さ: " . strlen($decryptedMessage) . "バイト\n";
72    echo "復号化されたメッセージ:\n" . $decryptedMessage . "\n\n";
73
74    // 6. 元のメッセージと復号化されたメッセージが一致するか検証します。
75    if ($message === $decryptedMessage) {
76        echo "✅ メッセージは正しく暗号化され、復号化されました。\n";
77    } else {
78        echo "❌ エラー: メッセージの復号化に失敗しました。\n";
79    }
80}
81
82// 関数の実行
83demonstrateSecretStreamEncryption();

PHP 8で提供されるSODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSHは、Libsodiumライブラリのストリーム暗号化機能で使用される定数です。この定数自体に引数や戻り値はありませんが、ストリーム暗号化において、メッセージの通常のデータブロック(チャンク)であることを示すタグとして利用されます。

サンプルコードでは、この定数を用いてストリーム暗号化の基本的な流れを説明しています。まず、暗号化と復号化に共通のキーを生成し、次に長いメッセージを複数の小さなチャンクに分割します。暗号化処理では、sodium_crypto_secretstream_xchacha20poly1305_init_push関数で初期状態とヘッダを生成した後、各メッセージチャンクをsodium_crypto_secretstream_xchacha20poly1305_push関数で暗号化します。この際、SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSHをタグとして指定することで、そのチャンクがストリームの中間にある一般的なメッセージであることを示します。

復号化の際には、最初に受信したヘッダとキーを使ってsodium_crypto_secretstream_xchacha20poly1305_init_pull関数で状態を初期化します。その後、sodium_crypto_secretstream_xchacha20poly1305_pull関数を用いて暗号化された各チャンクを順に復号化し、元のメッセージを再構築します。この定数を用いることで、大きなデータを効率的かつ安全にストリーム形式で処理し、通信の途中にデータを挿入するなどの操作が可能になります。

このサンプルコードは、PHPのLibsodiumを用いたストリーム暗号化でTAG_PUSH定数を使う方法を示します。重要な点として、暗号化キーは非常に機密性が高いため、厳重に管理し漏洩させないでください。また、sodium_crypto_secretstream_xchacha20poly1305_init_pushで生成されるストリームヘッダは、復号化のために必ず相手側に安全に伝える必要があります。TAG_PUSHは通常のメッセージチャンクに使われますが、ストリームの最後のチャンクにはSODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINALを使うのが一般的です。関連データ(AD)はオプションですが、認証したい情報を追加でき、改ざん検知に役立ちます。これらの点を理解し、データの機密性と完全性を保つために正しく活用してください。

関連コンテンツ

関連IT用語

関連プログラミング言語