秘密鍵を生成するための次のコード行があります。
int Xa = randomNo.nextInt(10000);
int Ya = (int) Math.pow(G, Xa) % P;
G
とP
は静的な数値です。一方Xa
、ランダムに生成されます。プログラムを実行するたびに、同じ結果が得られYa
ます。これはDiffie-Hellmanにとって正しいですか?アルゴリズムを実行するたびに秘密鍵を変更する必要があると思いました。
秘密鍵を生成するための次のコード行があります。
int Xa = randomNo.nextInt(10000);
int Ya = (int) Math.pow(G, Xa) % P;
G
とP
は静的な数値です。一方Xa
、ランダムに生成されます。プログラムを実行するたびに、同じ結果が得られYa
ます。これはDiffie-Hellmanにとって正しいですか?アルゴリズムを実行するたびに秘密鍵を変更する必要があると思いました。
問題は、Javaのクラスに、特定の方法で疑似乱数シーケンスを開始できる1つの引数(シードRandom
と呼ばれる)を持つコンストラクターがあることです。long
常に同じシードを使用する場合は、常に同じシーケンスを取得します。
この問題を解決するには、次のことを試してください。
Random randomNo = new Random(System.nanoTime());
int Xa = randomNo.nextInt(10000);
このように、シードは常に異なり、上記の行を呼び出すたびにシーケンスが変更されます。
他の人があなたの乱数の生成に関する問題について良い答えを出したようですので、私はあなたの質問に答えます「これはDiffie-Hellmanにとって正しいですか?」
Diffie-Helmanについてのあなたの理解は少しずれていると思います。一つには、「公開鍵」もあるかのように「秘密鍵」という用語を使い続けます。Diffie-Hellman鍵交換は、1つの対称鍵を交換するために使用される手法です。秘密鍵と公開鍵はありません。両方の当事者がメッセージを暗号化するために使用する鍵だけがあります。さらに、これはキーを「生成」するためのコードであるとおっしゃいました。Diffie-Hellmanでは、タンゴに2つかかります。このコードは、キーの最終製品を生成するのに十分ではありません。プロセスを完了するには、セカンドパーティに送信Ya
し、そのセカンドパーティから何かを取り戻す必要があります。詳細については、以下を参照してください。
それが想定されているものであると仮定すると、生成するための式Ya
は正しいXa
です。Xa
を生成した後でランダムな値に再割り当てするため、何をすべきかについての理解が少し心配ですYa
。Xa
キーの最終バージョンを作成するには、しばらくお待ちください。
生成Ya
したら、それを相手に送信する必要があります。相手はあなたにいくつかの番号を返します(それを呼びましょうR
)。対称鍵の最終バージョンを作成するには(これを呼びましょうSK
)、次のように計算する必要があります。
SK = (int)Math.pow(R, Xa) % P;
したがって、簡単に言うと、計算Xa
後に再計算しないでください。再計算しYa
ないと、キーを生成できなくなります。プロセスは次のとおりです。
Ya
します(これはあなたが使用したものなので、私はこの変数名を使用しています)。Ya
てください。Ya
(上記の例ではこの番号と呼びR
ます)。R
、暗号化に使用する対称鍵を計算します。(上記の式を参照してください)Xa
P
SK
問題は、べき乗で2倍オーバーフローし、無限大になり、毎回同じ値になることだと思います(幸運にも、指数に対して非常に少ない数値が返される場合を除きます)。
また、ランダム値を取得するには、必ずセキュアランダムを使用してください。
Random random = new SecureRandom();
// If you use more than 100 here, then
// with your value of 486 for G you will
// end up with infinity when doing Math.pow(G,Xa).
// Of course, this does not provide enough possible
// values to be cryptographically secure.
int Xa = random.nextInt(100);
int Ya = (int) (Math.pow(G, Xa) % P);
編集:デバッグを伴うコード(以下は私のために機能します):
double G = 42;
int P = 26;
Random random = new SecureRandom();
int Xa = random.nextInt(100);
double val = Math.pow(G, Xa);
System.out.println("Xa: " + Xa);
System.out.println("(double) Math.pow: " + val + " (int): " + (int) val);
int Ya = (int) (val % P);
System.out.println("Ya: " + Ya);
これは、Xa
が異なる場合にのみ異なる結果をもたらす可能性があります。どのようにしての価値を生み出しましたXa
か?通常はシードする必要がある疑似ランダムジェネレーターを使用した可能性があります。毎回デフォルトのシード(毎回同じシード)を使用すると、常に同じ乱数シーケンスが返されます。
ジェネレータをシードしてみてくださいSystem.currentTimeMillis();