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

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

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

作成日: 更新日:

基本的な使い方

『sodium_crypto_kx_keypair関数は、鍵交換(Key Exchange)のためのランダムな公開鍵と秘密鍵のペアを生成する関数です。鍵交換とは、通信を行うクライアントとサーバーなどの二者が、安全でない通信路を介して、共通のセッション鍵を安全に確立するための暗号技術です。この関数を呼び出すと、X25519アルゴリズムに基づいた鍵ペアが生成されます。戻り値は1つの文字列ですが、この文字列には秘密鍵と公開鍵の両方が連結された形で含まれています。この戻り値から個別の鍵を取り出すには、sodium_crypto_kx_secretkey()関数で秘密鍵を、sodium_crypto_kx_publickey()関数で公開鍵をそれぞれ抽出する必要があります。生成された鍵ペアは、通信相手と公開鍵を交換したのち、sodium_crypto_kx_client_session_keys()sodium_crypto_kx_server_session_keys()といった関数でセッション鍵を計算するために使用されます。これにより、第三者に知られることなく、両者間で共通の鍵を共有し、その後の通信を暗号化することが可能になります。』

構文(syntax)

1$keypair = sodium_crypto_kx_keypair();

引数(parameters)

引数なし

引数はありません

戻り値(return)

string

この関数は、公開鍵と秘密鍵のペアを生成し、そのペアを連結した文字列として返します。

サンプルコード

PHP Sodium 鍵交換と暗号化デモ

1<?php
2
3declare(strict_types=1);
4
5/**
6 * PHP Sodium 拡張機能における sodium_crypto_kx_keypair の使用例です。
7 *
8 * この関数は、アリスとボブの二者間での鍵交換プロトコルをシミュレートし、
9 * sodium_crypto_kx_keypair で生成した鍵ペアを用いて、安全に共有秘密鍵を導出し、
10 * その鍵を使ってメッセージを暗号化・復号化する一連の流れを示します。
11 *
12 * sodium_crypto_kx_keypair は、キーエクスチェンジ(鍵交換)のための鍵ペアを生成します。
13 * これは、通信相手と安全な共通の秘密鍵を導出するための基盤となります。
14 * 導出された共通鍵は、通常、対称暗号(例: sodium_crypto_secretbox)でメッセージを暗号化するために使用されます。
15 */
16function demonstrateSodiumKeyExchange(): void
17{
18    echo "--- PHP Sodium 鍵交換のデモンストレーション ---" . PHP_EOL . PHP_EOL;
19
20    // 1. アリスとボブがそれぞれ鍵ペアを生成します。
21    // sodium_crypto_kx_keypair は、公開鍵と秘密鍵が結合された鍵ペアを返します。
22    // この鍵ペアは、X25519 鍵交換プロトコルで使用されます。
23    $aliceKeyPair = sodium_crypto_kx_keypair();
24    $bobKeyPair = sodium_crypto_kx_keypair();
25
26    echo "1. 鍵ペアの生成:" . PHP_EOL;
27    echo "   アリスの鍵ペアの長さ: " . strlen($aliceKeyPair) . " バイト" . PHP_EOL;
28    echo "   ボブの鍵ペアの長さ: " . strlen($bobKeyPair) . " バイト" . PHP_EOL . PHP_EOL;
29
30    // 2. 鍵ペアから公開鍵と秘密鍵を抽出します。
31    // 実際に交換されるのは公開鍵のみです。秘密鍵は各当事者のみが保持します。
32    $aliceSecretKey = sodium_crypto_kx_secretkey($aliceKeyPair);
33    $alicePublicKey = sodium_crypto_kx_publickey($aliceKeyPair);
34
35    $bobSecretKey = sodium_crypto_kx_secretkey($bobKeyPair);
36    $bobPublicKey = sodium_crypto_kx_publickey($bobKeyPair);
37
38    echo "2. 公開鍵と秘密鍵の抽出:" . PHP_EOL;
39    echo "   アリスの公開鍵 (交換用): " . bin2hex($alicePublicKey) . PHP_EOL;
40    echo "   ボブの公開鍵 (交換用): " . bin2hex($bobPublicKey) . PHP_EOL . PHP_EOL;
41
42    // 3. アリスとボブが公開鍵を交換し、それぞれ共有秘密鍵を導出します。
43    // クライアント側 (アリス) は自身の鍵ペアと相手 (ボブ) の公開鍵を使用します。
44    $aliceSessionKeys = sodium_crypto_kx_client_session_keys(
45        $aliceKeyPair,  // アリス自身の鍵ペア
46        $bobPublicKey   // ボブの公開鍵
47    );
48    $aliceTx = $aliceSessionKeys[0]; // アリスがボブへ送信するメッセージの暗号化に使用する鍵
49    $aliceRx = $aliceSessionKeys[1]; // アリスがボブから受信するメッセージの復号に使用する鍵
50
51    // サーバー側 (ボブ) は自身の鍵ペアと相手 (アリス) の公開鍵を使用します。
52    $bobSessionKeys = sodium_crypto_kx_server_session_keys(
53        $bobKeyPair,    // ボブ自身の鍵ペア
54        $alicePublicKey // アリスの公開鍵
55    );
56    $bobTx = $bobSessionKeys[0]; // ボブがアリスへ送信するメッセージの暗号化に使用する鍵
57    $bobRx = $bobSessionKeys[1]; // ボブがアリスから受信するメッセージの復号に使用する鍵
58
59    echo "3. 共有秘密鍵の導出:" . PHP_EOL;
60    echo "   アリスの送信鍵 (Tx) の長さ: " . strlen($aliceTx) . " バイト" . PHP_EOL;
61    echo "   アリスの受信鍵 (Rx) の長さ: " . strlen($aliceRx) . " バイト" . PHP_EOL;
62    echo "   ボブの送信鍵 (Tx) の長さ: " . strlen($bobTx) . " バイト" . PHP_EOL;
63    echo "   ボブの受信鍵 (Rx) の長さ: " . strlen($bobRx) . " バイト" . PHP_EOL . PHP_EOL;
64
65    // 導出された鍵が正しく一致するか確認します。
66    // アリスの送信鍵はボブの受信鍵と、アリスの受信鍵はボブの送信鍵と一致するはずです。
67    if ($aliceTx === $bobRx && $aliceRx === $bobTx) {
68        echo "   => 鍵交換は成功しました。アリスとボブは安全な通信を開始できます。" . PHP_EOL . PHP_EOL;
69    } else {
70        echo "   => エラー: 鍵交換が正しく行われませんでした。共有秘密鍵が一致しません。" . PHP_EOL . PHP_EOL;
71        return; // エラーの場合はここで終了
72    }
73
74    // 4. 導出した共有秘密鍵を使用してメッセージを暗号化・復号化します。
75    // 通常、対称暗号関数 (例: sodium_crypto_secretbox) を使用します。
76
77    // アリスからボブへのメッセージ
78    $messageFromAlice = "こんにちは、ボブ!アリスからの秘密のメッセージです。";
79    // メッセージごとにユニークなナンス (Nonce) を生成します。
80    $nonceForAliceToBob = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
81
82    // アリスがメッセージを暗号化 (自身の送信鍵 $aliceTx を使用)
83    $encryptedMessageByAlice = sodium_crypto_secretbox($messageFromAlice, $nonceForAliceToBob, $aliceTx);
84
85    echo "4. メッセージの暗号化と復号化 (アリス -> ボブ):" . PHP_EOL;
86    echo "   アリスの元のメッセージ: \"" . $messageFromAlice . "\"" . PHP_EOL;
87    echo "   暗号化されたメッセージの長さ: " . strlen($encryptedMessageByAlice) . " バイト" . PHP_EOL;
88
89    // ボブがメッセージを復号化 (自身の受信鍵 $bobRx と同じナンスを使用)
90    try {
91        $decryptedMessageByBob = sodium_crypto_secretbox_open($encryptedMessageByAlice, $nonceForAliceToBob, $bobRx);
92        echo "   ボブが復号したメッセージ: \"" . $decryptedMessageByBob . "\"" . PHP_EOL;
93    } catch (SodiumException $e) {
94        echo "   メッセージの復号に失敗しました (ボブ): " . $e->getMessage() . PHP_EOL;
95    }
96
97    echo PHP_EOL;
98
99    // ボブからアリスへのメッセージ
100    $messageFromBob = "アリス、私も秘密を共有します。ボブより。";
101    $nonceForBobToAlice = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
102
103    // ボブがメッセージを暗号化 (自身の送信鍵 $bobTx を使用)
104    $encryptedMessageByBob = sodium_crypto_secretbox($messageFromBob, $nonceForBobToAlice, $bobTx);
105
106    echo "5. メッセージの暗号化と復号化 (ボブ -> アリス):" . PHP_EOL;
107    echo "   ボブの元のメッセージ: \"" . $messageFromBob . "\"" . PHP_EOL;
108    echo "   暗号化されたメッセージの長さ: " . strlen($encryptedMessageByBob) . " バイト" . PHP_EOL;
109
110    // アリスがメッセージを復号化 (自身の受信鍵 $aliceRx と同じナンスを使用)
111    try {
112        $decryptedMessageByAlice = sodium_crypto_secretbox_open($encryptedMessageByBob, $nonceForBobToAlice, $aliceRx);
113        echo "   アリスが復号したメッセージ: \"" . $decryptedMessageByAlice . "\"" . PHP_EOL;
114    } catch (SodiumException $e) {
115        echo "   メッセージの復号に失敗しました (アリス): " . $e->getMessage() . PHP_EOL;
116    }
117
118    echo PHP_EOL . "--- デモンストレーション終了 ---" . PHP_EOL;
119}
120
121// デモンストレーションを実行します。
122demonstrateSodiumKeyExchange();
123
124?>

PHPのsodium_crypto_kx_keypair関数は、安全な鍵交換プロトコルで使用される鍵ペアを生成します。この関数は引数を取らず、公開鍵と秘密鍵が結合された形式の文字列を戻り値として返します。生成された鍵ペアは、通信する二者間(例えばアリスとボブ)で、安全な共通の秘密鍵を導出するための基盤となります。

具体的には、生成された鍵ペアからsodium_crypto_kx_publickey関数で公開鍵を抽出し、通信相手に安全でないチャネルを介して渡します。その後、自身の鍵ペアと相手から受け取った公開鍵を用いて、sodium_crypto_kx_client_session_keyssodium_crypto_kx_server_session_keys関数を使い、メッセージの送受信にそれぞれ使用する共有秘密鍵を導出します。この導出された共有秘密鍵は、sodium_crypto_secretboxなどの対称暗号関数を用いて、メッセージの暗号化や復号化を行うために利用され、これにより安全な通信が実現されます。

sodium_crypto_kx_keypairは、安全な鍵交換プロトコルに必要な鍵ペアを生成する関数です。この関数が生成する秘密鍵は、決して通信相手と共有せず厳重に保管してください。公開鍵のみを交換し、sodium_crypto_kx_client_session_keyssodium_crypto_kx_server_session_keysを使って共有秘密鍵を導出します。メッセージの暗号化には、導出した送信鍵(Tx)と受信鍵(Rx)を適切に使い分け、sodium_crypto_secretboxなどの対称暗号関数を利用します。特に、暗号化の際にはメッセージごとに異なるユニークなナンス(Nonce)を必ず生成し、使い回さないよう注意してください。これらの機能はPHPのSodium拡張機能が有効な環境でのみ利用可能です。エラー発生時にはSodiumExceptionで捕捉し、適切に処理することが重要です。

libsodium 鍵交換用鍵ペアを生成する

1<?php
2
3/**
4 * libsodiumの鍵交換(Key Exchange)用鍵ペアを生成し、その情報を表示する関数です。
5 *
6 * sodium_crypto_kx_keypair() は、秘密鍵と公開鍵を含む鍵ペアを生成します。
7 * この関数は引数を取らず、string型のバイナリデータを返します。
8 * 生成された鍵ペアから、個別に秘密鍵と公開鍵を抽出することも可能です。
9 *
10 * 注: このコードはPHP 8で動作し、PHPのSodium拡張が有効になっている必要があります。
11 * Sodium拡張が有効でない場合、関数が見つからない旨のエラーが発生します。
12 */
13function generateKeyExchangeKeyPair(): void
14{
15    echo "--- libsodium 鍵交換(Key Exchange)用鍵ペアの生成と情報表示 ---\n\n";
16
17    // 鍵交換用の新しい鍵ペアを生成します。
18    // 戻り値は秘密鍵と公開鍵が結合されたバイナリ文字列です。
19    $keyPair = sodium_crypto_kx_keypair();
20    echo "生成された鍵ペア (バイナリを16進数で表示): " . bin2hex($keyPair) . "\n";
21    echo "鍵ペアの長さ: " . strlen($keyPair) . " バイト\n\n";
22
23    // 生成された鍵ペアから秘密鍵を抽出します。
24    $secretKey = sodium_crypto_kx_secretkey($keyPair);
25    echo "抽出された秘密鍵 (バイナリを16進数で表示): " . bin2hex($secretKey) . "\n";
26    echo "秘密鍵の長さ: " . strlen($secretKey) . " バイト\n\n";
27
28    // 生成された鍵ペアから公開鍵を抽出します。
29    $publicKey = sodium_crypto_kx_publickey($keyPair);
30    echo "抽出された公開鍵 (バイナリを16進数で表示): " . bin2hex($publicKey) . "\n";
31    echo "公開鍵の長さ: " . strlen($publicKey) . " バイト\n\n";
32
33    echo "--- 鍵ペアの生成と情報表示が完了しました ---\n";
34}
35
36// 関数を実行して、鍵ペアの生成と情報を表示します。
37generateKeyExchangeKeyPair();
38
39?>

sodium_crypto_kx_keypair関数は、セキュアな通信で利用される「鍵交換(Key Exchange)」のための鍵ペアを生成します。この関数は引数を取らず、秘密鍵と公開鍵が結合されたバイナリ形式の文字列を戻り値として返します。生成された鍵ペアは、通信相手との間で安全な共通鍵を導出する際に用いられる重要な要素です。

サンプルコードでは、最初にsodium_crypto_kx_keypairを呼び出して新しい鍵ペアを生成しています。戻り値は一つのバイナリ文字列ですが、この中には秘密鍵と公開鍵の両方が含まれています。その後、sodium_crypto_kx_secretkey関数を使って生成された鍵ペアから秘密鍵を、sodium_crypto_kx_publickey関数を使って公開鍵をそれぞれ抽出しています。これにより、個別の鍵を安全に管理したり、通信相手と交換したりすることが可能になります。

生成された鍵や抽出された鍵はバイナリデータであるため、サンプルコードではbin2hex関数を用いて人間が読みやすい16進数形式に変換して表示しています。また、strlen関数でそれぞれの鍵の長さを確認し、その構造を理解するのに役立てています。この関数を利用するには、PHP環境でSodium拡張が有効になっている必要があります。

PHPのSodium拡張がサーバーにインストールされ、有効になっていることが必須です。有効でない場合、関数が未定義である旨のエラーが発生します。 sodium_crypto_kx_keypair()が返す値は、秘密鍵と公開鍵が結合されたバイナリデータです。このデータを直接表示すると文字化けするため、bin2hex関数で16進数に変換して内容を確認してください。 鍵ペアから秘密鍵や公開鍵を個別に抽出するには、sodium_crypto_kx_secretkey()sodium_crypto_kx_publickey()を必ず使用します。 生成された秘密鍵は極めて機密性が高く、外部への漏洩は絶対にあってはなりません。厳重な管理を徹底してください。 この関数は鍵交換用途の鍵ペアを生成するものであり、電子署名用途の鍵ペアとは目的が異なります。

関連コンテンツ

関連プログラミング言語