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

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

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

作成日: 更新日:

基本的な使い方

sodium_crypto_aead_chacha20poly1305_ietf_encrypt関数は、ChaCha20-Poly1305アルゴリズム(IETF仕様)を用いて、指定されたメッセージを認証付き暗号化する関数です。この関数は、単にデータを秘密に保つ「暗号化」だけでなく、データが第三者によって改ざんされていないかを確認する「認証」の機能も兼ね備えているため、高いセキュリティを提供します。

具体的には、平文のメッセージ、オプションの関連データ(Associated Data: AD)、使い捨ての数値(Nonce: ナンス)、そして秘密鍵を入力として受け取ります。関連データは暗号化されませんが、暗号文と一緒に認証されるため、例えばヘッダー情報などの付随情報が改ざんされていないことを保証できます。ナンスは、同じ秘密鍵で複数のメッセージを暗号化する際に、毎回異なるユニークな値である必要があります。ナンスの再利用はセキュリティ上の脆弱性につながるため、厳重に管理することが重要です。

この関数は、暗号化されたメッセージと認証タグを結合した文字列を返します。これにより、データの盗聴や改ざんから情報を保護し、安全なデータ通信や保存を実現します。例えば、インターネットを介して機密情報を送受信する際や、データベースに重要な情報を格納する際などに利用されます。処理に失敗した場合や、無効な引数が渡された場合は、falseを返します。この機能はPHPの拡張機能として提供され、セキュアなアプリケーション開発を支援します。

構文(syntax)

1<?php
2$message = '暗号化するメッセージ';
3$additionalData = '認証されるが暗号化されない追加データ';
4$nonce = random_bytes(SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES);
5$key = random_bytes(SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES);
6
7$encryptedMessage = sodium_crypto_aead_chacha20poly1305_ietf_encrypt(
8    $message,
9    $additionalData,
10    $nonce,
11    $key
12);
13?>

引数(parameters)

string $message, string $additional_data, string $nonce, string $key

  • string $message: 暗号化したい平文データを指定する文字列
  • string $additional_data: 認証のみを行い、暗号化しない追加データを指定する文字列
  • string $nonce: ナンス(nonce)を指定する文字列。一意であることが重要です
  • string $key: 秘密鍵を指定する文字列

戻り値(return)

string

この関数は、ChaCha20-Poly1305-IETFアルゴリズムを使用してデータを暗号化し、その結果として暗号化されたバイナリ文字列を返します。

サンプルコード

PHP Sodium: ChaCha20-Poly1305暗号化・復号化

1<?php
2
3/**
4 * Demonstrates authenticated encryption and decryption using
5 * sodium_crypto_aead_chacha20poly1305_ietf_encrypt.
6 *
7 * This function showcases how to use the Sodium extension for secure data handling,
8 * including key generation, nonce management, and optional additional authenticated data (AAD).
9 */
10function encryptAndDecryptWithChacha20Poly1305Ietf(): void
11{
12    // 1. Generate a secure, random encryption key.
13    // This key must be kept secret and securely managed.
14    $key = sodium_crypto_aead_chacha20poly1305_ietf_keygen();
15
16    // 2. Define the message you want to encrypt.
17    $originalMessage = 'This is a super secret message for systems engineers!';
18
19    // 3. Define optional additional authenticated data (AAD).
20    // AAD is authenticated along with the ciphertext, but it is NOT encrypted.
21    // It's useful for binding the encryption to specific contexts (e.g., user ID, timestamp).
22    // If used during encryption, it MUST be provided identically during decryption.
23    $additionalData = 'user_id:12345, transaction_id:TXN987';
24
25    // 4. Generate a cryptographically secure random nonce (Number Used ONCE).
26    // The nonce size is critical and specific to the algorithm, defined by
27    // sodium_crypto_aead_chacha20poly1305_ietf_npubbytes.
28    // A nonce MUST NEVER be reused with the same key for this algorithm.
29    $nonceSize = sodium_crypto_aead_chacha20poly1305_ietf_npubbytes;
30    $nonce = random_bytes($nonceSize);
31
32    echo "--- Encryption Process ---" . PHP_EOL;
33    echo "Original Message: " . $originalMessage . PHP_EOL;
34    echo "Additional Data (AAD): " . $additionalData . PHP_EOL;
35    echo "Nonce Size: " . $nonceSize . " bytes" . PHP_EOL;
36    echo "Key Size: " . sodium_crypto_aead_chacha20poly1305_ietf_keybytes . " bytes" . PHP_EOL;
37
38    // 5. Encrypt the message.
39    // This function returns the ciphertext combined with an authentication tag.
40    $ciphertext = sodium_crypto_aead_chacha20poly1305_ietf_encrypt(
41        $originalMessage,
42        $additionalData,
43        $nonce,
44        $key
45    );
46
47    // For display, encode the binary ciphertext to base64.
48    echo "Encrypted Ciphertext (Base64): " . base64_encode($ciphertext) . PHP_EOL . PHP_EOL;
49
50    echo "--- Decryption Process ---" . PHP_EOL;
51    // 6. Decrypt the ciphertext.
52    // All original parameters ($ciphertext, $additionalData, $nonce, $key) are required.
53    // If any of these are tampered with or incorrect, decryption will fail (return false).
54    $decryptedMessage = sodium_crypto_aead_chacha20poly1305_ietf_decrypt(
55        $ciphertext,
56        $additionalData, // Must be the exact same AAD as used for encryption.
57        $nonce,          // Must be the exact same nonce as used for encryption.
58        $key             // Must be the exact same key.
59    );
60
61    // 7. Check if decryption was successful.
62    if ($decryptedMessage === false) {
63        echo "Decryption FAILED! The data might have been tampered with, " .
64             "or the key, nonce, or additional data were incorrect." . PHP_EOL;
65    } else {
66        echo "Decrypted Message: " . $decryptedMessage . PHP_EOL;
67
68        // Verify that the decrypted message matches the original.
69        if ($originalMessage === $decryptedMessage) {
70            echo "Verification: Original and decrypted messages MATCH." . PHP_EOL;
71        } else {
72            echo "Verification: Original and decrypted messages DO NOT MATCH. (This indicates an error!)" . PHP_EOL;
73        }
74    }
75
76    // 8. Securely erase sensitive data (key and nonce) from memory.
77    // This is a good practice to prevent sensitive data from lingering in memory.
78    sodium_memzero($key);
79    sodium_memzero($nonce);
80}
81
82// Ensure the 'sodium' extension is loaded before attempting to use its functions.
83if (!extension_loaded('sodium')) {
84    die("Error: The 'sodium' PHP extension is not loaded. Please enable it in your php.ini configuration." . PHP_EOL);
85}
86
87// Execute the demonstration function.
88encryptAndDecryptWithChacha20Poly1305Ietf();
89
90?>

PHPのsodium_crypto_aead_chacha20poly1305_ietf_encrypt関数は、Sodium拡張機能を通じて、データを認証付き暗号化するための重要な機能を提供します。この関数は、メッセージの機密性を保ちつつ、改ざんされていないことを保証するAEAD(Authenticated Encryption with Associated Data)アルゴリズムを採用しています。

サンプルコードでは、まずsodium_crypto_aead_chacha20poly1305_ietf_keygen()を用いて安全な秘密鍵を生成します。次に、暗号化したい元のメッセージ、任意で追加できる認証用データ($additional_data)、そしてsodium_crypto_aead_chacha20poly1305_ietf_npubbytesが示す正確なサイズのノンス($nonce)を用意します。ノンスは「Number Used ONCE」の略で、同じ鍵では決して再利用してはいけない一意の乱数です。

sodium_crypto_aead_chacha20poly1305_ietf_encrypt関数は、これらメッセージ、追加データ、ノンス、鍵を引数として受け取ります。戻り値として、暗号化されたメッセージと認証タグが結合された文字列を返します。この戻り値は、元のデータの保護と改ざん検知に利用されます。

復号処理にはsodium_crypto_aead_chacha20poly1305_ietf_decrypt関数を使用し、暗号化時と全く同じ鍵、ノンス、追加データを指定する必要があります。もしこれら引数の一部でも異なっていたり、暗号文が改ざんされていたりすると、復号は失敗しfalseが返されます。これにより、データの完全性と信頼性が確保されます。最後に、sodium_memzero関数で鍵やノンスなどの機密情報をメモリから安全に消去するセキュリティ上の良い実践も示されています。

このサンプルコードを利用する際、鍵とNonceの適切な管理が極めて重要です。鍵は厳重に秘密にし、Nonceは同じ鍵で二度と使用してはいけません。Nonceのサイズはsodium_crypto_aead_chacha20poly1305_ietf_npubbytesで取得し、常に安全な乱数で生成してください。追加認証データ(AAD)を使用する場合は、暗号化時と復号化時で完全に一致させる必要があります。復号に失敗した場合は、データが改ざんされたか、鍵、Nonce、AADのいずれかが誤っていることを示し、重要なセキュリティ警告となります。機密情報である鍵やNonceは、使用後にsodium_memzeroでメモリから安全に消去することを習慣にしましょう。この機能はPHPのSodium拡張機能が有効な環境でのみ動作します。

PHP sodium_crypto_aead_chacha20poly1305_ietf_encryptで暗号化・復号化する

1<?php
2
3// このスクリプトは、libsodiumライブラリのChaCha20-Poly1305 (IETF variant) を使用した
4// 認証付き暗号化と復号化の基本的な流れを示します。
5// システムエンジニアを目指す初心者向けに、各ステップをコメントで解説しています。
6
7/**
8 * ChaCha20-Poly1305 (IETF variant) を使用してメッセージを暗号化し、その後復号化します。
9 *
10 * AEAD (Authenticated Encryption with Associated Data) の概念を理解するために、
11 * 以下の処理を行います。
12 * 1. 鍵とノンス(使い捨ての数値)を生成します。
13 * 2. 指定されたメッセージと追加データを暗号化します。
14 * 3. 暗号化されたメッセージを復号化し、元のメッセージと一致するか確認します。
15 *
16 * @param string $originalMessage 暗号化する元のメッセージ。
17 * @param string $additionalData オプションの追加データ。これは暗号化されませんが、
18 *                                認証タグの一部として検証されます(改ざん防止)。
19 * @return void 結果を標準出力に出力します。
20 */
21function demonstrateChaCha20Poly1305IetfEncryptionDecryption(string $originalMessage, string $additionalData = ''): void
22{
23    echo "--- ChaCha20-Poly1305 (IETF) AEAD デモンストレーション ---\n\n";
24
25    echo "元のメッセージ: " . $originalMessage . "\n";
26    echo "追加データ: " . ($additionalData ?: '[なし]') . "\n\n";
27
28    // 1. セキュアなランダム鍵を生成します。
29    // 鍵の長さは SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES で定義されたバイト数でなければなりません。
30    $key = random_bytes(SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES);
31    echo "鍵 (Hex): " . bin2hex($key) . "\n";
32
33    // 2. セキュアなランダムノンス(Number Used Once)を生成します。
34    // ノンスの長さは SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES で定義されたバイト数でなければなりません。
35    // 同じ鍵で複数のメッセージを暗号化する場合、各メッセージに対して異なるノンスを使用することが非常に重要です。
36    $nonce = random_bytes(SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES);
37    echo "ノンス (Hex): " . bin2hex($nonce) . "\n\n";
38
39    // 3. メッセージを暗号化します。
40    // sodium_crypto_aead_chacha20poly1305_ietf_encrypt は、暗号文と認証タグを連結した文字列を返します。
41    // 認証タグは、メッセージと追加データが改ざんされていないことを検証するために使用されます。
42    try {
43        $ciphertextWithTag = sodium_crypto_aead_chacha20poly1305_ietf_encrypt(
44            $originalMessage,
45            $additionalData,
46            $nonce,
47            $key
48        );
49        echo "暗号化成功。\n";
50        echo "暗号文 + タグ (Hex): " . bin2hex($ciphertextWithTag) . "\n\n";
51    } catch (SodiumException $e) {
52        echo "暗号化失敗: " . $e->getMessage() . "\n";
53        return;
54    }
55
56    // 4. メッセージを復号化します。
57    // sodium_crypto_aead_chacha20poly1305_ietf_decrypt は、認証タグを検証し、
58    // 検証が成功した場合に元のメッセージを返します。
59    // データまたは認証タグが改ざんされた場合(または誤った鍵/ノンスが使用された場合)、falseを返します。
60    try {
61        $decryptedMessage = sodium_crypto_aead_chacha20poly1305_ietf_decrypt(
62            $ciphertextWithTag,
63            $additionalData,
64            $nonce,
65            $key
66        );
67
68        if ($decryptedMessage === false) {
69            echo "復号化失敗: 認証タグが無効であるか、データが改ざんされました。\n";
70        } else {
71            echo "復号化成功。\n";
72            echo "復号化されたメッセージ: " . $decryptedMessage . "\n\n";
73
74            // 復号化されたメッセージが元のメッセージと一致するか検証します。
75            if ($decryptedMessage === $originalMessage) {
76                echo "検証: 復号化されたメッセージは元のメッセージと一致します。(成功)\n";
77            } else {
78                echo "検証: 復号化されたメッセージは元のメッセージと一致しません。(失敗)\n";
79            }
80        }
81    } catch (SodiumException $e) {
82        echo "復号化失敗: " . $e->getMessage() . "\n";
83    }
84
85    echo "\n------------------------------------------------------\n";
86}
87
88// --- 使用例 ---
89// libsodium拡張機能がロードされていることを確認します。
90if (!extension_loaded('sodium')) {
91    die("エラー: 'sodium' 拡張機能がロードされていません。php.iniで有効にしてください。\n");
92}
93
94$message1 = "システムエンジニアさん、こんにちは!これは秘密のメッセージです。";
95$aad1 = "トランザクションID-12345";
96demonstrateChaCha20Poly1305IetfEncryptionDecryption($message1, $aad1);
97
98$message2 = "追加データなしの別の機密情報です。";
99demonstrateChaCha20Poly1305IetfEncryptionDecryption($message2);

PHPのsodium_crypto_aead_chacha20poly1305_ietf_encrypt関数は、libsodiumライブラリを利用し、ChaCha20-Poly1305 (IETF variant) アルゴリズムを用いた認証付き暗号化(AEAD)を実現するための関数です。この関数を使用することで、メッセージの機密性を保つだけでなく、データが改ざんされていないことを同時に検証できるようになります。

この関数は、暗号化したい$message(文字列)、オプションで認証の対象としたい$additional_data(文字列)、各暗号化処理で一度だけ使用する$nonce(使い捨ての乱数、文字列)、そして暗号化と復号化に用いる秘密の$key(文字列)の4つの引数を受け取ります。$additional_dataは暗号化されませんが、認証タグの一部として検証されるため、改ざん防止に役立ちます。$nonceは同じ鍵で複数のメッセージを暗号化する際に、メッセージごとに異なる値を設定することが必須です。

処理が成功すると、暗号化されたデータと認証タグが結合された単一の文字列が戻り値として返されます。この結合された文字列は、対応するsodium_crypto_aead_chacha20poly1305_ietf_decrypt関数と、同じ鍵、ノンス、追加データを用いることで復号化し、元のメッセージを取り出すことができます。鍵とノンスはrandom_bytes関数などを用いて、必ず安全に生成してください。

このサンプルコードで認証付き暗号化を行う上で、特に重要な注意点がいくつかあります。まず、暗号化に用いる鍵は絶対に秘密にし、厳重に管理してください。そして、ノンス(Number Used Once)は、同じ鍵で暗号化するすべてのメッセージに対して、毎回必ず異なるランダムな値を使用することが極めて重要です。 ノンスの再利用はセキュリティ上の深刻な脆弱性を引き起こします。また、additional_dataは暗号化されませんが、認証タグによって改ざんの有無が検証されるため、データの完全性を高めます。復号化関数がfalseを返した場合、データが改ざんされたか、誤った鍵やノンスが使用されたことを意味し、そのメッセージは信用できないと判断してください。最後に、この機能を使用するにはPHPのsodium拡張機能が有効になっている必要がありますので、確認をお願いします。

関連コンテンツ

関連IT用語

関連プログラミング言語