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

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

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

作成日: 更新日:

基本的な使い方

sodium_crypto_stream関数は、ストリーム暗号化処理に利用できる擬似乱数バイト列を生成する関数です。この関数は、指定された長さの、暗号学的に安全なランダムなバイト列を生成します。

主にストリーム暗号(例えばSalsa20やChaCha20)において、データの暗号化や復号に必要な鍵ストリームの一部を生成するために使用されます。また、他の暗号処理におけるノンス(Number Used Once、一度だけ使用される値)や、予測不可能な安全なデータが必要な場面でも活用できます。

引数として、生成したいバイト列の長さを指定する$length、暗号処理のたびに異なるユニークな値であるノンスを指定する$nonce、そして暗号化に使用する秘密鍵である$keyを受け取ります。$nonceは、同じ鍵で複数回この関数を使用する際に使い回すとセキュリティ上の脆弱性につながるため、必ず異なる値を指定する必要があります。$keyは、外部に漏洩しないよう厳重に管理することが求められます。

この関数によって生成されるバイト列は、指定された鍵とノンスに基づき、常に予測不可能なため、高いセキュリティが保証されます。戻り値として、指定した長さの、暗号学的に安全なバイト列を返します。

構文(syntax)

1$keystream = sodium_crypto_stream(
2    int $length,
3    string $nonce,
4    string $key
5);

引数(parameters)

int $length, string $nonce, string $key

  • int $length: 生成する暗号化ストリームのバイト長を指定する整数
  • string $nonce: 一意性を保証するためのノンス(nonce)を指定する文字列。同じキーとノンスの組み合わせで同じ平文を暗号化しても、異なる暗号文が生成されます。
  • string $key: 暗号化に使用する秘密鍵を指定する文字列。

戻り値(return)

string

暗号化されたデータが文字列として返されます。

サンプルコード

PHP Libsodium ストリーム暗号でデータを暗号化する

1<?php
2
3/**
4 * Libsodiumのストリーム暗号を使用してデータを暗号化・復号化するサンプル。
5 * sodium_crypto_stream 関数は、暗号化に使用する疑似乱数ストリーム(パッド)を生成します。
6 * このパッドを平文とXORすることで暗号化が行われます。
7 *
8 * これは、stream_socket_enable_crypto のようなネットワークストリームの暗号化とは異なり、
9 * より低レベルなアプリケーション層でのデータの暗号化に使用されます。
10 *
11 * @param string $data 暗号化/復号化するデータ
12 * @param string $nonce 一度だけ使用されるランダムな値 (Nonce)
13 * @param string $key ストリーム暗号用の秘密鍵
14 * @return string 暗号化または復号化されたデータ
15 * @throws Exception 鍵またはノンスの長さが不適切である場合、またはSodium拡張が利用できない場合
16 */
17function encryptDecryptWithSodiumStream(string $data, string $nonce, string $key): string
18{
19    // Libsodiumが利用可能か確認
20    if (!extension_loaded('sodium')) {
21        throw new Exception('Sodium extension is not loaded. Please enable it in php.ini.');
22    }
23
24    // キーの長さが正しいか確認
25    if (mb_strlen($key, '8bit') !== SODIUM_CRYPTO_STREAM_KEYBYTES) {
26        throw new Exception('Invalid key length. Key must be ' . SODIUM_CRYPTO_STREAM_KEYBYTES . ' bytes.');
27    }
28
29    // ノンスの長さが正しいか確認
30    if (mb_strlen($nonce, '8bit') !== SODIUM_CRYPTO_STREAM_NONCEBYTES) {
31        throw new Exception('Invalid nonce length. Nonce must be ' . SODIUM_CRYPTO_STREAM_NONCEBYTES . ' bytes.');
32    }
33
34    // sodium_crypto_stream を使用して、データの長さと同じ疑似乱数ストリーム(パッド)を生成します。
35    // このパッドは、指定されたキーとノンスから再現可能な疑似乱数列であり、平文とXORすることで暗号文を生成するために使用されます。
36    // これは、PHPの stream_socket_enable_crypto が提供するTLS/SSLのようなトランスポート層の暗号化とは異なり、
37    // アプリケーションが直接データを暗号化する際に利用されるストリーム暗号の構成要素です。
38    $streamPad = sodium_crypto_stream(mb_strlen($data, '8bit'), $nonce, $key);
39
40    // 生成されたストリームパッドとデータをバイトごとにXORすることで暗号化/復号化します。
41    // PHPでは文字列に対するバイト単位のXOR演算が直接可能です。
42    // 同じストリームパッドで2回XORすると元のデータに戻ります。
43    return $data ^ $streamPad;
44}
45
46// 例の使用法
47try {
48    // 1. ストリーム暗号用の秘密鍵を生成
49    // sodium_crypto_stream_keygen() は SODIUM_CRYPTO_STREAM_KEYBYTES の長さのランダムな鍵を生成します。
50    $key = sodium_crypto_stream_keygen();
51    echo "Generated Key (hex): " . bin2hex($key) . PHP_EOL;
52
53    // 2. ノンス(Nonce - Number used once)を生成
54    // ノンスは暗号化ごとに異なるものである必要がありますが、復号化時には同じものが必要です。
55    // 推奨される長さは SODIUM_CRYPTO_STREAM_NONCEBYTES (PHP 8.xでは24バイト) です。
56    $nonce = random_bytes(SODIUM_CRYPTO_STREAM_NONCEBYTES);
57    echo "Generated Nonce (hex): " . bin2hex($nonce) . PHP_EOL;
58
59    // 3. 暗号化する平文データ
60    $plaintext = "Hello, this is a secret message for beginners learning PHP and cryptography!";
61    echo "Original Plaintext: " . $plaintext . PHP_EOL;
62
63    // 4. データを暗号化
64    $ciphertext = encryptDecryptWithSodiumStream($plaintext, $nonce, $key);
65    echo "Ciphertext (hex): " . bin2hex($ciphertext) . PHP_EOL;
66
67    // 5. データを復号化 (暗号化時と同じ nonce と key を使用)
68    $decryptedtext = encryptDecryptWithSodiumStream($ciphertext, $nonce, $key);
69    echo "Decrypted Plaintext: " . $decryptedtext . PHP_EOL;
70
71    // 復号化されたデータが元のデータと同じであることを確認
72    if ($plaintext === $decryptedtext) {
73        echo "Encryption and decryption successful!" . PHP_EOL;
74    } else {
75        echo "Error: Decrypted text does not match original plaintext." . PHP_EOL;
76    }
77
78} catch (Exception $e) {
79    echo "An error occurred: " . $e->getMessage() . PHP_EOL;
80    exit(1); // エラー発生時にプログラムを終了
81}

sodium_crypto_stream関数は、PHP 8で利用可能なLibsodium拡張機能の一部で、ストリーム暗号化の基礎となる疑似乱数ストリーム(パッド)を生成するために使用されます。この関数は、指定された秘密鍵とノンス(一度だけ使用する値)から、指定された長さのバイト列を生成します。

引数としては、生成するパッドの長さをバイト数で指定する$length、暗号化ごとに異なる必要があり復号化時にも同じものが必要となるランダムな値$nonce、そして暗号化・復号化に使う秘密鍵$keyを受け取ります。戻り値は、生成された疑似乱数ストリームを表す文字列です。

この生成されたパッドと元のデータをバイトごとにXOR演算することで、暗号化や復号化が行われます。同じパッドで二度XORすると元のデータに戻るため、この一方向の関数で暗号化と復号化の両方が可能です。

これは、stream_socket_enable_crypto関数が提供するTLS/SSLのようなネットワーク通信の暗号化とは異なり、アプリケーションが直接データの中身を保護したい場合に、より低レベルで柔軟な暗号化を実装する際に利用される機能です。安全な利用のためには、鍵とノンスの適切な生成と管理が非常に重要となります。

sodium_crypto_stream関数は、指定した長さの疑似乱数ストリーム(パッド)を生成するものです。このパッドとデータをXORすることで暗号化・復号化を行うため、関数自体が直接データを暗号化するわけではない点にご注意ください。これは、stream_socket_enable_cryptoのようなネットワーク通信を暗号化する機能とは異なり、アプリケーション層でデータを扱う際に利用される暗号化の仕組みです。鍵とノンスは、それぞれ定められた正確な長さで生成し、ノンスは暗号化ごとに必ず異なるものを使用し、決して使い回さないでください。また、PHP環境でLibSodium拡張が有効になっていることを確認してからご利用ください。これらの点を守ることで、安全に暗号化処理を実施できます。

PHP sodium_crypto_streamで暗号ストリームを生成する

1<?php
2
3/**
4 * LibsodiumライブラリのPHP拡張機能である`sodium`を使って、
5 * 暗号学的に安全なバイトストリームを生成するサンプルコードです。
6 *
7 * キーワード「php sodium と は」について:
8 * `sodium`は、暗号プリミティブを提供するLibsodiumライブラリのPHP拡張です。
9 * `sodium_crypto_stream`は、ストリーム暗号の主要部分として、
10 * 鍵とノンス(使い捨ての数値)に基づいて予測不可能なバイト列を生成します。
11 * これはデータの暗号化、または安全なランダムバイトの生成などに利用されます。
12 */
13
14/**
15 * Libsodiumのcrypto_stream関数を直接呼び出して、指定された長さの暗号ストリームを生成します。
16 *
17 * @param int $length 生成するストリームの長さ(バイト数)。
18 * @param string $nonce ノンス(使い捨ての数値)。`sodium_crypto_stream_NONCEBYTES`の長さが必要です。
19 * @param string $key 秘密鍵。`sodium_crypto_stream_KEYBYTES`の長さが必要です。
20 * @return string 生成された暗号ストリーム。
21 * @throws Exception sodium拡張機能が利用できない場合。
22 */
23function use_sodium_crypto_stream_function(int $length, string $nonce, string $key): string
24{
25    // sodium拡張機能がロードされているか確認します。
26    // ロードされていない場合、関連する定数や関数は利用できません。
27    if (!extension_loaded('sodium')) {
28        throw new Exception('Sodium extension is not loaded. Please enable it in php.ini.');
29    }
30
31    // `sodium_crypto_stream`関数を呼び出し、暗号ストリームを生成します。
32    // 引数の$nonceと$keyは、事前に適切な長さと安全性で生成されている必要があります。
33    return sodium_crypto_stream($length, $nonce, $key);
34}
35
36// ----------------------------------------------------
37// サンプルコードの実行部分
38// ----------------------------------------------------
39
40try {
41    // `sodium_crypto_stream`に必要な鍵とノンスのバイト数を取得します。
42    // これらの定数は`sodium`拡張機能によって提供されます。
43    $key_bytes = sodium_crypto_stream_KEYBYTES;
44    $nonce_bytes = sodium_crypto_stream_NONCEBYTES;
45
46    // 安全な鍵とノンスを生成します。
47    // `random_bytes()`は暗号学的に安全な疑似乱数を生成します。
48    // 本番環境では、鍵は安全に管理された場所から取得し、
49    // ノンスは毎回異なる、予測不可能な値を使用することが必須です。
50    $key = random_bytes($key_bytes);
51    $nonce = random_bytes($nonce_bytes);
52
53    // 生成するストリームの長さを定義します (例: 64バイト)。
54    $stream_length_to_generate = 64;
55
56    echo "生成するストリームの長さ: " . $stream_length_to_generate . "バイト\n";
57    echo "鍵の長さ: " . strlen($key) . "バイト (要求: " . $key_bytes . "バイト)\n";
58    echo "ノンスの長さ: " . strlen($nonce) . "バイト (要求: " . $nonce_bytes . "バイト)\n";
59
60    // 暗号ストリームを生成します。
61    $generated_stream = use_sodium_crypto_stream_function($stream_length_to_generate, $nonce, $key);
62
63    echo "生成された暗号ストリーム (長さ: " . strlen($generated_stream) . "バイト):\n";
64    // バイナリデータを可視化するため、16進数文字列に変換して表示します。
65    echo bin2hex($generated_stream) . "\n";
66
67} catch (TypeError $e) {
68    // 引数の型が不正な場合に発生します。
69    echo "エラー (TypeError): " . $e->getMessage() . "\n";
70    exit(1);
71} catch (ValueError $e) {
72    // 引数の値が不正な場合に発生します (例: ノンスや鍵の長さが不適切)。
73    echo "エラー (ValueError): " . $e->getMessage() . "\n";
74    exit(1);
75} catch (Exception $e) {
76    // その他のエラー (例: sodium拡張機能がロードされていない) が発生した場合。
77    echo "エラー: " . $e->getMessage() . "\n";
78    exit(1);
79}

PHP 8のsodium_crypto_stream関数は、LibsodiumライブラリのPHP拡張機能であるsodiumの一部です。sodiumとは、PHPで高度な暗号処理を安全に扱うための機能を提供する拡張機能であり、本関数は暗号学的に安全なバイトストリームを生成します。これは、データの暗号化や安全なランダムバイトの生成などに利用されます。

引数としては、生成したいストリームの長さをバイト数で指定する$length(整数)、ストリーム生成のたびに異なる、使い捨ての数値である$nonce(文字列)、そして秘密情報である$key(文字列)を受け取ります。$nonce$keyはそれぞれ所定の長さ(sodium_crypto_stream_NONCEBYTESsodium_crypto_stream_KEYBYTESで定義)が必要です。戻り値は、指定された長さで生成された暗号ストリームをバイナリ文字列として返します。セキュリティを確保するため、$keyは厳重に管理し、$nonceは毎回ユニークで予測不可能な値を安全に生成して使用することが重要です。

sodium_crypto_streamは暗号学的に安全なバイトストリームを生成する関数です。利用にはPHPのsodium拡張機能の有効化が必須となります。引数である鍵とノンスは、それぞれsodium_crypto_stream_KEYBYTESsodium_crypto_stream_NONCEBYTESで定められた正確な長さで提供する必要があります。特に、鍵は厳重に管理し、ノンスは毎回異なる予測不可能な値を必ず使用してください。同じ鍵とノンスの組み合わせを繰り返し使うことは、セキュリティを著しく損なうため避けるべきです。これらの値はrandom_bytes()などで安全に生成し、型や値が不正な場合はエラーとなるため、適切なエラーハンドリングを実装することが重要です。

関連コンテンツ

関連IT用語

関連プログラミング言語