【PHP8.x】sodium_crypto_kx_secretkey()関数の使い方
sodium_crypto_kx_secretkey関数の使い方について、初心者にもわかりやすく解説します。
基本的な使い方
sodium_crypto_kx_secretkey関数は、鍵交換(Key Exchange)用のキーペアから秘密鍵を抽出する関数です。鍵交換とは、クライアントとサーバーなどの二者間で安全な通信を行うために、共通のセッションキーを安全に生成するための暗号技術です。この関数は、事前にsodium_crypto_kx_keypair関数で生成された、公開鍵と秘密鍵が結合されたキーペア文字列を引数として受け取ります。そのキーペアから秘密鍵の部分だけを分離し、文字列として返します。ここで返される秘密鍵は、所有者だけが保持すべき非常に重要な情報であり、絶対に第三者に知られてはなりません。この秘密鍵は、通信相手の公開鍵と組み合わせることで、共有セッションキーを計算するために使用されます。具体的には、クライアント側ではsodium_crypto_kx_client_session_keys関数、サーバー側ではsodium_crypto_kx_server_session_keys関数で、それぞれの秘密鍵が必要となります。この一連の処理によって、安全な通信チャネルを確立することが可能になります。
構文(syntax)
1<?php 2 3// キーペアから秘密鍵を抽出します。 4// $key_pair には、sodium_crypto_kx_keypair() で生成されたキーペアを指定します。 5$secret_key = sodium_crypto_kx_secretkey($key_pair); 6 7?>
引数(parameters)
string $key_pair
- string $key_pair: 認証局(CA)が発行した公開鍵と秘密鍵のペア。このペアは、
sodium_crypto_kx_keypair()関数で生成されたものを使用します。
戻り値(return)
string|false
この関数は、安全な鍵交換(KX)プロトコルで使用する秘密鍵を生成します。成功した場合は秘密鍵を文字列として返しますが、生成に失敗した場合は false を返します。
サンプルコード
PHP Sodium: 鍵交換とsecretbox暗号化
1<?php 2 3/** 4 * プログラミング言語の専門家からのPHPサンプルコード 5 * 6 * このコードは、システムエンジニアを目指す初心者向けに、 7 * libsodium (PHPのSodium拡張) を使った安全な鍵交換 (Key Exchange: KX) と 8 * 対称鍵暗号 (Symmetric Encryption) のデモンストレーションです。 9 * 10 * 主に sodium_crypto_kx_secretkey 関数と、関連キーワードである 11 * sodium_crypto_secretbox を用いたメッセージの暗号化・復号化を示します。 12 */ 13 14/** 15 * 安全な通信プロセス(鍵交換とメッセージ暗号化)を実演します。 16 */ 17function demonstrateSecureCommunication(): void 18{ 19 // Sodium拡張がロードされているか確認します。 20 if (!extension_loaded('sodium')) { 21 echo "エラー: 'sodium' 拡張がロードされていません。php.iniで有効にしてください。" . PHP_EOL; 22 exit(1); 23 } 24 25 echo "--- 鍵ペアの生成 ---" . PHP_EOL; 26 27 // 1. クライアントとサーバーそれぞれの鍵ペアを生成します。 28 // 鍵ペアは公開鍵と秘密鍵の両方を含みます。 29 $clientKeyPair = sodium_crypto_kx_keypair(); 30 $serverKeyPair = sodium_crypto_kx_keypair(); 31 32 // 2. 鍵ペアから公開鍵と秘密鍵を抽出します。 33 // sodium_crypto_kx_secretkey は鍵ペアから秘密鍵を抽出するために使用されます。 34 // この秘密鍵は、鍵交換プロセスでセッション鍵を導出するために不可欠です。 35 $clientSecretKey = sodium_crypto_kx_secretkey($clientKeyPair); 36 $clientPublicKey = sodium_crypto_kx_publickey($clientKeyPair); 37 38 $serverSecretKey = sodium_crypto_kx_secretkey($serverKeyPair); 39 $serverPublicKey = sodium_crypto_kx_publickey($serverKeyPair); 40 41 echo "クライアント公開鍵: " . bin2hex($clientPublicKey) . PHP_EOL; 42 echo "サーバー公開鍵: " . bin2hex($serverPublicKey) . PHP_EOL; 43 // 注意: 秘密鍵は機密情報であり、決してログに出力したり、外部に公開したりしないでください。 44 // echo "クライアント秘密鍵: " . bin2hex($clientSecretKey) . PHP_EOL; 45 46 echo PHP_EOL . "--- 鍵交換による共有セッション鍵の導出 ---" . PHP_EOL; 47 48 // 3. 鍵交換 (Key Exchange: KX) を実行して、共有セッション鍵を導出します。 49 // クライアントは自身の鍵ペアとサーバーの公開鍵を使ってセッション鍵を導出します。 50 $clientSessionKeys = sodium_crypto_kx_client_session_keys($clientKeyPair, $serverPublicKey); 51 52 // サーバーは自身の鍵ペアとクライアントの公開鍵を使ってセッション鍵を導出します。 53 $serverSessionKeys = sodium_crypto_kx_server_session_keys($serverKeyPair, $clientPublicKey); 54 55 // 導出されたセッション鍵が両者で一致することを確認します。 56 // クライアントの送信 (tx) 鍵は、サーバーの受信 (rx) 鍵と一致するはずです。 57 if ($clientSessionKeys['tx'] !== $serverSessionKeys['rx']) { 58 throw new Exception("エラー: クライアントの送信鍵がサーバーの受信鍵と一致しません。"); 59 } 60 // サーバーの送信 (tx) 鍵は、クライアントの受信 (rx) 鍵と一致するはずです。 61 if ($clientSessionKeys['rx'] !== $serverSessionKeys['tx']) { 62 throw new Exception("エラー: サーバーの送信鍵がクライアントの受信鍵と一致しません。"); 63 } 64 65 $sharedKeyClientToServer = $clientSessionKeys['tx']; // クライアントがサーバーへ送るメッセージを暗号化する鍵 66 $sharedKeyServerToClient = $serverSessionKeys['tx']; // サーバーがクライアントへ送るメッセージを暗号化する鍵 67 68 echo "クライアントからサーバーへの共有鍵: " . bin2hex($sharedKeyClientToServer) . PHP_EOL; 69 echo "サーバーからクライアントへの共有鍵: " . bin2hex($sharedKeyServerToClient) . PHP_EOL; 70 71 echo PHP_EOL . "--- 共有鍵を使ったメッセージの暗号化と復号化 (sodium_crypto_secretbox) ---" . PHP_EOL; 72 73 // 4. 導出した共有鍵を使用して、対称鍵暗号 (sodium_crypto_secretbox) でメッセージを暗号化・復号化します。 74 $originalMessage = "こんにちは、安全な世界!クライアントからサーバーへの秘密のメッセージです。"; 75 echo "元のメッセージ: " . $originalMessage . PHP_EOL; 76 77 // 暗号化に使用する一回限りの乱数 (nonce) を生成します。 78 // ノンスは、同じ鍵で暗号化するメッセージごとに一意である必要があります。 79 $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); 80 81 // 共有鍵を使ってメッセージを暗号化します。 82 $encryptedMessage = sodium_crypto_secretbox($originalMessage, $nonce, $sharedKeyClientToServer); 83 echo "暗号化されたメッセージ (hex): " . bin2hex($encryptedMessage) . PHP_EOL; 84 85 // 同じ共有鍵とノンスを使ってメッセージを復号化します。 86 $decryptedMessage = sodium_crypto_secretbox_open($encryptedMessage, $nonce, $sharedKeyClientToServer); 87 88 if ($decryptedMessage === false) { 89 throw new Exception("復号化に失敗しました!"); 90 } 91 92 echo "復号化されたメッセージ: " . $decryptedMessage . PHP_EOL; 93 94 if ($originalMessage === $decryptedMessage) { 95 echo "-> 暗号化と復号化が成功しました!" . PHP_EOL; 96 } else { 97 echo "-> エラー: 復号化されたメッセージが元のメッセージと一致しません。" . PHP_EOL; 98 } 99 100 echo PHP_EOL . "--- サーバーからクライアントへの返信 ---" . PHP_EOL; 101 102 // サーバーからクライアントへのメッセージ送信の例 103 $responseMessage = "サーバーからクライアントへの安全な返信です。"; 104 echo "元の返信メッセージ: " . $responseMessage . PHP_EOL; 105 $responseNonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); 106 $encryptedResponse = sodium_crypto_secretbox($responseMessage, $responseNonce, $sharedKeyServerToClient); 107 echo "暗号化された返信 (hex): " . bin2hex($encryptedResponse) . PHP_EOL; 108 $decryptedResponse = sodium_crypto_secretbox_open($encryptedResponse, $responseNonce, $sharedKeyServerToClient); 109 110 if ($decryptedResponse === false) { 111 throw new Exception("返信の復号化に失敗しました!"); 112 } 113 echo "復号化された返信: " . $decryptedResponse . PHP_EOL; 114 115 if ($responseMessage === $decryptedResponse) { 116 echo "-> 返信の暗号化と復号化が成功しました!" . PHP_EOL; 117 } else { 118 echo "-> エラー: 復号化された返信が元のメッセージと一致しません。" . PHP_EOL; 119 } 120} 121 122// デモンストレーションを実行します。 123demonstrateSecureCommunication();
PHPのsodium_crypto_kx_secretkey関数は、鍵交換プロトコルに用いる鍵ペアから「秘密鍵」の部分だけを安全に抽出する関数です。引数には、事前にsodium_crypto_kx_keypair()などで生成された鍵ペア全体を表す文字列(string $key_pair)を渡します。成功した場合は秘密鍵のバイナリデータを含む文字列(string)を返し、処理が失敗した場合はfalseを返します。
このサンプルコードでは、まずクライアントとサーバーがそれぞれ鍵ペアを生成し、本関数を用いてそこから個々の秘密鍵を抽出します。そして、公開鍵と組み合わせてsodium_crypto_kx_client_session_keysやsodium_crypto_kx_server_session_keysにより、クライアントとサーバー間で「共有セッション鍵」を安全に導出します。最終的に、この共有セッション鍵をsodium_crypto_secretbox関数と組み合わせて、送受信するメッセージを暗号化・復号化することで、安全な通信が実現される様子を示しています。これにより、第三者に内容を知られることなく、機密性の高い情報をやり取りできるようになります。
sodium_crypto_kx_secretkeyは鍵ペアから秘密鍵を安全に抽出する関数です。抽出した秘密鍵は極めて機密性が高く、決して外部に公開したり、ログに出力したりしないでください。この秘密鍵は、相手の公開鍵と組み合わせて安全に共有セッション鍵を導出するために利用されます。sodium_crypto_secretboxでメッセージを暗号化・復号化する際は、この共有セッション鍵と、メッセージごとに必ず一意なノンス(nonce)を生成して使用してください。同じ鍵で複数のメッセージを暗号化する場合でもノンスの再利用は避けるべきです。コードを実行する前にPHPのSodium拡張が有効になっていることを必ず確認してください。また、復号化が失敗した場合はfalseが返されるため、そのチェックを忘れないでください。
PHP Sodium: KX秘密鍵を抽出する
1<?php 2 3/** 4 * PHP Sodium extensionを使い、Key Exchange (KX) の秘密鍵を抽出する方法をデモンストレーションします。 5 * また、関連キーワードである sodium_crypto_box における秘密鍵の扱いついての文脈も提供します。 6 * 7 * システムエンジニアを目指す初心者にも理解しやすいように、正確かつ簡潔なコードです。 8 */ 9function demonstrateSodiumKeyExtraction(): void 10{ 11 // Sodium拡張が有効か確認します。PHPの暗号化機能を使用するために必要です。 12 if (!extension_loaded('sodium')) { 13 echo 'Error: Sodium拡張がロードされていません。php.iniで有効にしてください。' . PHP_EOL; 14 return; 15 } 16 17 echo "--- sodium_crypto_kx_secretkey のデモンストレーション ---" . PHP_EOL; 18 19 // 1. Key Exchange (KX) 用の鍵ペアを生成します。 20 // この鍵ペアは、2者間で安全に共通の秘密鍵を確立するために特化しています。 21 $kxKeyPair = sodium_crypto_kx_keypair(); 22 echo '生成されたKX鍵ペアの全長: ' . strlen($kxKeyPair) . ' バイト' . PHP_EOL; 23 24 // 2. sodium_crypto_kx_secretkey を使用して、KX鍵ペアから秘密鍵を抽出します。 25 // この関数は、完全な鍵ペアからプライベート(秘密)部分のみを取り出します。 26 $kxSecretKey = sodium_crypto_kx_secretkey($kxKeyPair); 27 28 if ($kxSecretKey === false) { 29 echo 'エラー: KX秘密鍵の抽出に失敗しました。' . PHP_EOL; 30 return; 31 } 32 33 echo ' 抽出されたKX秘密鍵 (HEX): ' . sodium_bin2hex($kxSecretKey) . PHP_EOL; 34 echo ' KX秘密鍵の長さ: ' . strlen($kxSecretKey) . ' バイト (32バイトが期待されます)' . PHP_EOL; 35 36 // (オプション) 補完のために公開鍵も抽出します。 37 // 公開鍵は鍵交換の相手に共有されます。 38 $kxPublicKey = sodium_crypto_kx_publickey($kxKeyPair); 39 echo ' 抽出されたKX公開鍵 (HEX): ' . sodium_bin2hex($kxPublicKey) . PHP_EOL; 40 echo ' KX公開鍵の長さ: ' . strlen($kxPublicKey) . ' バイト (32バイトが期待されます)' . PHP_EOL; 41 42 echo PHP_EOL; 43 echo "--- 関連キーワード: sodium_crypto_box との比較 ---" . PHP_EOL; 44 45 // キーワードである "sodium_crypto_box" は、公開鍵暗号を用いた認証付き暗号化/復号のための 46 // 別の暗号プリミティブ(基本機能)を指します。 47 // KX と crypto_box はいずれも公開鍵/秘密鍵ペアを使用しますが、その目的は異なります。 48 // - KX: 将来の共通鍵暗号のために、共有の対称秘密鍵を導出します。 49 // - crypto_box: 非対称鍵を使ってメッセージを直接暗号化・復号します。 50 51 // 1. crypto_box用の鍵ペアを生成します。 52 $boxKeyPair = sodium_crypto_box_keypair(); 53 echo '生成されたcrypto_box鍵ペアの全長: ' . strlen($boxKeyPair) . ' バイト' . PHP_EOL; 54 55 // 2. sodium_crypto_box_secretkey を使用して、crypto_box鍵ペアから秘密鍵を抽出します。 56 // これは sodium_crypto_kx_secretkey と同様に、鍵ペアから秘密部分を抽出する機能ですが、 57 // crypto_boxの鍵ペアに対して行われます。 58 $boxSecretKey = sodium_crypto_box_secretkey($boxKeyPair); 59 60 if ($boxSecretKey === false) { 61 echo 'エラー: crypto_box秘密鍵の抽出に失敗しました。' . PHP_EOL; 62 return; 63 } 64 65 echo ' 抽出されたcrypto_box秘密鍵 (HEX): ' . sodium_bin2hex($boxSecretKey) . PHP_EOL; 66 echo ' crypto_box秘密鍵の長さ: ' . strlen($boxSecretKey) . ' バイト (32バイトが期待されます)' . PHP_EOL; 67} 68 69// スクリプト実行時にデモンストレーション関数を呼び出します。 70demonstrateSodiumKeyExtraction(); 71 72?>
sodium_crypto_kx_secretkey は、PHPのSodium拡張機能が提供する関数の一つです。この関数は、Key Exchange(鍵交換、略してKX)のために生成された完全な鍵ペアから、秘密鍵のみを安全に抽出する役割を持っています。
引数にはstring型の $key_pair を受け取ります。これは、秘密鍵と公開鍵が結合された状態の完全なKX鍵ペアです。本関数は、その $key_pair から公開鍵ではない、秘密鍵の部分のみを分離して取り出します。戻り値はstring型で抽出された秘密鍵そのものです。もし抽出に失敗した場合は、戻り値はfalseとなりますので、処理の成功を確認できます。
サンプルコードでは、まず鍵交換用の鍵ペアを生成し、その後に sodium_crypto_kx_secretkey を用いて秘密鍵を取り出す手順を示しています。抽出された秘密鍵は、通信相手との間で安全に共通の秘密情報を確立する際に利用されます。
関連キーワードの sodium_crypto_box は、認証付き暗号化に特化した別の暗号機能です。こちらも鍵ペアを使用し、 sodium_crypto_box_secretkey という同様の関数で秘密鍵を抽出できますが、KXとは鍵ペアの用途が異なります。KXが共通鍵の確立を目的とするのに対し、crypto_boxはメッセージを直接暗号化・復号するために使われます。
PHPのSodium拡張が有効になっていることが前提条件です。抽出された秘密鍵は極めて機密性が高く、厳重な管理と漏洩防止が絶対条件となります。決してログに出力したり、外部に公開したりしないでください。sodium_crypto_kx_secretkeyは鍵交換(KX)用途の鍵ペアからのみ秘密鍵を抽出する関数です。関連するsodium_crypto_boxなど、他の暗号化用途にはそれぞれ対応する別の鍵ペア生成関数と秘密鍵抽出関数が存在するため、混同しないよう注意が必要です。関数は失敗時にfalseを返すため、必ず戻り値を確認し、適切にエラー処理を実装してください。また、抽出される鍵の長さが想定通りであることも確認することが安全な利用のために重要です。