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

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

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

作成日: 更新日:

基本的な使い方

sodium_crypto_aead_chacha20poly1305_ietf_keygen関数は、ChaCha20-Poly1305(IETF版)という認証付き暗号方式で使用する、安全な暗号化キー(鍵)を生成する関数です。この暗号方式は、データの機密性(内容を秘密に保つこと)と完全性(データが改ざんされていないこと)の両方を同時に保護するために設計されています。

この関数が生成するキーは、暗号化と復号化の双方に利用されるため、セキュリティ上非常に重要です。予測不可能なランダムなキーであることは、安全な通信を確立する上で不可欠となります。本関数は、PHPのSodiumエクステンションによって提供され、暗号学的に強力な乱数生成器を用いて、指定された暗号方式に適した長さ(256ビット、つまり32バイト)の安全なキーを生成します。

生成されたキーは、例えばsodium_crypto_aead_chacha20poly1305_ietf_encrypt関数でデータを暗号化する際や、sodium_crypto_aead_chacha20poly1305_ietf_decrypt関数でデータを復号化する際に使用されます。キーを生成する際には、この関数を一度だけ実行し、その生成されたキーを秘密かつ安全に管理することが求められます。これにより、第三者によるデータの解読や改ざんを防ぎ、安全な情報交換が可能になります。

構文(syntax)

1<?php
2
3$key = sodium_crypto_aead_chacha20poly1305_ietf_keygen();
4
5?>

引数(parameters)

引数なし

引数はありません

戻り値(return)

string

ChaCha20-Poly1305-IETF暗号化に使用できる、ランダムで安全な32バイトの鍵を文字列として返します。

サンプルコード

ChaCha20-Poly1305 IETF 暗号化・復号化デモ

1<?php
2
3/**
4 * ChaCha20-Poly1305 IETF を用いたデータの暗号化と復号化の例。
5 * システムエンジニアを目指す初心者向けに、安全なデータ処理の基本を示します。
6 *
7 * この関数は、ランダムな秘密鍵を生成し、その鍵とユニークなNonceを使って
8 * 平文を暗号化し、その後、正しく復号化できることを示します。
9 */
10function demonstrateAeadEncryptionDecryption(): void
11{
12    echo "=== ChaCha20-Poly1305 IETF 暗号化・復号化のデモンストレーション ===\n\n";
13
14    // 1. 秘密鍵の生成
15    // sodium_crypto_aead_chacha20poly1305_ietf_keygen() は、
16    // 暗号化と復号化に使用するランダムで強力な秘密鍵を生成します。
17    // この鍵は、データが安全であることを保証するために絶対に秘密に保つ必要があります。
18    $key = sodium_crypto_aead_chacha20poly1305_ietf_keygen();
19    echo "1. 秘密鍵を生成しました (セキュリティのため、内容は直接表示しません)。\n";
20    // var_dump(bin2hex($key)); // デバッグ用: 鍵の内容を確認したい場合
21
22    // 2. Nonce (Number Used Once) の生成
23    // Nonceは、各暗号化操作ごとに「一度だけ使用される数値」です。
24    // 同じ鍵で同じNonceを複数回使用すると、セキュリティが著しく低下するため、
25    // 必ずユニークなものを生成する必要があります。
26    // sodium_crypto_aead_chacha20poly1305_ietf_npubbytes は、
27    // このアルゴリズムに必要なNonceのバイト数 (長さ) を教えてくれます。
28    $nonce = random_bytes(sodium_crypto_aead_chacha20poly1305_ietf_npubbytes);
29    echo "2. ユニークなNonceを生成しました (セキュリティのため、内容は直接表示しません)。\n";
30    echo "   (必要なNonceサイズ: " . sodium_crypto_aead_chacha20poly1305_ietf_npubbytes . " バイト)\n";
31    // var_dump(bin2hex($nonce)); // デバッグ用: Nonceの内容を確認したい場合
32
33    // 3. 暗号化したい平文データと追加認証データ (AAD) の準備
34    $plaintext = "これはChaCha20-Poly1305 IETFで暗号化される秘密のメッセージです。";
35    echo "3. 暗号化する平文: '{$plaintext}'\n";
36
37    // 追加認証データ (AAD) は、暗号化はされませんが、暗号文と一緒に認証されるデータです。
38    // これにより、暗号文だけでなくAADの改ざんも検知できます。
39    // 例: データベースのレコードIDなど。
40    $additionalData = "userID_123_sessionID_abc";
41    echo "   追加認証データ (AAD): '{$additionalData}'\n";
42
43    // 4. データの暗号化
44    // sodium_crypto_aead_chacha20poly1305_ietf_encrypt() を使用してデータを暗号化します。
45    // 戻り値は、暗号文と認証タグが結合された文字列です。
46    $ciphertext = sodium_crypto_aead_chacha20poly1305_ietf_encrypt(
47        $plaintext,
48        $additionalData,
49        $nonce,
50        $key
51    );
52    echo "4. データを暗号化しました。暗号文の長さ: " . strlen($ciphertext) . " バイト\n";
53    // var_dump(bin2hex($ciphertext)); // デバッグ用: 暗号文の内容を確認したい場合
54
55    // 5. データの復号化
56    // sodium_crypto_aead_chacha20poly1305_ietf_decrypt() を使用してデータを復号化します。
57    // 暗号化時と全く同じ鍵、Nonce、追加認証データが提供されない場合、
58    // または暗号文が改ざんされている場合、この関数は false を返して復号化に失敗します。
59    $decryptedPlaintext = sodium_crypto_aead_chacha20poly1305_ietf_decrypt(
60        $ciphertext,
61        $additionalData,
62        $nonce,
63        $key
64    );
65
66    echo "5. データを復号化しました。\n";
67
68    // 6. 復号化結果の確認
69    if ($decryptedPlaintext !== false) {
70        echo "   復号化された平文: '{$decryptedPlaintext}'\n";
71        if ($decryptedPlaintext === $plaintext) {
72            echo "   => 復号化は成功し、元の平文と完全に一致しました。\n";
73        } else {
74            echo "   => エラー: 復号化は成功しましたが、元の平文と一致しません。\n";
75        }
76    } else {
77        echo "   => エラー: 復号化に失敗しました。これは、鍵、Nonce、または追加認証データが間違っているか、\n";
78        echo "      暗号文が送信中に改ざんされたことを意味します。\n";
79    }
80
81    echo "\n=== デモンストレーション終了 ===\n";
82}
83
84// 関数を実行してデモンストレーションを開始します。
85demonstrateAeadEncryptionDecryption();

sodium_crypto_aead_chacha20poly1305_ietf_keygen関数は、PHP 8で利用可能なSodium拡張機能の一部として、ChaCha20-Poly1305 IETFという認証付き暗号アルゴリズムで使用する、安全でランダムな秘密鍵を生成します。この関数は引数を取らず、暗号化と復号化の両方に必要となる、強力な秘密鍵を表す文字列(string)を戻り値として返します。生成された鍵はデータの機密性を保証するための基盤であり、外部に漏洩しないよう厳重に管理する必要があります。

サンプルコードでは、この関数を用いて最初に秘密鍵を生成しています。その後、sodium_crypto_aead_chacha20poly1305_ietf_npubbytes関数で取得した必要なバイト数に基づき、各暗号化操作で一度だけ使用するユニークなNonce(ナンス)を生成します。そして、生成された秘密鍵とNonce、任意に指定する追加認証データ(AAD)と共に、sodium_crypto_aead_chacha20poly1305_ietf_encrypt関数で平文を暗号化します。復号化の際には、暗号化時と完全に一致する秘密鍵、Nonce、AADを提供することで、sodium_crypto_aead_chacha20poly1305_ietf_decrypt関数が元の平文を安全に復元できることを示しています。この一連の処理は、システムにおいて重要なデータを保護するための基本的な手順を示しており、sodium_crypto_aead_chacha20poly1305_ietf_keygenはそのセキュリティの第一歩を担います。

生成された秘密鍵は厳重に管理し、絶対に公開しないでください。漏洩すると暗号化データが全て解読されます。Nonce(一度だけ使用される数値)は、毎回必ず新しくユニークなものを生成してください。同じ鍵とNonceを複数回使うと、セキュリティが大きく損なわれるため、sodium_crypto_aead_chacha20poly1305_ietf_npubbytesの推奨サイズで生成が必須です。追加認証データ(AAD)は、暗号文と一緒に認証され改ざん防止に役立ちますので、適切に活用してください。復号化がfalseを返した場合、鍵、Nonce、AADのいずれかが不正か暗号文が改ざんされたサインですので、適切にエラーを処理してください。これらの機能はPHPのSodium拡張が有効な環境でのみ動作します。

PHP Sodium拡張でAEAD鍵を生成する

1<?php
2
3declare(strict_types=1);
4
5/**
6 * PHPのSodium拡張を使って、共通鍵暗号(Authenticated Encryption with Associated Data - AEAD)
7 * の鍵生成、暗号化、復号の一連の流れを示すサンプル関数です。
8 *
9 * sodium_crypto_aead_chacha20poly1305_ietf_keygen() 関数は、
10 * ChaCha20-Poly1305 IETF アルゴリズムで使用する秘密鍵を生成します。
11 * この鍵は、データの暗号化と復号、およびデータの改ざん検出(認証)の両方に利用されます。
12 *
13 * 【キーワード「sodium_crypto_box」について】
14 * このサンプルは共通鍵暗号(対称暗号)の利用を示しています。
15 * 一方、`sodium_crypto_box` 関数群は、公開鍵暗号(非対称暗号)の機能を提供します。
16 * 両方ともPHPのSodium拡張が提供する強力な暗号機能の一部ですが、用途が異なります。
17 * このコードは、`sodium_crypto_aead_chacha20poly1305_ietf_keygen` を中心に、
18 * Sodium拡張を使った暗号化の基本的な考え方を示しています。
19 */
20function demonstrateSodiumAead(): void
21{
22    echo "--- Sodium AEAD (ChaCha20-Poly1305 IETF) のデモンストレーション ---" . PHP_EOL;
23
24    // 1. 共通鍵(秘密鍵)の生成
25    // この鍵は、暗号化と復号の両方に使われるため、厳重に管理する必要があります。
26    $secretKey = sodium_crypto_aead_chacha20poly1305_ietf_keygen();
27    echo "生成された共通鍵の長さ: " . strlen($secretKey) . " バイト" . PHP_EOL;
28    // 鍵自体はバイナリデータなので、そのまま表示しても判読可能な文字列にはなりません。
29
30    // 2. 暗号化する元のメッセージの準備
31    $originalMessage = "こんにちは、これは極秘メッセージです!";
32    echo "元のメッセージ: " . $originalMessage . PHP_EOL;
33
34    // 3. ノンセ(Nonce: Number used once)の生成
35    // ノンセは、同じ鍵で複数のメッセージを暗号化する際に必須です。
36    // 暗号化するたびに、絶対に重複しないユニークなノンセを使用する必要があります。
37    // 同じ鍵とノンセの組み合わせを2度使用すると、セキュリティ上の問題が発生します。
38    $nonce = random_bytes(SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES);
39    echo "生成されたノンセの長さ: " . strlen($nonce) . " バイト" . PHP_EOL;
40
41    // 4. 追加データ(Optional Associated Data - AAD)の準備
42    // このデータは暗号化されませんが、認証データの一部として扱われます。
43    // 例えば、送信者情報やタイムスタンプなど、メッセージと関連付けたい情報を設定します。
44    // 復号時にこのデータが一致しないと認証エラーとなり、復号が拒否されます。
45    $additionalData = "アプリケーションID: app-001, 処理ID: tx-5678";
46    echo "追加認証データ: " . $additionalData . PHP_EOL;
47
48    // 5. メッセージの暗号化
49    // sodium_crypto_aead_chacha20poly1305_ietf_encrypt() 関数は、
50    // 指定された鍵、ノンセ、追加データを使用してメッセージを暗号化し、
51    // 認証タグを付与した暗号文を生成します。
52    $encryptedMessage = sodium_crypto_aead_chacha20poly1305_ietf_encrypt(
53        $originalMessage,
54        $additionalData,
55        $nonce,
56        $secretKey
57    );
58    echo "暗号化されたメッセージ (Hex表現): " . bin2hex($encryptedMessage) . PHP_EOL;
59    echo "暗号化されたメッセージの長さ: " . strlen($encryptedMessage) . " バイト" . PHP_EOL;
60
61    // 6. メッセージの復号
62    // sodium_crypto_aead_chacha20poly1305_ietf_decrypt() 関数は、
63    // 暗号化されたメッセージ、鍵、元のノンセ、元の追加データを使用して復号を試みます。
64    // 認証に成功し、復号も成功した場合に元のメッセージを返します。
65    // 復号に失敗したり、データが改ざんされている場合は `false` を返します。
66    $decryptedMessage = sodium_crypto_aead_chacha20poly1305_ietf_decrypt(
67        $encryptedMessage,
68        $additionalData, // 暗号化時と同じ追加データを渡す必要がある
69        $nonce,          // 暗号化時と同じノンセを渡す必要がある
70        $secretKey       // 暗号化時と同じ秘密鍵を渡す必要がある
71    );
72
73    // 7. 復号結果の検証
74    if ($decryptedMessage === false) {
75        echo "エラー: メッセージの復号または認証に失敗しました。データが改ざんされたか、鍵/ノンセ/追加データが一致しません。" . PHP_EOL;
76        return;
77    }
78
79    echo "復号されたメッセージ: " . $decryptedMessage . PHP_EOL;
80
81    // 元のメッセージと復号されたメッセージが一致するか確認
82    if ($decryptedMessage === $originalMessage) {
83        echo "メッセージは正常に暗号化され、復号されました!" . PHP_EOL;
84    } else {
85        echo "エラー: 復号されたメッセージが元のメッセージと一致しません。何らかの問題が発生しました。" . PHP_EOL;
86    }
87
88    echo "--- デモンストレーション終了 ---" . PHP_EOL;
89}
90
91// 関数を実行します。
92// PHPでこのスクリプトを実行すると、上記の処理が順に実行されます。
93demonstrateSodiumAead();

このPHPサンプルコードは、PHP 8で利用可能なSodium拡張を使用し、共通鍵暗号(AEAD: Authenticated Encryption with Associated Data)の一連の基本的な流れをシステムエンジニアを目指す方向けに示しています。

sodium_crypto_aead_chacha20poly1305_ietf_keygen関数は、ChaCha20-Poly1305 IETFという強力な暗号アルゴリズムで使用する秘密鍵を生成します。この関数は引数を一切取らず、暗号化、復号、そしてデータの改ざん検出(認証)に不可欠なランダムなバイナリ文字列(秘密鍵)を戻り値として返します。

サンプルでは、まずこの関数で生成した秘密鍵を用いて、元のメッセージを、毎回異なる値であるノンセ(Nonce)と任意に追加できる認証データと共に暗号化します。この認証データは暗号化されませんが、データの完全性確認に利用されます。次に、暗号化されたメッセージを同じ秘密鍵、ノンセ、認証データを用いて復号し、元のメッセージと完全に一致するかを検証することで、データが安全に保護され、改ざんされていないことを確認する流れを理解できます。

なお、キーワードに挙げられたsodium_crypto_boxは公開鍵暗号方式に用いられる関数群であり、共通鍵暗号を扱うこのサンプルコードとは異なる目的で使用されることを補足いたします。このコードを通じて、PHPにおける安全なデータ暗号化の基礎を学ぶことができます。

共通鍵は厳重に管理し、漏洩させないでください。漏洩すると暗号化が無意味になります。ノンセは暗号化ごとに必ず異なる値を使い、絶対に重複させないでください。同じ鍵とノンセの組み合わせを二度使用すると、セキュリティ上の重大な問題が発生します。追加認証データは暗号化時と復号時で完全に一致させる必要があり、不一致は改ざん検知として復号を拒否します。sodium_crypto_boxは公開鍵暗号であり、この共通鍵暗号とは用途が異なるため混同にご注意ください。復号関数がfalseを返した際は、復号失敗またはデータ改ざんを示すため、必ずその戻り値を確認し、適切にエラー処理を行ってください。

関連コンテンツ

関連IT用語

関連プログラミング言語