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

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

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

作成日: 更新日:

基本的な使い方

sodium_crypto_secretbox_open関数は、共通鍵暗号方式を用いて暗号化されたデータを安全に復号し、そのデータの真正性を検証する関数です。この関数は、事前に共有された秘密鍵と、暗号化時に使用されたノンス(一回限りの乱数値)を受け取り、提供された暗号文を元の平文に戻す処理を実行します。

最も重要な機能の一つとして、単にデータを復号するだけでなく、暗号文が送信中に改ざんされていないか、または不適切な鍵で生成されていないかを厳密に検証する「認証」機能を備えています。これにより、データの完全性と信頼性が保証され、悪意のある改ざんやなりすましから情報を保護することができます。

具体的な使い方としては、復号したい暗号文、それに対応するノンス、そして暗号化と復号で共通に使用する秘密鍵の三つを引数として渡します。復号と認証のプロセスが正常に完了した場合、関数は元の平文データを返します。しかし、もし認証に失敗した場合(例えば、暗号文が改ざんされた場合や、誤った鍵が使用された場合など)、この関数はfalseを返します。これにより、プログラムは安全でないデータを処理することを避け、適切なエラーハンドリングを行うことが可能となります。機密情報の安全な送受信や保存において、この関数は重要な役割を果たします。

構文(syntax)

1<?php
2// 復号する暗号化済みデータ(string)
3$ciphertext = random_bytes(64); // 実際のデータは sodium_crypto_secretbox の出力
4
5// 暗号化時に使用されたノンス(string、SODIUM_CRYPTO_SECRETBOX_NONCEBYTES = 24バイト)
6$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
7
8// 暗号化時に使用された秘密鍵(string、SODIUM_CRYPTO_SECRETBOX_KEYBYTES = 32バイト)
9$key = random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES);
10
11// 構文: sodium_crypto_secretbox_open(string $ciphertext, string $nonce, string $key): string|false
12$decrypted_data = sodium_crypto_secretbox_open($ciphertext, $nonce, $key);
13
14// 戻り値 $decrypted_data は、復号成功時に元のデータ(string)を、失敗時に false を返します。
15?>

引数(parameters)

string $ciphertext, string $nonce, string $key

  • string $ciphertext: 復号化したい暗号化されたデータ(バイト列)
  • string $nonce: 暗号化に使用された、再利用不可能なランダムな値(バイト列)
  • string $key: 暗号化に使用された、秘密鍵(バイト列)

戻り値(return)

string|false

sodium_crypto_secretbox_open 関数は、暗号化されたメッセージを復号化し、元の平文(文字列)を返します。復号化に失敗した場合は false を返します。

サンプルコード

libsodiumで秘密鍵暗号化・復号する

1<?php
2
3/**
4 * libsodiumのsodium_crypto_secretbox_open関数を使用して、メッセージの復号を実演します。
5 * システムエンジニアを目指す初心者向けに、共通鍵暗号の基本的な流れを示します。
6 */
7function demonstrateSecretBoxDecryption(): void
8{
9    // PHP 'sodium' 拡張がロードされているか確認します。
10    // libsodiumはPHP 7.2以降で標準バンドルされており、PHP 8でも利用可能です。
11    if (!extension_loaded('sodium')) {
12        echo "エラー: PHP 'sodium' 拡張がロードされていません。php.iniで有効にしてください。\n";
13        return;
14    }
15
16    // 1. 共通鍵を生成します。この鍵は暗号化と復号の両方で使用され、安全に保管する必要があります。
17    // sodium_crypto_secretbox_keygen() は、適切な長さの安全なランダム鍵を生成します。
18    $key = sodium_crypto_secretbox_keygen();
19
20    // 2. 一度だけ使用されるランダムな値(Nonce: ナンス)を生成します。
21    // ノンスは毎回異なる値を生成する必要があり、同じ鍵とノンスの組み合わせを再利用してはいけません。
22    // SODIUM_CRYPTO_SECRETBOX_NONCEBYTES は、必要なノンスの正確なバイト長を定義しています。
23    $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
24
25    // 3. 暗号化する平文のメッセージを定義します。
26    $originalMessage = 'これは外部に漏らしたくない秘密のデータです。';
27    echo "元のメッセージ: " . $originalMessage . "\n\n";
28
29    // 4. メッセージを共通鍵とノンスで暗号化します。
30    // sodium_crypto_secretbox は、メッセージ、ノンス、鍵を使用して暗号化し、
31    // 認証タグを含む暗号文を返します。これにより、改ざん検出も行われます。
32    $ciphertext = sodium_crypto_secretbox($originalMessage, $nonce, $key);
33    echo "メッセージを暗号化しました。暗号文の長さ: " . strlen($ciphertext) . "バイト\n\n";
34
35    // 5. 暗号化されたメッセージ、元のノンス、元の鍵を使用して復号を試みます。
36    // sodium_crypto_secretbox_open は、暗号文、ノンス、鍵を受け取ります。
37    // 復号と認証が成功した場合は元の平文を返します。
38    // 認証に失敗したり(改ざんを検出した場合など)、復号できない場合は false を返します。
39    $decryptedMessage = sodium_crypto_secretbox_open($ciphertext, $nonce, $key);
40    echo "暗号文を復号しようとしています...\n";
41
42    // 6. 復号結果を確認します。
43    if ($decryptedMessage === false) {
44        echo "エラー: メッセージの復号に失敗しました。鍵、ノンス、または暗号文が不正である可能性があります(例: 改ざん検出)。\n";
45    } else {
46        echo "復号されたメッセージ: " . $decryptedMessage . "\n";
47
48        // 復号されたメッセージが元のメッセージと完全に一致するか検証します。
49        if ($originalMessage === $decryptedMessage) {
50            echo "結果: メッセージは正しく復号され、元の内容と一致しました。\n";
51        } else {
52            echo "警告: 復号されたメッセージが元のメッセージと一致しませんでした。何らかの問題が発生した可能性があります。\n";
53        }
54    }
55}
56
57// 関数を実行して、暗号化と復号のデモンストレーションを開始します。
58demonstrateSecretBoxDecryption();
59
60?>

sodium_crypto_secretbox_open関数は、PHP 8に搭載されているlibsodium拡張機能の一部として、共通鍵暗号方式で暗号化されたデータを復号し、その改ざんがないか検証する際に使用されます。

この関数は以下の3つの引数を取ります。

  1. $ciphertext: sodium_crypto_secretbox関数で生成された暗号文(暗号化されたデータ)です。
  2. $nonce: 暗号化時に使用された一度きりのランダムな値(ノンス)です。セキュリティ上、同じ鍵と同じノンスの再利用は避けてください。
  3. $key: 暗号化と復号の両方で共有される秘密の共通鍵です。この鍵は厳重に管理する必要があります。

戻り値は、復号と認証(データ改ざんの有無の検証)が成功した場合に、元の平文データを文字列として返します。もし、鍵、ノンス、暗号文のいずれかが不正、またはデータが改ざんされていると検出された場合は、falseを返します。

サンプルコードでは、事前に暗号化されたメッセージを、正しいノンスと共通鍵を使ってsodium_crypto_secretbox_open関数で復号しています。これにより、元のメッセージが安全に復号され、共通鍵暗号における復号の仕組みを理解するのに役立ちます。

このサンプルコードを利用する際は、共通鍵を厳重に管理し、他者に漏洩させないでください。ノンス(nonce)は毎回異なる値を生成し、同じ鍵とノンスの組み合わせを二度と使用しないでください。これらが正しく扱われないと、セキュリティが著しく損なわれる可能性があります。sodium_crypto_secretbox_open関数は、復号に失敗したりデータの改ざんが検出されたりした場合にfalseを返しますので、必ずその戻り値をチェックし、falseの場合はエラーとして適切に処理することが重要です。この暗号化機能はPHPのsodium拡張に依存しているため、利用前にPHPの設定で有効になっていることを確認してください。

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

1<?php
2
3/**
4 * PHPのlibsodium拡張機能を使用して、安全な秘密鍵暗号化と復号の例を示します。
5 * sodium_crypto_secretbox はメッセージを暗号化し、
6 * sodium_crypto_secretbox_open はその暗号文を復号します。
7 *
8 * このコードは、PHP 8とlibsodium拡張機能が有効な環境で動作します。
9 */
10
11// 1. 秘密鍵の生成
12// sodium_crypto_secretbox_keygen() は、暗号化と復号の両方に使用される
13// 安全な秘密鍵を生成します。この鍵は厳重に秘密に保つ必要があります。
14$key = sodium_crypto_secretbox_keygen();
15
16// 2. 暗号化する平文のメッセージ
17$originalMessage = "これは非常に機密性の高いメッセージです。誰にも読まれたくない情報。";
18echo "元のメッセージ: " . $originalMessage . "\n";
19
20// 3. ノンス(Nonce)の生成
21// ノンスは暗号化ごとにユニーク(一意)である必要があります。
22// 予測不可能なランダムな値を使用することが非常に重要です。
23// SODIUM_CRYPTO_SECRETBOX_NONCEBYTES は、libsodiumが要求するノンスのバイト数を定義しています。
24$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
25
26// 4. メッセージの暗号化
27// sodium_crypto_secretbox() を使用して、元のメッセージを暗号化します。
28// 引数: $message (string), $nonce (string), $key (string)
29$ciphertext = sodium_crypto_secretbox($originalMessage, $nonce, $key);
30echo "暗号化されたメッセージ (部分表示): " . substr(base64_encode($ciphertext), 0, 30) . "...\n\n";
31
32// 5. メッセージの復号
33// sodium_crypto_secretbox_open() を使用して、暗号文を復号します。
34// 復号には、暗号化時と全く同じ暗号文、ノンス、秘密鍵が必要です。
35// 失敗した場合は false を返します。
36// 引数: $ciphertext (string), $nonce (string), $key (string)
37$decryptedMessage = sodium_crypto_secretbox_open($ciphertext, $nonce, $key);
38
39// 6. 復号結果の確認
40if ($decryptedMessage !== false) {
41    echo "復号されたメッセージ: " . $decryptedMessage . "\n";
42
43    // 復号されたメッセージが元のメッセージと一致するか確認
44    if ($decryptedMessage === $originalMessage) {
45        echo "✅ 復号は成功し、元のメッセージと完全に一致しました。\n";
46    } else {
47        echo "❌ 復号は成功しましたが、元のメッセージと一致しませんでした (データ破損の可能性)。\n";
48    }
49} else {
50    echo "❌ メッセージの復号に失敗しました。\n";
51    echo "提供された鍵、ノンス、または暗号文が正しくない可能性があります。\n";
52}
53
54?>

PHPのsodium_crypto_secretbox_open関数は、libsodium拡張機能が提供する強力な秘密鍵暗号化システムの一部で、sodium_crypto_secretboxによって安全に暗号化されたメッセージを元の状態に戻す(復号する)ために使用されます。システムエンジニアを目指す方にとって、データの機密性を保つための重要な機能です。

この関数は三つの引数を必要とします。一つ目は復号したい暗号文そのものである$ciphertext、二つ目は暗号化時に一度だけ使用されたランダムな値である$nonce(ノンス)、そして三つ目は暗号化と復号の両方に用いられる秘密の鍵$keyです。これら三つの引数は、暗号化時に使用されたものと完全に一致していなければなりません。

復号が成功した場合、この関数は元の平文メッセージをstring型で返します。しかし、もし提供された暗号文、ノンス、または秘密鍵のいずれかが誤っている場合や、暗号文が破損している場合は、復号に失敗しfalseが返されます。これにより、メッセージが正しく復号できたか、あるいは不正なアクセスや改ざんがないかを安全に確認できる仕組みです。高いセキュリティレベルを確保するため、鍵とノンスの厳重な管理が不可欠です。

sodium_crypto_secretbox_open関数で暗号文を復号する際には、暗号化時と完全に一致する暗号文、ノンス、秘密鍵が必要です。特にノンスは、暗号化ごとに必ず異なる予測不可能なランダムな値を使用してください。同じノンスを使い回すと、セキュリティが著しく低下し、情報漏洩のリスクが高まります。秘密鍵は厳重に管理し、絶対に外部に漏洩させてはいけません。復号に失敗した場合、この関数はfalseを返しますので、必ずその戻り値をチェックし、適切にエラー処理を行ってください。これは、暗号文が改ざんされていないかの確認にも役立ちます。この機能を利用するには、PHP環境でlibsodium拡張機能が有効になっている必要があります。

関連コンテンツ

関連プログラミング言語