【PHP8.x】sodium_crypto_box_seed_keypair()関数の使い方
sodium_crypto_box_seed_keypair関数の使い方について、初心者にもわかりやすく解説します。
基本的な使い方
sodium_crypto_box_seed_keypair関数は、指定されたシード(種)から、一貫して同じ公開鍵と秘密鍵のペアを生成する関数です。この関数は、セキュアな通信やデータの暗号化、デジタル署名に用いられる鍵ペアを作成します。鍵ペアは、公開鍵と秘密鍵の二つから構成されます。公開鍵は安全に他者と共有できる情報であり、メッセージの暗号化や相手の署名の検証に使われます。一方、秘密鍵は決して他者に漏らしてはならない情報であり、自分宛の暗号化メッセージの復号や、自身がメッセージに署名する際に使用されます。
この関数の特徴は、乱数から鍵を生成するのではなく、「シード」と呼ばれる固定のバイナリデータを使用する点です。同じシードを常に使用することで、何度実行しても全く同じ公開鍵と秘密鍵のペアが生成されるため、再現性のある鍵生成が可能です。例えば、システムのバックアップから鍵ペアを復元したい場合や、複数の異なる環境で特定の鍵ペアを確実に利用したい場合に役立ちます。
引数には、鍵ペア生成の元となる32バイトのバイナリ文字列であるシードを指定します。戻り値としては、生成された公開鍵と秘密鍵の両方を含む96バイトのバイナリ文字列を返します。セキュリティを確保するため、シード自体は安全に管理し、推測されにくい、強力な値を使用することが非常に重要です。
構文(syntax)
1<?php 2 3$seed = random_bytes(SODIUM_CRYPTO_BOX_SEEDBYTES); 4$keypair = sodium_crypto_box_seed_keypair($seed); 5 6?>
引数(parameters)
string $seed
- string $seed: 鍵ペアを生成するためのシードとなる24バイトのバイナリ文字列
戻り値(return)
string
sodium_crypto_box_seed_keypair 関数は、指定されたシード値から生成された公開鍵と秘密鍵のペアを文字列として返します。
サンプルコード
sodium_crypto_box_seed_keypair でキーペア生成
1<?php 2 3// このスクリプトは、libナトリウムがインストールされ、PHPのsodium拡張が有効になっている環境で動作します。 4 5/** 6 * sodium_crypto_box_seed_keypair を使用してキーペアを生成し、 7 * それを用いてメッセージの暗号化と復号化を行うサンプル関数です。 8 * システムエンジニアを目指す初心者にも理解しやすいように、各ステップにコメントを付けています。 9 */ 10function demonstrateSodiumCryptoBoxSeedKeypair(): void 11{ 12 echo "--- sodium_crypto_box_seed_keypair のデモンストレーション ---" . PHP_EOL . PHP_EOL; 13 14 // --- 1. シードからキーペアを生成 --- 15 16 // 暗号学的に安全なランダムなシードを生成します。 17 // シードの長さは SODIUM_CRYPTO_BOX_SEEDBYTES 定数で定義されています。 18 // このシードは、公開鍵と秘密鍵のペアを一意に決定するための元となります。 19 $seed = random_bytes(SODIUM_CRYPTO_BOX_SEEDBYTES); 20 echo "1. 生成されたシード (HEX): " . bin2hex($seed) . PHP_EOL . PHP_EOL; 21 22 // sodium_crypto_box_seed_keypair 関数は、指定されたシードから 23 // 秘密鍵と公開鍵が連結されたキーペアを生成して返します。 24 // このキーペアは、後続の暗号化・復号化操作で使用されます。 25 $keypair = sodium_crypto_box_seed_keypair($seed); 26 27 // 生成されたキーペアから公開鍵と秘密鍵をそれぞれ分離します。 28 // 公開鍵は安全に共有できますが、秘密鍵は厳重に管理する必要があります。 29 $publicKey = sodium_crypto_box_publickey($keypair); 30 $secretKey = sodium_crypto_box_secretkey($keypair); 31 32 echo "2. 生成された公開鍵 (HEX): " . bin2hex($publicKey) . PHP_EOL; 33 echo "3. 生成された秘密鍵 (HEX): " . bin2hex($secretKey) . PHP_EOL . PHP_EOL; 34 35 // --- 2. 生成されたキーペアを使用したメッセージの暗号化と復号化 --- 36 37 // 送信するプレーンテキストメッセージを用意します。 38 $originalMessage = "こんにちは、PHPのSodium拡張の世界へようこそ!"; 39 echo "4. 元のメッセージ: " . $originalMessage . PHP_EOL . PHP_EOL; 40 41 // 暗号化には「ナンス」(Nonce: Number used once)が必要です。 42 // ナンスは各暗号化操作で一意である必要があり、再利用してはいけません。 43 // ナンスの長さは SODIUM_CRYPTO_BOX_NONCEBYTES 定数で定義されています。 44 // ナンスは暗号化されたデータと一緒に安全でないチャネルで送信しても問題ありません。 45 $nonce = random_bytes(SODIUM_CRYPTO_BOX_NONCEBYTES); 46 echo "5. 生成されたナンス (HEX): " . bin2hex($nonce) . PHP_EOL . PHP_EOL; 47 48 // sodium_crypto_box 関数を使用してメッセージを暗号化します。 49 // この関数は、送信者の秘密鍵と受信者の公開鍵(またはその逆)を使用して、 50 // 認証付き暗号化を行います。 51 // ここでは、生成したキーペアを使って「自分自身に」メッセージを送信する例を示します。 52 $encryptedMessage = sodium_crypto_box( 53 $originalMessage, // 暗号化するメッセージ 54 $nonce, // 暗号化に使用する一意のナンス 55 $publicKey, // 受信者の公開鍵 (今回は自分自身の公開鍵) 56 $secretKey // 送信者の秘密鍵 (今回は自分自身の秘密鍵) 57 ); 58 echo "6. 暗号化されたメッセージ (HEX): " . bin2hex($encryptedMessage) . PHP_EOL . PHP_EOL; 59 60 // sodium_crypto_box_open 関数を使用して暗号化されたメッセージを復号化します。 61 // 復号化には、暗号化時と同じナンス、受信者の秘密鍵、送信者の公開鍵が必要です。 62 $decryptedMessage = sodium_crypto_box_open( 63 $encryptedMessage, // 復号化するメッセージ 64 $nonce, // 暗号化時に使用したナンス 65 $publicKey, // 送信者の公開鍵 (今回は自分自身の公開鍵) 66 $secretKey // 受信者の秘密鍵 (今回は自分自身の秘密鍵) 67 ); 68 69 echo "7. 復号化されたメッセージ: "; 70 if ($decryptedMessage === false) { 71 echo "エラー: メッセージの復号化に失敗しました。" . PHP_EOL; 72 } else { 73 echo $decryptedMessage . PHP_EOL; 74 // 元のメッセージと復号化されたメッセージが一致するか確認し、成功を判定します。 75 if ($originalMessage === $decryptedMessage) { 76 echo "結果: 暗号化と復号化は成功し、メッセージは一致しました。" . PHP_EOL; 77 } else { 78 echo "結果: エラー - 復号化されたメッセージが元のメッセージと異なります。" . PHP_EOL; 79 } 80 } 81 82 echo PHP_EOL . "--- デモンストレーション終了 ---" . PHP_EOL; 83} 84 85// 上記のサンプル関数を実行します。 86demonstrateSodiumCryptoBoxSeedKeypair();
PHPのsodium_crypto_box_seed_keypair関数は、暗号化ライブラリLibsodiumをPHPで利用するためのSodium拡張機能に含まれる関数です。この関数は、暗号学的に安全なランダムなバイト列であるシード(引数$seed)を受け取り、それに基づいて一対の秘密鍵と公開鍵を生成します。これらの鍵は連結された単一のキーペア文字列として戻り値で返されます。
引数$seedは、キーペアを一意に生成するための元となる情報です。そのため、SODIUM_CRYPTO_BOX_SEEDBYTES定数で定義された適切な長さの、安全なランダムバイト列を使用することが重要です。
戻り値のキーペア文字列からは、sodium_crypto_box_publickey関数を使って公開鍵を、sodium_crypto_box_secretkey関数を使って秘密鍵をそれぞれ抽出することができます。生成された公開鍵は安全に共有できますが、秘密鍵は厳重に管理する必要があります。
このキーペアは、主にsodium_crypto_boxやsodium_crypto_box_openといった関数を用いることで、Diffie-Hellman鍵交換に基づいた認証付き暗号化システムにおいて、メッセージの暗号化や復号化に利用されます。シードからキーペアを生成する利点として、同じシードからは常に同じキーペアが生成されるため、鍵の再現性が必要なシステム構築に適しています。
このコードは、libナトリウムがインストールされ、PHPのsodium拡張が有効な環境でのみ動作します。暗号学的に安全なシードをrandom_bytesで生成していますが、シードが予測可能だと鍵ペアの安全性が損なわれるため、乱数源の確保は非常に重要です。生成された秘密鍵は厳重に管理し、絶対に第三者に漏洩させてはいけません。また、暗号化に使用するナンスは、各暗号化操作で必ず一意である必要があり、再利用は暗号の安全性を著しく損なうため厳禁です。復号化が失敗した場合にはfalseが返されるため、必ずその結果を確認し、適切にエラー処理を行ってください。本番環境での利用時には、これらのセキュリティ要件を十分に理解し、鍵管理やナンスの生成ロジックについて専門家の助言を求めることをお勧めします。
sodium_crypto_secretboxで安全に通信する
1<?php 2 3/** 4 * Demonstrates secure communication by generating asymmetric key pairs 5 * and then using a derived shared secret for symmetric encryption. 6 * 7 * This example shows how 'sodium_crypto_box_seed_keypair' can be used 8 * to establish a shared secret, which is then utilized by 9 * 'sodium_crypto_secretbox' for authenticated encryption of messages. 10 * This is a common pattern in cryptography: asymmetric key exchange 11 * followed by symmetric bulk data encryption. 12 */ 13function demonstrateSecureCommunicationFlow(): void 14{ 15 echo "--- Secure Communication Flow Demonstration ---\n\n"; 16 17 // 1. Generate Key Pairs for two parties (Alice and Bob) 18 // sodium_crypto_box_seed_keypair creates a public/private key pair 19 // from a given seed. The seed must be SODIUM_CRYPTO_BOX_SEEDBYTES long. 20 // For general random key generation, sodium_crypto_box_keypair() is often used. 21 $aliceSeed = random_bytes(SODIUM_CRYPTO_BOX_SEEDBYTES); 22 $aliceKeypair = sodium_crypto_box_seed_keypair($aliceSeed); 23 $aliceSecretKey = sodium_crypto_box_secretkey($aliceKeypair); 24 $alicePublicKey = sodium_crypto_box_publickey($aliceKeypair); 25 26 $bobSeed = random_bytes(SODIUM_CRYPTO_BOX_SEEDBYTES); 27 $bobKeypair = sodium_crypto_box_seed_keypair($bobSeed); 28 $bobSecretKey = sodium_crypto_box_secretkey($bobKeypair); 29 $bobPublicKey = sodium_crypto_box_publickey($bobKeypair); 30 31 echo "✅ Key pairs generated for Alice and Bob.\n\n"; 32 33 // 2. Derive a Shared Secret Key using the asymmetric keys 34 // Both Alice and Bob can independently compute the same shared secret. 35 // Alice uses her secret key and Bob's public key. 36 // Bob uses his secret key and Alice's public key. 37 $aliceSharedSecret = sodium_crypto_box_beforenm($bobPublicKey, $aliceSecretKey); 38 $bobSharedSecret = sodium_crypto_box_beforenm($alicePublicKey, $bobSecretKey); 39 40 if ($aliceSharedSecret === $bobSharedSecret) { 41 echo "✅ Shared secret successfully derived by both Alice and Bob.\n"; 42 echo " Shared Secret Length: " . strlen($aliceSharedSecret) . " bytes\n\n"; 43 } else { 44 echo "❌ Error: Shared secrets do not match. Aborting.\n"; 45 return; 46 } 47 48 // We now have a common secret key for symmetric encryption 49 $sharedSecretForSymmetricEncryption = $aliceSharedSecret; 50 51 // 3. Encrypt and Decrypt a Message using the Shared Secret 52 // sodium_crypto_secretbox performs authenticated symmetric encryption. 53 // It requires a shared secret key and a unique nonce for each message. 54 $originalMessage = "This is a secret message sent securely!"; 55 echo "Original Message: \"{$originalMessage}\"\n\n"; 56 57 // Generate a unique nonce (number used once). 58 // The nonce does not need to be secret, but it MUST be unique for each message 59 // encrypted with the same key. It's typically transmitted alongside the ciphertext. 60 $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); 61 62 // Encrypt the message 63 $ciphertext = sodium_crypto_secretbox($originalMessage, $nonce, $sharedSecretForSymmetricEncryption); 64 echo "✅ Message encrypted.\n"; 65 // For display, we might base64 encode, but it's raw binary data. 66 echo " Ciphertext (Base64 for display): " . base64_encode($ciphertext) . "\n\n"; 67 68 // Decrypt the message 69 // Bob (or any recipient with the shared secret and nonce) can decrypt. 70 $decryptedMessage = sodium_crypto_secretbox_open($ciphertext, $nonce, $sharedSecretForSymmetricEncryption); 71 72 if ($decryptedMessage === false) { 73 echo "❌ Decryption failed! Message may have been tampered with, or key/nonce is incorrect.\n"; 74 } else { 75 echo "✅ Message decrypted.\n"; 76 echo " Decrypted Message: \"{$decryptedMessage}\"\n\n"; 77 78 if ($decryptedMessage === $originalMessage) { 79 echo "✅ Decryption successful and message integrity verified!\n"; 80 } else { 81 echo "❌ Decrypted content does not match original message (integrity check failed or logic error).\n"; 82 } 83 } 84 85 // It's good practice to clear sensitive data from memory when no longer needed. 86 sodium_memzero($aliceKeypair); 87 sodium_memzero($aliceSecretKey); 88 sodium_memzero($bobKeypair); 89 sodium_memzero($bobSecretKey); 90 sodium_memzero($sharedSecretForSymmetricEncryption); 91 sodium_memzero($nonce); 92 93 echo "\n--- End of Demonstration ---\n"; 94} 95 96// Execute the demonstration function 97demonstrateSecureCommunicationFlow(); 98 99?>
PHP 8のsodium_crypto_box_seed_keypair関数は、セキュアな通信を実現するための公開鍵と秘密鍵のペアを生成します。引数の$seedには、暗号学的に安全なランダムなバイト列を指定し、これにより一意で予測不可能な鍵ペアが生成されます。戻り値は、生成された公開鍵と秘密鍵を合わせた文字列です。
この関数は、主に二者間の安全な鍵交換プロトコルで利用されます。サンプルコードでは、通信を行うアリスとボブそれぞれがこの関数で鍵ペアを生成しています。そして、生成されたアリスの秘密鍵とボブの公開鍵、またはボブの秘密鍵とアリスの公開鍵を組み合わせることで、互いに共通の秘密鍵を導出します。
導出された共通の秘密鍵は、sodium_crypto_secretboxのような共通鍵暗号関数と組み合わせて使用されます。これにより、メッセージを認証付きで暗号化し、盗聴や改ざんから保護された安全な通信チャネルを確立できます。このプロセスは、非対称鍵で安全に共通鍵を確立し、その共通鍵で実際のデータを高速に暗号化するという、現代のセキュア通信の基本的なパターンを示しています。
sodium_crypto_box_seed_keypairは特定のシードから鍵ペアを生成しますが、通常は予測不可能な乱数で鍵ペアを生成するsodium_crypto_box_keypair()の利用が一般的です。メッセージの暗号化にsodium_crypto_secretboxを使用する際は、ノンス(一時的な使い捨ての値)を各メッセージで必ずユニークに生成することが極めて重要です。ノンスが重複するとセキュリティが著しく損なわれるため、十分注意してください。また、秘密鍵や共有シークレット、ノンスなどの機密情報は、使用後にsodium_memzero関数でメモリから安全に消去する習慣をつけましょう。これにより、情報漏洩のリスクを低減できます。復号に失敗してfalseが返される場合は、メッセージが改ざんされたか鍵が誤っている可能性があるので、必ずエラーとして適切に処理してください。