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

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

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

作成日: 更新日:

基本的な使い方

SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_MESSAGE定数は、PHPのlibsodium拡張機能が提供するセキュアなストリーム暗号化において、暗号化されるデータの種類を示すタグを表す定数です。この定数は、XChaCha20-Poly1305アルゴリズムを用いたストリーム暗号化(メッセージを連続して送信する方式)で使用され、送信されるメッセージブロックが「通常のデータ」であることを識別するために利用されます。

ストリーム暗号化では、単にデータを暗号化するだけでなく、メッセージの区切りや、鍵の更新、ストリームの終了といった特別なイベントを管理する必要があります。そのため、暗号化される各メッセージには「タグ」と呼ばれる情報が付与されます。SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_MESSAGEは、その中でも最も一般的なタグであり、特別な処理を必要としない、連続するデータの一部として扱われるメッセージに指定されます。

開発者がsodium_crypto_secretstream_xchacha20poly1305_push関数などを使用してデータを暗号化し送信する際、この定数をタグとして渡すことで、そのデータが通常の情報伝達を目的としたメッセージブロックであることを明示します。受信側は、復号時にこのタグを確認することで、受け取ったデータが単なるメッセージなのか、あるいはストリームの鍵を更新する合図(TAG_REKEY)や、ストリームが終了したことを示す合図(TAG_FINAL)なのかを正確に判断できます。これにより、データの整合性とセキュリティを保ちながら、複雑なセキュア通信プロトコルをシンプルに実装することが可能になります。

構文(syntax)

1<?php
2$tag = SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_MESSAGE;
3?>

引数(parameters)

引数なし

引数はありません

戻り値(return)

戻り値なし

戻り値はありません

サンプルコード

PHP sodium_crypto_secretboxでメッセージを暗号化・復号化する

1<?php
2
3/**
4 * Libsodiumライブラリのsodium_crypto_secretbox関数を使用して、
5 * メッセージの暗号化と復号化を行う例です。
6 *
7 * SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_MESSAGE は
8 * SecretStream APIでメッセージチャンクを識別するための定数ですが、
9 * sodium_crypto_secretbox は単一のメッセージを安全に暗号化する機能を提供します。
10 * このサンプルでは、「メッセージ」を安全に扱うという共通の概念に焦点を当てます。
11 *
12 * @param string $plainText 暗号化する平文のメッセージ。
13 * @return void
14 */
15function handleSecretMessage(string $plainText): void
16{
17    // Libsodiumが利用可能か確認
18    if (!extension_loaded('sodium')) {
19        echo "Error: The Sodium extension is not loaded." . PHP_EOL;
20        return;
21    }
22
23    // 1. 秘密鍵を生成
24    // sodium_crypto_secretbox_keygen() は、暗号化と復号化の両方に使用する秘密鍵を生成します。
25    // SODIUM_CRYPTO_SECRETBOX_KEYBYTES は鍵の推奨される長さを定義する定数です。
26    $key = sodium_crypto_secretbox_keygen();
27    echo "生成された秘密鍵 (Base64エンコード): " . base64_encode($key) . PHP_EOL;
28
29    // 2. ノンス(Nonce: Number used once)を生成
30    // ノンスは、同じ鍵で複数のメッセージを暗号化する場合に、メッセージごとに必ず異なる値である必要があります。
31    // SODIUM_CRYPTO_SECRETBOX_NONCEBYTES はノンスの推奨される長さを定義する定数です。
32    $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
33    echo "生成されたノンス (Base64エンコード): " . base64_encode($nonce) . PHP_EOL;
34
35    echo "---" . PHP_EOL;
36    echo "元のメッセージ: " . $plainText . PHP_EOL;
37    echo "---" . PHP_EOL;
38
39    // 3. メッセージを暗号化
40    // sodium_crypto_secretbox() は、平文、ノンス、秘密鍵を引数に取り、
41    // 暗号化されたデータ(認証タグを含む)を返します。
42    $cipherText = sodium_crypto_secretbox($plainText, $nonce, $key);
43    echo "暗号化されたメッセージ (Base64エンコード): " . base64_encode($cipherText) . PHP_EOL;
44    echo "---" . PHP_EOL;
45
46    // 4. 暗号化されたメッセージを復号化
47    // sodium_crypto_secretbox_open() は、暗号文、ノンス、秘密鍵を引数に取り、
48    // 復号化された平文を返します。
49    // メッセージが改ざんされた場合や、鍵・ノンスが正しくない場合は false を返します。
50    $decryptedText = sodium_crypto_secretbox_open($cipherText, $nonce, $key);
51
52    if ($decryptedText === false) {
53        echo "エラー: メッセージの復号化に失敗しました。データが改ざんされたか、鍵またはノンスが誤っています。" . PHP_EOL;
54    } else {
55        echo "復号化されたメッセージ: " . $decryptedText . PHP_EOL;
56    }
57}
58
59// サンプルメッセージで関数を実行
60handleSecretMessage("これはPHPのsodium_crypto_secretboxを使って暗号化・復号化される秘密のメッセージです。");
61

このサンプルコードは、PHPのLibSodium拡張機能を使用し、sodium_crypto_secretbox関数によるメッセージの安全な暗号化と復号化の方法を示しています。LibSodiumは、強力な暗号化機能を提供するライブラリです。本来SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_MESSAGE定数はSecretStream APIにおけるメッセージの種別を識別するためのものですが、本サンプルでは「メッセージの安全な扱い」という共通の概念に注目し、単一のメッセージ暗号化に特化したsodium_crypto_secretboxを利用しています。

まず、sodium_crypto_secretbox_keygen()で暗号化と復号化に共通の秘密鍵を生成します。次に、random_bytes()SODIUM_CRYPTO_SECRETBOX_NONCEBYTES定数を用いて、各メッセージに一意である必要があるノンス(Number used once)を生成します。

メッセージの暗号化にはsodium_crypto_secretbox()関数を使用します。この関数は、平文のメッセージ、生成したノンス、秘密鍵を引数として受け取り、認証タグを含む暗号文を返します。この暗号文は、ノンスと秘密鍵がなければ復号化できません。

復号化はsodium_crypto_secretbox_open()関数で行います。暗号文、暗号化時に使用したノンス、秘密鍵を引数として渡し、成功すれば元の平文が戻り値として得られます。もしデータが改ざんされていたり、鍵やノンスが正しくない場合は、falseが返され、セキュリティ上の問題が検出されたことを示します。これにより、安全にデータを送受信するための基本的な仕組みを理解できます。

sodium_crypto_secretboxを利用する際は、秘密鍵とノンスの扱いに特に注意が必要です。生成した秘密鍵は絶対に外部に漏らさず、厳重に管理してください。ノンスは、同じ秘密鍵で複数のメッセージを暗号化するたびに、必ず異なる値を生成し使用する必要があります。同じノンスを繰り返し使うと、セキュリティ上の深刻な脆弱性が発生する原因となります。また、復号化関数sodium_crypto_secretbox_openfalseを返した場合、データが改ざんされたか、鍵またはノンスが誤っていることを意味しますので、必ず適切にエラーを処理するようにしてください。PHPのSodium拡張機能がサーバーにインストールされていることも事前に確認が必要です。

sodium_crypto_boxでメッセージを暗号化・復号する

1<?php
2
3/**
4 * Libsodiumのcrypto_box関数を使用してメッセージを安全に暗号化および復号するサンプル。
5 *
6 * この関数は、PHPのSodium拡張が有効になっていることを前提としています。
7 * `sodium_crypto_box`は、公開鍵暗号の原則に基づき、送信者の秘密鍵と受信者の公開鍵を用いて
8 * メッセージを暗号化し、機密性、完全性、送信者の認証を保証します。
9 *
10 * @param string $plainMessage 暗号化する平文メッセージ。
11 * @return void
12 */
13function demonstrateAuthenticatedEncryption(string $plainMessage): void
14{
15    echo "元のメッセージ: " . $plainMessage . "\n\n";
16
17    // 1. 送信者 (Alice) と受信者 (Bob) の鍵ペアを生成します。
18    // 鍵ペアには公開鍵と秘密鍵が含まれ、秘密鍵は決して共有してはいけません。
19    $aliceKeyPair = sodium_crypto_box_keypair();
20    $alicePublicKey = sodium_crypto_box_publickey($aliceKeyPair);
21    $aliceSecretKey = sodium_crypto_box_secretkey($aliceKeyPair);
22
23    $bobKeyPair = sodium_crypto_box_keypair();
24    $bobPublicKey = sodium_crypto_box_publickey($bobKeyPair);
25    $bobSecretKey = sodium_crypto_box_secretkey($bobKeyPair);
26
27    echo "--- 鍵ペア生成 ---\n";
28    echo "Aliceの公開鍵 (HEX): " . bin2hex($alicePublicKey) . "\n";
29    echo "Bobの公開鍵 (HEX):   " . bin2hex($bobPublicKey) . "\n\n";
30
31    // 2. ノンス (Nonce) を生成します。
32    // ノンスは "Number once" の略で、同じ鍵ペアで複数のメッセージを暗号化する際に、
33    // 各暗号化操作で一度だけ使用される予測不可能なランダムな値です。
34    // これにより、リプレイ攻撃などを防ぎます。
35    $nonce = random_bytes(SODIUM_CRYPTO_BOX_NONCEBYTES);
36    echo "生成されたノンス (HEX): " . bin2hex($nonce) . "\n\n";
37
38    // 3. AliceがBob宛てにメッセージを暗号化します。
39    // Aliceは自身の秘密鍵 ($aliceSecretKey) とBobの公開鍵 ($bobPublicKey) を使用します。
40    $encryptedMessage = sodium_crypto_box(
41        $plainMessage,
42        $nonce,
43        $bobPublicKey, // 受信者の公開鍵
44        $aliceSecretKey // 送信者の秘密鍵
45    );
46
47    echo "--- 暗号化 ---\n";
48    echo "暗号化されたメッセージ (HEX): " . bin2hex($encryptedMessage) . "\n\n";
49
50    // 4. BobがAliceからのメッセージを復号します。
51    // Bobは自身の秘密鍵 ($bobSecretKey) とAliceの公開鍵 ($alicePublicKey) を使用します。
52    // 暗号化時と同じノンス ($nonce) が必要です。
53    $decryptedMessage = sodium_crypto_box_open(
54        $encryptedMessage,
55        $nonce,
56        $alicePublicKey, // 送信者の公開鍵
57        $bobSecretKey // 受信者の秘密鍵
58    );
59
60    echo "--- 復号 ---\n";
61    if ($decryptedMessage === false) {
62        echo "メッセージの復号に失敗しました。不正なメッセージ、鍵、またはノンスの誤りが考えられます。\n";
63    } else {
64        echo "復号されたメッセージ: " . $decryptedMessage . "\n\n";
65
66        // 復号されたメッセージが元のメッセージと一致するか検証します。
67        if ($decryptedMessage === $plainMessage) {
68            echo "検証結果: 成功 - 復号されたメッセージは元のメッセージと一致します。\n";
69        } else {
70            echo "検証結果: 失敗 - 復号されたメッセージは元のメッセージと一致しません。\n";
71        }
72    }
73}
74
75// サンプル関数の実行
76demonstrateAuthenticatedEncryption("ハロー、Bob!これはAliceからの秘密のメッセージです。");

このサンプルコードは、PHPのSodium拡張を利用し、sodium_crypto_box関数を用いた認証付き暗号化と復号のプロセスを示しています。これは、公開鍵暗号の原則に基づき、送信者の秘密鍵と受信者の公開鍵を組み合わせてメッセージを安全にやり取りする方法です。

具体的には、まず送信者(Alice)と受信者(Bob)それぞれの鍵ペア(公開鍵と秘密鍵)を生成します。次に、暗号化ごとに一度だけ使用されるランダムな値であるノンスを生成します。

メッセージを暗号化する際、送信者は自身の秘密鍵と受信者の公開鍵、そしてノンスを使ってsodium_crypto_box関数を呼び出します。この関数は引数として、暗号化したい平文メッセージ、生成したノンス、受信者の公開鍵、送信者の秘密鍵を受け取り、暗号化されたメッセージを返します。

復号する際には、受信者は自身の秘密鍵と送信者の公開鍵、暗号化されたメッセージ、そして同じノンスを使ってsodium_crypto_box_open関数を呼び出します。この関数は、復号に成功すれば元の平文メッセージを返し、失敗した場合はfalseを返します。復号が成功すれば、メッセージの機密性、完全性、そして送信者の認証が保証されたことになります。この一連の処理により、データが不正に改ざんされたり、第三者に内容を知られたりすることを防ぎます。

このサンプルコードはLibSodium拡張による公開鍵暗号化の基本を示します。まず、PHPでSodium拡張が有効であることを確認してください。秘密鍵は決して共有せず、厳重に管理することが重要です。ノンスは各暗号化で異なる予測不可能な値を一度だけ使用し、再利用は重大なセキュリティリスクとなり、絶対に避けてください。sodium_crypto_box_openfalseを返す場合は復号失敗なので、必ずエラー処理を実装すべきです。実際の利用では、鍵ペアは一度生成し、安全に永続化して利用します。

関連コンテンツ

関連プログラミング言語