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

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

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

作成日: 更新日:

基本的な使い方

sodium_crypto_scalarmult関数は、暗号技術の重要な要素であるスカラー倍算を実行する関数です。この関数は、特にCurve25519などの楕円曲線暗号システムにおいて、安全な鍵交換プロトコル(例えば、Diffie-Hellman鍵交換)で共有シークレットを計算するために使用されます。これにより、二者間で安全に秘密の情報を共有し、その後の暗号化通信に利用することが可能になります。

具体的には、2つのバイナリ文字列を引数として受け取ります。1つ目の引数は、秘密の数値である「スカラー」で、これは通常、利用者の秘密鍵の一部として機能します。2つ目の引数は「ポイント」で、これは通常、通信相手の公開鍵や、固定されたベースポイントを表します。関数は、与えられたスカラーとポイントの積を計算し、その結果として得られる共有シークレットをバイナリ文字列として返します。このスカラー倍算は、ネットワーク通信のセキュリティを確保する上で非常に重要な暗号操作であり、PHPのLibSodium拡張を通じて、開発者が堅牢で安全な暗号機能をアプリケーションに組み込むことを可能にします。安全な鍵共有は、データの機密性と完全性を保護するための基盤となります。

構文(syntax)

1string sodium_crypto_scalarmult(string $n, string $p)

引数(parameters)

string $n, string $p

  • string $n: 秘密鍵を指定する文字列。256ビット(32バイト)である必要があります。
  • string $p: 公開鍵を指定する文字列。256ビット(32バイト)である必要があります。

戻り値(return)

string

この関数は、2つの秘密鍵から計算された共有秘密鍵をバイナリ文字列として返します。

サンプルコード

PHP sodium_crypto_scalarmultで鍵交換する

1<?php
2
3/**
4 * PHPのlibsodium拡張機能を使った楕円曲線スカラー倍算 (Diffie-Hellman鍵交換) のサンプルコード。
5 *
6 * sodium_crypto_scalarmult 関数は、スカラー(秘密鍵)と点(公開鍵)から、
7 * 別の点(共有秘密鍵)を計算するために使用されます。
8 * この例では、アリスとボブが互いに安全な共有秘密鍵を導出するプロセスを示します。
9 */
10
11// libsodium拡張機能が利用可能かを確認します。
12if (!extension_loaded('sodium')) {
13    die('エラー: sodium拡張機能がロードされていません。PHPの設定を確認してください。');
14}
15
16echo "libsodium拡張機能が利用可能です。\n\n";
17
18// --- 1. アリスの鍵ペア生成 ---
19// アリスの秘密鍵 (スカラー) を生成します。
20// sodium_crypto_scalarmult_base() は、秘密鍵(スカラー)を生成し、
21// 引数を渡さなければ新しいランダムな秘密鍵を生成します。
22$aliceSecretKey = sodium_crypto_scalarmult_base();
23
24// アリスの公開鍵 (点) を生成します。
25// 生成された秘密鍵から対応する公開鍵を計算します。
26// これは、ベースポイントと呼ばれる標準の点とアリスの秘密鍵から計算されます。
27$alicePublicKey = sodium_crypto_scalarmult_base($aliceSecretKey);
28
29echo "アリスの鍵ペアを生成しました。\n";
30echo "  アリスの公開鍵 (Hex): " . bin2hex($alicePublicKey) . "\n";
31
32// --- 2. ボブの鍵ペア生成 ---
33// ボブの秘密鍵 (スカラー) を生成します。
34$bobSecretKey = sodium_crypto_scalarmult_base();
35
36// ボブの公開鍵 (点) を生成します。
37$bobPublicKey = sodium_crypto_scalarmult_base($bobSecretKey);
38
39echo "ボブの鍵ペアを生成しました。\n";
40echo "  ボブの公開鍵 (Hex): " . bin2hex($bobPublicKey) . "\n\n";
41
42// --- 3. アリスが共有秘密鍵を計算 ---
43// アリスは自身の秘密鍵とボブの公開鍵を使って共有秘密鍵を計算します。
44// sodium_crypto_scalarmult(秘密鍵, 相手の公開鍵)
45$aliceSharedKey = sodium_crypto_scalarmult($aliceSecretKey, $bobPublicKey);
46
47echo "アリスが共有秘密鍵を計算しました。\n";
48echo "  アアリスの共有秘密鍵 (Hex): " . bin2hex($aliceSharedKey) . "\n";
49
50// --- 4. ボブが共有秘密鍵を計算 ---
51// ボブは自身の秘密鍵とアリスの公開鍵を使って共有秘密鍵を計算します。
52// sodium_crypto_scalarmult(秘密鍵, 相手の公開鍵)
53$bobSharedKey = sodium_crypto_scalarmult($bobSecretKey, $alicePublicKey);
54
55echo "ボブが共有秘密鍵を計算しました。\n";
56echo "  ボブの共有秘密鍵 (Hex): " . bin2hex($bobSharedKey) . "\n\n";
57
58// --- 5. 共有秘密鍵の一致を検証 ---
59// アリスとボブが計算した共有秘密鍵が同じであることを確認します。
60// hash_equals() を使用して、タイミング攻撃を防ぎながら比較を行います。
61if (hash_equals($aliceSharedKey, $bobSharedKey)) {
62    echo "成功: アリスとボブの共有秘密鍵は一致しました。\n";
63    echo "この共有秘密鍵は、以降の暗号化通信などで利用できます。\n";
64} else {
65    echo "エラー: 共有秘密鍵が一致しませんでした。\n";
66}
67
68// --- 6. 秘密情報のクリア (セキュリティ上のベストプラクティス) ---
69// 秘密鍵や共有秘密鍵などの機密情報をメモリから安全に消去します。
70// これはメモリダンプなどによる情報漏洩を防ぐための重要な手順です。
71sodium_memzero($aliceSecretKey);
72sodium_memzero($bobSecretKey);
73sodium_memzero($aliceSharedKey);
74sodium_memzero($bobSharedKey);
75
76echo "\n秘密鍵と共有秘密鍵はメモリからクリアされました。\n";
77
78?>

PHP 8のsodium拡張機能が提供するsodium_crypto_scalarmult関数は、楕円曲線暗号におけるスカラー倍算を実行し、安全な鍵共有を実現するために使用されます。この関数は、ディフィー・ヘルマン鍵交換のプロセスで、通信相手と共有秘密鍵を確立する際に中心的な役割を果たします。

引数$nには自身の秘密鍵(スカラー)を、$pには相手の公開鍵(点)を指定します。これにより、お互いが共通の秘密鍵を計算できるようになり、戻り値として、計算された共有秘密鍵が文字列形式で返されます。

サンプルコードでは、まずsodium_crypto_scalarmult_base関数を用いて、アリスとボブがそれぞれ自身の秘密鍵と、そこから導出される公開鍵を生成します。その後、アリスは自身の秘密鍵とボブの公開鍵を、ボブは自身の秘密鍵とアリスの公開鍵をそれぞれsodium_crypto_scalarmult関数に渡し、互いに共有秘密鍵を計算します。これらの計算結果は両者で一致するため、安全な通信のための共通の秘密情報として利用可能となります。最後に、セキュリティ上のベストプラクティスとして、秘密鍵などの機密情報をメモリから安全に消去するためsodium_memzero関数を使用しています。これにより、計算された共有秘密鍵は、メッセージの暗号化や認証など、その後の暗号化通信に活用されます。

このサンプルコードを利用するには、まずPHPのsodium拡張機能が有効になっていることを確認してください。sodium_crypto_scalarmult 関数は、自身の秘密鍵と相手の公開鍵を引数に渡す必要があります。引数の順序を誤ると正しく動作しませんので注意が必要です。鍵ペアの生成にはsodium_crypto_scalarmult_base関数を使用します。また、生成された秘密鍵や共有秘密鍵は非常に機密性の高い情報です。計算が完了したら、セキュリティのために必ずsodium_memzero関数でメモリから安全に消去してください。共有秘密鍵を比較する際は、タイミング攻撃を防ぐためhash_equals関数を用いることが必須です。

PHP Sodium 鍵交換をデモする

1<?php
2
3/**
4 * PHPのSodium拡張は、暗号化機能を安全かつ使いやすく提供するためのライブラリです。
5 * sodium_crypto_scalarmult 関数は、楕円曲線ディフィー・ヘルマン (ECDH)
6 * 鍵交換プロトコルにおいて、共通の秘密鍵を安全に導出するために使用されます。
7 * この関数は、特定のスカラー(秘密鍵)と点(公開鍵)から、新しい点(共有秘密鍵)を計算します。
8 *
9 * このサンプルコードでは、アリスとボブが互いの秘密鍵を明かすことなく、
10 * 安全に共通の秘密鍵を生成するプロセスをデモンストレーションします。
11 */
12function demonstrateEcdhKeyExchange(): void
13{
14    // PHPにSodium拡張がロードされているか確認します。
15    if (!extension_loaded('sodium')) {
16        echo "エラー: Sodium拡張がロードされていません。php.iniで有効にしてください。\n";
17        return;
18    }
19
20    echo "--- ECDH (Elliptic Curve Diffie-Hellman) 鍵交換のデモンストレーション ---\n\n";
21
22    // 1. アリスの鍵ペア(秘密鍵と公開鍵)を生成します。
23    // 秘密鍵はランダムなバイト列から生成され、他人には絶対に公開されません。
24    $aliceSecretKey = random_bytes(SODIUM_CRYPTO_SCALARMULT_SCALARBYTES);
25    // 公開鍵は秘密鍵から導出され、相手に渡しても安全です。
26    // sodium_crypto_scalarmult_base() は、ベースポイントと秘密鍵から公開鍵を計算します。
27    $alicePublicKey = sodium_crypto_scalarmult_base($aliceSecretKey);
28
29    echo "アリスの秘密鍵 (hex): " . bin2hex($aliceSecretKey) . "\n";
30    echo "アリスの公開鍵 (hex): " . bin2hex($alicePublicKey) . "\n\n";
31
32    // 2. ボブの鍵ペア(秘密鍵と公開鍵)を生成します。
33    $bobSecretKey = random_bytes(SODIUM_CRYPTO_SCALARMULT_SCALARBYTES);
34    $bobPublicKey = sodium_crypto_scalarmult_base($bobSecretKey);
35
36    echo "ボブの秘密鍵 (hex): " . bin2hex($bobSecretKey) . "\n";
37    echo "ボブの公開鍵 (hex): " . bin2hex($bobPublicKey) . "\n\n";
38
39    // 3. 共有秘密鍵の導出 (sodium_crypto_scalarmult を使用)
40    // アリスは「自分の秘密鍵」と「ボブの公開鍵」を使って共有秘密鍵を計算します。
41    // sodium_crypto_scalarmult(スカラー $n, 点 $p) は、スカラー倍算を行い、新しい点を返します。
42    $sharedSecretAlice = sodium_crypto_scalarmult($aliceSecretKey, $bobPublicKey);
43
44    // ボブは「自分の秘密鍵」と「アリスの公開鍵」を使って共有秘密鍵を計算します。
45    $sharedSecretBob = sodium_crypto_scalarmult($bobSecretKey, $alicePublicKey);
46
47    echo "アリスが導出した共有秘密鍵 (hex): " . bin2hex($sharedSecretAlice) . "\n";
48    echo "ボブが導出した共有秘密鍵 (hex): " . bin2hex($sharedSecretBob) . "\n\n";
49
50    // 4. 共有秘密鍵が一致することを確認します。
51    // 両者が計算した共有秘密鍵は、理論上、完全に一致するはずです。
52    if (hash_equals($sharedSecretAlice, $sharedSecretBob)) {
53        echo "結論: 両者が導出した共有秘密鍵は一致しました!\n";
54        echo "これにより、安全な通信チャネルを確立するための共通鍵が生成されました。\n";
55    } else {
56        echo "エラー: 共有秘密鍵が一致しませんでした。何らかの問題が発生しています。\n";
57    }
58
59    // セキュリティ上の注意:
60    // 導出された共有秘密鍵は、そのまま暗号化の鍵として使用するのではなく、
61    // KDF (Key Derivation Function) などの関数でさらに処理し、
62    // 適切な長さと強度の鍵を生成することが推奨されます。
63}
64
65// 関数を実行して、ECDH鍵交換のデモンストレーションを開始します。
66demonstrateEcdhKeyExchange();

PHPのSodium拡張は、安全な暗号化機能を提供するライブラリです。その中にあるsodium_crypto_scalarmult関数は、楕円曲線ディフィー・ヘルマン (ECDH) 鍵交換プロトコルにおいて、通信相手との間で共通の秘密鍵を安全に導出するために使用されます。

この関数は、第一引数string $nとして自身の秘密鍵(スカラー)を、第二引数string $pとして相手の公開鍵(点)を受け取ります。これらの引数をもとに楕円曲線上の計算(スカラー倍算)を行い、共有の秘密鍵となる新しい点(string型)を戻り値として返します。

サンプルコードでは、この鍵交換のプロセスをアリスとボブという二人の登場人物を通して具体的に示しています。まず、アリスとボブがそれぞれ自分だけの秘密鍵と、そこから導出される公開鍵を生成します。次に、アリスは「自分の秘密鍵」と「ボブの公開鍵」を、ボブは「自分の秘密鍵」と「アリスの公開鍵」を、それぞれsodium_crypto_scalarmult関数に渡して計算を実行します。この計算により、お互いの秘密鍵を直接交換することなく、最終的にアリスとボブがまったく同じ共通の秘密鍵を安全に導出できることを確認できます。これにより、盗聴の心配なく安全な通信を始めるための基盤が作られます。

PHPにSodium拡張がロードされているか必ず確認してください。未ロードの場合、この関数は利用できません。 sodium_crypto_scalarmultは、自分の秘密鍵と相手の公開鍵から共通秘密鍵を導出します。秘密鍵はSODIUM_CRYPTO_SCALARMULT_SCALARBYTESなどで指定される長さで生成し、厳重に管理して決して外部に公開しないでください。 導出された共有秘密鍵は、そのまま直接暗号化の鍵として利用せず、鍵導出関数(KDF)で適切な強度の鍵に変換してから利用することが推奨されます。

関連コンテンツ

関連IT用語

関連プログラミング言語