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

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

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

作成日: 更新日:

基本的な使い方

sodium_crypto_secretstream_xchacha20poly1305_init_pull関数は、暗号化されたデータのストリームを受信し、それを復号するための準備(初期化)を実行する関数です。この関数は、ファイルや一連のメッセージのような大きなデータや連続したデータを安全に送受信するための「シークレットストリーム」という仕組みの一部であり、データを受け取る側(復号側)で最初に一度だけ呼び出されます。具体的には、送信側で暗号化を開始した際に生成されたストリームのヘッダー情報と、送信側と受信側であらかじめ共有している秘密鍵の2つを引数として受け取ります。関数内部では、これらの情報をもとに、後続の復号処理で必要となる内部的な状態(state)を生成し、それを戻り値として返します。この返された状態は、それ自体が復号されたデータではなく、暗号化されたメッセージの断片を一つずつ復号していくための重要な情報です。この関数で初期化を行った後、sodium_crypto_secretstream_xchacha20poly1305_pull関数にこの状態と暗号化されたメッセージを渡すことで、元のデータを安全に復元することができます。

構文(syntax)

1<?php
2
3// ストリーム暗号化に使用する秘密鍵を生成します。
4// 鍵の長さは SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES である必要があります。
5$key = random_bytes(SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES);
6
7// ここでは、init_pull 関数で使用するために必要なヘッダーを生成しています。
8// 実際のアプリケーションでは、このヘッダーは暗号化されたデータと一緒に送信側から受け取ります。
9list($state_push, $header) = sodium_crypto_secretstream_xchacha20poly1305_init_push($key);
10
11// 受信側でストリームの復号化を開始するために初期化を行います。
12// 秘密鍵と、送信側から受け取ったヘッダーを渡します。
13// 戻り値は、ストリームの状態を保持する配列と、復号化されたヘッダーです。
14list($state_pull, $decrypted_header) = sodium_crypto_secretstream_xchacha20poly1305_init_pull($key, $header);
15
16// $state_pull は、以降のストリーム復号化操作(sodium_crypto_secretstream_xchacha20poly1305_pull)で使用されます。
17// $decrypted_header は、通常、元の $header と同じ内容です。
18?>

引数(parameters)

string $header, string $key

  • string $header: 復号化に使用するセッションヘッダーを指定する文字列
  • string $key: 復号化に使用する共有秘密鍵を指定する文字列

戻り値(return)

array

sodium_crypto_secretstream_xchacha20poly1305_init_pull関数は、認証付き複合処理の初期化に必要な状態情報を含む配列を返します。この配列には、複合処理で使用するキーと、一意のパディング情報が含まれます。

サンプルコード

PHP libsodium SecretStream 暗号化/復号化する

1<?php
2
3// ソディウム拡張がロードされているか確認
4if (!extension_loaded('sodium')) {
5    die('エラー: sodium 拡張がロードされていません。php.ini で有効にしてください。');
6}
7
8/**
9 * libsodium の SecretStream 機能を使用してデータの暗号化と復号化を行うサンプル。
10 *
11 * この関数は、sodium_crypto_secretstream_xchacha20poly1305_init_pull の使用方法を
12 * 示すために、まずデータを SecretStream で暗号化し、その後に復号化します。
13 */
14function demonstrateSecretStreamEncryption(): void
15{
16    echo "--- libsodium SecretStream 暗号化/復号化 デモンストレーション ---\n\n";
17
18    // 1. SecretStream 用の共有鍵を生成します。
19    // この鍵は暗号化と復号化の両方に使用されます。
20    $key = random_bytes(SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES);
21    echo "1. 共有鍵を生成しました。\n";
22
23    // 2. SecretStream のプッシュ (暗号化) を初期化します。
24    // sodium_crypto_secretstream_xchacha20poly1305_init_push は、
25    // [ヘッダー, 暗号化状態] の配列を返します。
26    [$header, $statePush] = sodium_crypto_secretstream_xchacha20poly1305_init_push($key);
27    echo "2. SecretStream プッシュを初期化し、ヘッダーを生成しました。\n";
28    echo "   ヘッダー (" . SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES . " バイト): " . bin2hex($header) . "\n\n";
29
30    // 3. 暗号化する複数のメッセージを準備します。
31    $originalMessages = [
32        "こんにちは、シークレットストリームの世界へようこそ!",
33        "これは、メッセージの2番目の部分です。",
34        "そして、これがシークレットストリームの最後の部分です。",
35    ];
36
37    echo "3. 以下のメッセージを暗号化します:\n";
38    foreach ($originalMessages as $index => $msg) {
39        echo "   メッセージ" . ($index + 1) . ": '$msg'\n";
40    }
41    echo "\n";
42
43    // 4. メッセージを SecretStream にプッシュ (暗号化) します。
44    // sodium_crypto_secretstream_xchacha20poly1305_push は、
45    // 暗号化されたデータと更新された暗号化状態を返します。
46    // 最後のメッセージには SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL を使用します。
47    $cipherTexts = [];
48    foreach ($originalMessages as $index => $message) {
49        $tag = ($index === count($originalMessages) - 1)
50            ? SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL // 最後のメッセージ
51            : SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_MESSAGE; // 通常のメッセージ
52
53        $cipherTexts[] = sodium_crypto_secretstream_xchacha20poly1305_push(
54            $statePush,
55            $message,
56            '', // 関連データは今回はなし
57            $tag
58        );
59        echo "4" . chr(ord('a') + $index) . ". メッセージ" . ($index + 1) . "を暗号化しました (タグ: $tag)。\n";
60    }
61    echo "\n   合計 " . count($cipherTexts) . " 個の暗号文が生成されました。\n\n";
62
63    // --- ここから復号化処理 (sodium_crypto_secretstream_xchacha20poly1305_init_pull の使用) ---
64
65    echo "--- 復号化処理を開始します ---\n\n";
66
67    // 5. SecretStream のプル (復号化) を初期化します。
68    // sodium_crypto_secretstream_xchacha20poly1305_init_pull は、
69    // 最初に生成されたヘッダーと共有鍵を使用して、復号化状態を初期化します。
70    // 復号化状態 (state) を返します。
71    $statePull = sodium_crypto_secretstream_xchacha20poly1305_init_pull($header, $key);
72    echo "5. SecretStream プルを初期化しました (ヘッダーと鍵を使用)。\n\n";
73
74    // 6. 暗号化されたメッセージを SecretStream からプル (復号化) します。
75    // sodium_crypto_secretstream_xchacha20poly1305_pull は、
76    // [復号化された平文, メッセージタグ] の配列を返します。
77    echo "6. 暗号化されたデータを復号化します:\n";
78    $decryptedMessages = [];
79    foreach ($cipherTexts as $index => $cipherText) {
80        try {
81            [$decryptedMessage, $tag] = sodium_crypto_secretstream_xchacha20poly1305_pull(
82                $statePull,
83                $cipherText,
84                '' // 関連データは今回はなし
85            );
86            $decryptedMessages[] = $decryptedMessage;
87            echo "   復号化されたメッセージ" . ($index + 1) . ": '$decryptedMessage' (タグ: $tag)\n";
88        } catch (SodiumException $e) {
89            echo "   復号化エラーが発生しました: " . $e->getMessage() . "\n";
90            return; // エラーが発生した場合は処理を中断
91        }
92    }
93    echo "\n";
94
95    // 7. 復号化されたデータが元のデータと一致するか検証します。
96    echo "7. 復号化されたデータが元のデータと一致するか検証します:\n";
97    $allMatched = true;
98    for ($i = 0; $i < count($originalMessages); $i++) {
99        if ($originalMessages[$i] === $decryptedMessages[$i]) {
100            echo "   メッセージ" . ($i + 1) . ": OK (元のメッセージと一致)\n";
101        } else {
102            echo "   メッセージ" . ($i + 1) . ": NG (不一致) - 元: '{$originalMessages[$i]}', 復号化: '{$decryptedMessages[$i]}'\n";
103            $allMatched = false;
104        }
105    }
106
107    if ($allMatched) {
108        echo "\nすべてのメッセージが正常に暗号化および復号化されました!\n";
109    } else {
110        echo "\nエラー: 一部のメッセージが一致しませんでした。\n";
111    }
112
113    echo "\n--- デモンストレーション終了 ---\n";
114}
115
116// サンプルコードを実行します
117demonstrateSecretStreamEncryption();

sodium_crypto_secretstream_xchacha20poly1305_init_pull関数は、PHPのlibsodium拡張が提供する「SecretStream」という機能において、暗号化された複数のメッセージを順次復号化する処理を開始するために使用されます。この機能は、データのストリームを安全に送受信する際に利用され、メッセージの整合性と機密性を保ちます。

この関数は、SecretStreamでデータを暗号化した際に生成された特別な「ヘッダー」と、暗号化と復号化で共通して使用する「秘密鍵」を引数として受け取ります。第一引数 $header には、暗号化の初期化を行う sodium_crypto_secretstream_xchacha20poly1305_init_push 関数が返したヘッダー文字列を指定します。第二引数 $key には、事前に安全に共有されている秘密鍵文字列を渡します。

sodium_crypto_secretstream_xchacha20poly1305_init_pull関数は、これらの引数に基づいて復号処理に必要な内部状態を初期化し、配列として返します。この戻り値である「復号状態」は、その後、各暗号文を実際の平文に復元する sodium_crypto_secretstream_xchacha20poly1305_pull 関数に渡して使用されます。これにより、一連の暗号化されたメッセージを正確かつ安全に復号することが可能になります。

この関数を使用するには、まずPHPのsodium拡張を有効にしてください。復号化に必須となるヘッダーと鍵は、暗号化時に生成されたものであり、これらを安全に管理し、復号化処理の際に正しく渡す必要があります。特に鍵は機密情報のため厳重な取り扱いが求められます。また、この関数は連続したデータの復号化を開始するためのもので、暗号化側のsodium_crypto_secretstream_xchacha20poly1305_init_pushで生成されたヘッダーと対になります。復号化の途中で問題が発生した場合に備え、SodiumExceptionによるエラーハンドリングを行うことが重要です。認証済み追加データ(AD)も利用可能です。

sodium_crypto_secretstream_xchacha20poly1305_init_pull でストリーム復号を初期化する

1<?php
2
3/**
4 * Demonstrates the usage of sodium_crypto_secretstream_xchacha20poly1305_init_pull.
5 *
6 * This function simulates a scenario where a sender encrypts multiple messages
7 * into a secret stream using a shared secret key, and a receiver then decrypts
8 * these messages from the stream using the same key and the stream header.
9 * It showcases the full lifecycle of stream encryption and decryption using Sodium.
10 *
11 * The underlying cryptographic primitive is a symmetric authenticated encryption
12 * scheme, similar in principle to `sodium_crypto_secretbox` but optimized
13 * for continuous data streams rather than individual messages.
14 */
15function demonstrateSecretStreamDecryption(): void
16{
17    // 1. Generate a 32-byte secret key for the stream.
18    // This key must be securely shared between the sender and receiver.
19    $sharedSecretKey = sodium_crypto_secretstream_xchacha20poly1305_keygen();
20    echo "Generated Shared Secret Key (Hex): " . bin2hex($sharedSecretKey) . PHP_EOL . PHP_EOL;
21
22    // --- Sender Side: Encrypting the Stream ---
23    echo "--- Sender Side: Encrypting Data Stream ---" . PHP_EOL;
24
25    // Initialize the push stream. This function returns an array containing:
26    // [0] => The stream header (a string, essential for the receiver to decrypt).
27    // [1] => The internal state handle for the push operation.
28    $pushInitialization = sodium_crypto_secretstream_xchacha20poly1305_init_push($sharedSecretKey);
29    $streamHeader = $pushInitialization[0];
30    $senderStateHandle = $pushInitialization[1];
31
32    echo "Stream Header generated (to be securely sent to receiver): " . bin2hex($streamHeader) . PHP_EOL;
33
34    $originalMessages = [
35        "This is the first part of the secret stream data.",
36        "The second part contains more confidential information.",
37        "And this is the final message, completing the stream."
38    ];
39
40    $encryptedStreamParts = [];
41    foreach ($originalMessages as $index => $message) {
42        // Determine the tag for the message.
43        // SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL marks the last message.
44        $tag = ($index === count($originalMessages) - 1)
45            ? SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL
46            : SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_MESSAGE;
47
48        // Encrypt the message part using the sender's state handle.
49        $encryptedPart = sodium_crypto_secretstream_xchacha20poly1305_push(
50            $senderStateHandle,
51            $message,
52            '', // No additional authenticated data for this example
53            $tag
54        );
55        $encryptedStreamParts[] = $encryptedPart;
56        echo "Sender encrypted message " . ($index + 1) . " (Tag: " . $tag . ") into: " . bin2hex($encryptedPart) . PHP_EOL;
57    }
58    echo PHP_EOL;
59
60    // --- Receiver Side: Decrypting the Stream ---
61    echo "--- Receiver Side: Decrypting Data Stream ---" . PHP_EOL;
62
63    // Initialize the pull stream using the received header and the shared secret key.
64    // This is the core function demonstrated here: sodium_crypto_secretstream_xchacha20poly1305_init_pull.
65    // It returns an array:
66    // [0] => The internal state handle for the pull operation.
67    // [1] => A copy of the header that was passed in.
68    try {
69        $pullInitialization = sodium_crypto_secretstream_xchacha20poly1305_init_pull($streamHeader, $sharedSecretKey);
70        $receiverStateHandle = $pullInitialization[0];
71        $verifiedHeader = $pullInitialization[1]; // Can be used to confirm the header used
72
73        echo "Receiver successfully initialized pull stream with header: " . bin2hex($verifiedHeader) . PHP_EOL;
74        echo "Proceeding to decrypt received messages..." . PHP_EOL;
75
76        $decryptedMessages = [];
77        foreach ($encryptedStreamParts as $index => $encryptedPart) {
78            // Decrypt each part of the stream using the receiver's state handle.
79            // The function returns an array containing:
80            // [0] => The decrypted message string.
81            // [1] => The tag associated with this message part.
82            $decryptedResult = sodium_crypto_secretstream_xchacha20poly1305_pull(
83                $receiverStateHandle,
84                $encryptedPart
85            );
86            $decryptedMessage = $decryptedResult[0];
87            $receivedTag = $decryptedResult[1];
88
89            $decryptedMessages[] = $decryptedMessage;
90            echo "Decrypted message " . ($index + 1) . " (Received Tag: " . $receivedTag . "): '" . $decryptedMessage . "'" . PHP_EOL;
91
92            if ($receivedTag === SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL) {
93                echo "-> Final message tag detected, indicating the end of the stream." . PHP_EOL;
94            }
95        }
96
97        echo PHP_EOL;
98        echo "--- Verification ---" . PHP_EOL;
99        // Verify that all messages were decrypted correctly and match the originals.
100        if ($originalMessages === $decryptedMessages) {
101            echo "SUCCESS: All messages decrypted successfully and match the original messages." . PHP_EOL;
102        } else {
103            echo "FAILURE: Decryption resulted in mismatched messages." . PHP_EOL;
104        }
105
106    } catch (SodiumException $e) {
107        echo "ERROR: Failed to initialize pull stream or decrypt message: " . $e->getMessage() . PHP_EOL;
108    }
109}
110
111// Ensure the Sodium extension is loaded before attempting to use its functions.
112if (extension_loaded('sodium')) {
113    demonstrateSecretStreamDecryption();
114} else {
115    echo "The PHP 'sodium' extension is not loaded. Please enable it to run this example." . PHP_EOL;
116}

sodium_crypto_secretstream_xchacha20poly1305_init_pull関数は、PHPのSodium拡張機能の一部で、XChaCha20-Poly1305アルゴリズムを用いて暗号化されたデータストリームを復号する準備を行うための関数です。この関数は、送信側から受け取った暗号化ストリームを、受信側で安全に復元する際に最初に呼び出されます。

引数$headerには、送信側がストリームの暗号化を開始する際に生成したヘッダー情報を指定します。このヘッダーは、ストリームの復号に必要なメタデータを含んでおり、送信側から受信側へ安全に伝達される必要があります。もう一つの引数$keyには、送信側と受信側で事前に共有された32バイトの秘密鍵を指定します。この秘密鍵がなければ、ストリームの復号はできません。

この関数は配列を戻り値として返します。配列の最初の要素[0]は、その後のストリーム復号処理で使用する内部状態(ハンドル)です。二番目の要素[1]は、引数で渡されたヘッダーのコピーであり、正常に初期化されたことを確認するために利用できます。

この関数で得られたハンドルを使って、sodium_crypto_secretstream_xchacha20poly1305_pull関数を繰り返し呼び出すことで、ストリームの各部分を順次復号していくことが可能になります。これは、単一のメッセージを扱うsodium_crypto_secretboxとは異なり、大量の連続したデータを効率的かつ安全にやり取りするための仕組みです。

sodium_crypto_secretstream_xchacha20poly1305_init_pullは、共通の秘密鍵とストリームヘッダーを用いて、暗号化されたデータストリームの復号を開始する関数です。利用上の重要な注意点は、引数に渡す$header$keyが、暗号化時に使用されたものと完全に一致していなければ復号が失敗することです。特に$keyである秘密鍵は、通信の両端で安全に管理・共有されるべき極めて機密性の高い情報です。この関数は、単一のメッセージ暗号化でなく、連続するデータを効率的に処理するストリーム暗号化に最適化されており、sodium_crypto_secretboxとは用途が異なります。戻り値は、復号に用いる内部状態ハンドルと、確認用のヘッダーコピーを含む配列です。

関連コンテンツ

関連IT用語

関連プログラミング言語