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

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

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

作成日: 更新日:

基本的な使い方

sodium_crypto_box_open関数は、暗号化されたメッセージを復号化するためにPHPで利用される重要な関数です。この関数は、Libsodiumライブラリが提供する堅牢な暗号化機能の一部として、安全なデータ通信を実現するために設計されています。具体的には、sodium_crypto_box関数によって暗号化されたメッセージを、受信者の秘密鍵と送信者の公開鍵を使用して元の平文に戻す役割を果たします。

この関数は、通信の「機密性」と「認証」の両方を提供します。機密性とは、メッセージの内容が第三者には読めないようにすること、認証とは、メッセージが本物の送信者から送られ、途中で改ざんされていないことを確認することです。

sodium_crypto_box_open関数を使用するには、いくつかの情報が必要です。まず、復号化したい「暗号文」そのもの、次に、暗号化時に一度だけ使用された「ナンス」(Nonceと呼ばれる使い捨ての数値)、そして「受信者の秘密鍵」と「送信者の公開鍵」が必要です。ナンスはセキュリティ上非常に重要であり、同じ鍵ペアで同じナンスを二度と使用してはいけません。

関数が正常に実行されると、復号化された元のメッセージ(平文)が文字列として返されます。もし復号化に失敗した場合や、メッセージが改ざんされていると検出された場合は、falseが返されます。システムエンジニアを目指す上では、このような暗号化・復号化の仕組みを理解し、鍵の管理やナンスの適切な利用に細心の注意を払うことが不可欠です。

構文(syntax)

1<?php
2$plaintext = sodium_crypto_box_open($ciphertext, $nonce, $keypair);
3?>

引数(parameters)

string $ciphertext, string $nonce, string $key_pair

  • string $ciphertext: 復号化する暗号文を指定する文字列
  • string $nonce: 暗号化に使用されたナンス(一度しか使用されないランダムな値)を指定する文字列
  • string $key_pair: 復号化に使用する秘密鍵を含む、鍵ペアを指定する文字列

戻り値(return)

string|false

成功した場合、復号化されたデータ(文字列)を返します。失敗した場合はfalseを返します。

サンプルコード

PHP Sodium: sodium_crypto_box_openで復号化する

1<?php
2
3// Sodium拡張機能が利用可能か確認
4if (!extension_loaded('sodium')) {
5    echo "PHP Sodium拡張機能がインストールされていません。\n";
6    exit(1);
7}
8
9/**
10 * PHP Sodiumライブラリを使用して、メッセージの暗号化と復号化を行うサンプル。
11 *
12 * sodium_crypto_box_open は、sodium_crypto_box で暗号化されたメッセージを復号化します。
13 * これは公開鍵暗号方式で、送信者と受信者が互いの公開鍵を知っている必要があります。
14 */
15
16// 1. 鍵ペアの生成
17// 送信者(例: Alice)の鍵ペアを生成
18$alice_keypair = sodium_crypto_box_keypair();
19$alice_public_key = sodium_crypto_box_publickey($alice_keypair);
20$alice_secret_key = sodium_crypto_box_secretkey($alice_keypair);
21
22// 受信者(例: Bob)の鍵ペアを生成
23$bob_keypair = sodium_crypto_box_keypair();
24$bob_public_key = sodium_crypto_box_publickey($bob_keypair);
25$bob_secret_key = sodium_crypto_box_secretkey($bob_keypair);
26
27echo "鍵ペアの生成が完了しました。\n";
28
29// 2. 送信するメッセージを準備
30$original_message = "Hello, Bob! This is a secret message from Alice.";
31echo "オリジナルメッセージ: " . $original_message . "\n";
32
33// 3. 送信者(Alice)が受信者(Bob)宛にメッセージを暗号化
34// 暗号化には、Aliceの秘密鍵とBobの公開鍵を使用します。
35// また、各暗号化ごとにユニークなワンタイムナンス (Nonce) が必要です。
36$nonce = random_bytes(SODIUM_CRYPTO_BOX_NONCEBYTES); // ノンスはランダムに生成
37$sender_box_keypair = sodium_crypto_box_keypair_from_secretkey_and_publickey(
38    $alice_secret_key,
39    $bob_public_key
40);
41
42$encrypted_message = sodium_crypto_box(
43    $original_message,
44    $nonce,
45    $sender_box_keypair
46);
47
48if ($encrypted_message === false) {
49    echo "エラー: メッセージの暗号化に失敗しました。\n";
50    exit(1);
51}
52echo "メッセージが暗号化されました。\n";
53
54// 暗号化されたメッセージとnonceは受信者(Bob)に送信されると仮定します。
55// 例: echo "暗号化されたメッセージ (Hex): " . bin2hex($encrypted_message) . "\n";
56// 例: echo "ノンス (Hex): " . bin2hex($nonce) . "\n";
57
58
59// 4. 受信者(Bob)がメッセージを復号化
60// 復号化には、Bobの秘密鍵とAliceの公開鍵、そして暗号化に使用された同じnonceを使用します。
61$receiver_box_keypair = sodium_crypto_box_keypair_from_secretkey_and_publickey(
62    $bob_secret_key,
63    $alice_public_key
64);
65
66$decrypted_message = sodium_crypto_box_open(
67    $encrypted_message,
68    $nonce,
69    $receiver_box_keypair
70);
71
72if ($decrypted_message === false) {
73    echo "エラー: メッセージの復号化に失敗しました。\n";
74    echo "これは、暗号文、ノンス、または鍵ペアのいずれかが正しくないことを示唆しています。\n";
75} else {
76    echo "メッセージが復号化されました。\n";
77    echo "復号化されたメッセージ: " . $decrypted_message . "\n";
78
79    // オリジナルメッセージと復号化されたメッセージが一致するか確認
80    if ($original_message === $decrypted_message) {
81        echo "検証成功: 復号化されたメッセージはオリジナルと一致します。\n";
82    } else {
83        echo "検証失敗: 復号化されたメッセージがオリジナルと一致しません。\n";
84    }
85}
86
87?>

sodium_crypto_box_open関数は、PHPのSodium拡張機能が提供する公開鍵暗号方式の復号化機能です。この関数は、sodium_crypto_box関数によって暗号化されたメッセージを、元の平文に戻すために使用されます。

この関数は三つの引数を取ります。一つ目は暗号化されたデータである$ciphertext、二つ目は暗号化時に使用された一度だけ使う数値である$nonceです。$nonceは、暗号化と復号化の両方で全く同じ値が使われる必要があります。三つ目は$key_pairで、これはメッセージを受信する側の秘密鍵と、送信した側の公開鍵を組み合わせて生成された鍵ペアを指定します。

処理が成功すると、復号化されたstring型のメッセージが返されます。もし、$ciphertext$nonce、または$key_pairのいずれかが正しくないなどの理由で復号化に失敗した場合は、falseが返されます。

サンプルコードでは、まず「Alice」と「Bob」がそれぞれ公開鍵と秘密鍵のペアを生成します。次に、AliceがBob宛のメッセージを、自身の秘密鍵とBobの公開鍵、そして一意のnonceを使ってsodium_crypto_box関数で暗号化します。最後に、Bobが受け取った暗号化されたメッセージとnonce、そして自身の秘密鍵とAliceの公開鍵を使ってsodium_crypto_box_open関数で復号化し、元のメッセージを安全に取得する一連の通信プロセスを示しています。これにより、安全なメッセージのやり取りが実現できます。

sodium_crypto_box_open関数を利用するには、PHP Sodium拡張機能がサーバーにインストールされている必要があります。この関数は公開鍵暗号方式の復号化に用いられ、暗号化に使用した送信者の公開鍵と受信者の秘密鍵を組み合わせた鍵ペア、そして暗号化時に使用された全く同じノンス(Nonce)が必要です。特に、ノンスは暗号化ごとに一意でなければならず、再利用するとセキュリティ上の脆弱性が生じるため厳重に注意してください。復号化が成功すると元のメッセージを返しますが、失敗した場合はfalseを返しますので、必ず戻り値を検証し、エラー処理を実装することが重要です。秘密鍵はシステム内で厳重に管理し、決して外部に公開しないでください。

PHP Sodium: 暗号化メッセージを復号する

1<?php
2
3// Sodium拡張が利用可能か確認します
4if (!extension_loaded('sodium')) {
5    die('Sodium拡張がロードされていません。PHP設定で有効にしてください。');
6}
7
8/**
9 * sodium_crypto_box_open 関数を使った非対称暗号化のデモンストレーション。
10 * 送信者が受信者向けにメッセージを暗号化し、受信者がそれを復号するシナリオをシミュレートします。
11 */
12function demonstrateSodiumCryptoBoxOpen(): void
13{
14    echo "--- Sodium Crypto Box Open デモンストレーション ---" . PHP_EOL . PHP_EOL;
15
16    // 1. 送信者と受信者の鍵ペアを生成
17    // 実際のアプリケーションでは、これらの鍵ペアは一度生成され、安全に保管されます。
18    // 公開鍵は交換されます。
19    $senderKeyPair = sodium_crypto_box_keypair();
20    $receiverKeyPair = sodium_crypto_box_keypair();
21
22    // 鍵ペアから公開鍵と秘密鍵を抽出
23    $senderPublicKey = sodium_crypto_box_publickey($senderKeyPair);
24    $senderSecretKey = sodium_crypto_box_secretkey($senderKeyPair);
25
26    $receiverPublicKey = sodium_crypto_box_publickey($receiverKeyPair);
27    $receiverSecretKey = sodium_crypto_box_secretkey($receiverKeyPair);
28
29    echo "生成された送信者の公開鍵 (Hex): " . bin2hex($senderPublicKey) . PHP_EOL;
30    echo "生成された受信者の公開鍵 (Hex): " . bin2hex($receiverPublicKey) . PHP_EOL . PHP_EOL;
31
32    // 2. 送信者が受信者向けにメッセージを暗号化
33    $originalMessage = "こんにちは、受信者への秘密のメッセージです!";
34    echo "元のメッセージ: " . $originalMessage . PHP_EOL;
35
36    // 暗号化のための安全なランダムなnonceを生成
37    // NONCE_BYTES は sodium_crypto_box で推奨されるnonceのサイズです。
38    $nonce = random_bytes(SODIUM_CRYPTO_BOX_NONCEBYTES);
39
40    // 受信者の公開鍵と送信者の秘密鍵を使ってメッセージを暗号化
41    $ciphertext = sodium_crypto_box($originalMessage, $nonce, $receiverPublicKey, $senderSecretKey);
42
43    echo "Nonce (Hex): " . bin2hex($nonce) . PHP_EOL;
44    echo "暗号化されたデータ (Ciphertext) (Hex): " . bin2hex($ciphertext) . PHP_EOL . PHP_EOL;
45
46    // 3. 受信者がメッセージを復号
47    // 受信者が必要とするもの:
48    // - 暗号化されたデータ (Ciphertext)
49    // - Nonce (Ciphertextと一緒に送信される)
50    // - 送信者の公開鍵 (受信者が知っている)
51    // - 受信者自身の秘密鍵 (受信者のみが知っている)
52
53    // sodium_crypto_box_open のための "key_pair" 引数を作成
54    // これは受信者の秘密鍵と送信者の公開鍵を連結したものです。
55    $decryptionKeyPair = $receiverSecretKey . $senderPublicKey;
56
57    echo "メッセージの復号を試みます..." . PHP_EOL;
58    $decryptedMessage = sodium_crypto_box_open($ciphertext, $nonce, $decryptionKeyPair);
59
60    if ($decryptedMessage === false) {
61        echo "復号に失敗しました!メッセージが改ざんされたか、鍵/nonceが正しくありません。" . PHP_EOL;
62    } else {
63        echo "復号に成功しました!" . PHP_EOL;
64        echo "復号されたメッセージ: " . $decryptedMessage . PHP_EOL;
65    }
66
67    echo PHP_EOL . "--- デモンストレーション終了 ---" . PHP_EOL;
68}
69
70// デモンストレーションを実行
71demonstrateSodiumCryptoBoxOpen();

PHPのsodium_crypto_box_open関数は、公開鍵暗号(非対称暗号)の仕組みを利用して、暗号化されたメッセージを安全に元の状態へ戻すために使用されます。この方式では、メッセージの送信者が受信者の公開鍵と自身の秘密鍵でデータを暗号化し、受信者は自身の秘密鍵と送信者の公開鍵を使って復号を行います。これにより、メッセージの内容が外部に漏れることなく、かつ途中で改ざんされていないことを検証できます。

引数として、まず$ciphertextに暗号化されたメッセージ本体を指定します。次に$nonceには、暗号化時に一度だけ使われた一意の数値(ナンス)を渡します。そして最も重要な$key_pairには、メッセージを復号する側の秘密鍵と、メッセージを暗号化した送信者側の公開鍵を連結したものを渡す必要があります。

関数は、復号に成功すれば元のメッセージを文字列として返します。しかし、メッセージが途中で改ざんされた場合や、鍵、あるいはナンスが正しくない場合には、復号に失敗したことを示すfalseを返します。サンプルコードでは、これらの鍵の生成からメッセージの暗号化、そしてsodium_crypto_box_openによる復号までの一連の流れを実践的に示しています。

この関数は、非対称暗号化(公開鍵暗号)の復号に利用されます。まず、PHPのSodium拡張が有効であることを確認してください。秘密鍵は絶対に漏洩しないよう厳重に管理し、公開鍵は共有しても安全です。暗号化時に使用したnonce(ノンス)は毎回異なるランダムな値を生成し、暗号文と共に受信者に安全に渡す必要があります。特に、sodium_crypto_box_open$key_pair引数は、復号する側の秘密鍵と暗号化に使用された送信者の公開鍵を連結したものである点に注意してください。復号に失敗した場合はfalseを返すため、必ず戻り値を確認しエラー処理を行うことが重要です。

関連コンテンツ

関連IT用語

関連プログラミング言語