Nodeのcryptoとディフィー・ヘルマン鍵共有の数式との対応関係
#Node.js #crypto #セキュリティ #Diffie_Hellman #少し数学 #ディフィー・ヘルマン鍵共有
実装と理論の対応関係を理解しておくことは大事。
理論で保証されていることを守ることで、セキュリティ面でちゃんと効果を発揮する。
cryptoのコードと数式の対応関係
以下のコードと理論の対応関係についてわかったこと。
code:js
const crypto = require('crypto');
const assert = require('assert');
// Generate Alice's keys...
const alice = crypto.createDiffieHellman(2048);
const aliceKey = alice.generateKeys();
// Generate Bob's keys...
const bob = crypto.createDiffieHellman(alice.getPrime(), alice.getGenerator());
const bobKey = bob.generateKeys();
// Exchange and generate the secret...
const aliceSecret = alice.computeSecret(bobKey);
const bobSecret = bob.computeSecret(aliceKey);
// OK
assert.strictEqual(aliceSecret.toString('hex'), bobSecret.toString('hex'));
(コードの元:)
以下の$ G, P, A, Bなどの変数たちがソースコードのどれに対応しているかという解釈。
https://gyazo.com/bdf4f1bbab4f4830e14f4cb0fba9b977
(写真の元:ディフィー・ヘルマン鍵共有の仕組み - 小人さんの妄想)
(写真の元ではディフィー・ヘルマン鍵共有の仕組みに関して具体的に説明が載ってます。)
まず、ディフィー・ヘルマン鍵共有の前提知識として、以下の値たちは公開して大丈夫値。
$ G
$ P
$ G^A \mod P
$ G^B \mod P
(注:$ G^x \mod Pが公開という意味は、計算結果が公開可能ということを意味していて、$ Aと$ Bは秘密 )
上記の図で、$ G^A \mod Pと$ G^B \mod Pを交換してることがわかるように、
このモジュロ演算の結果が公開鍵になっている。
対応関係は以下のようになっているはず。
$ G =alice.getGenerator()
$ P =alice.getPrime()
$ G^A \mod P = alice.generateKeys()
$ G^B \mod P =がbob.generateKeys()
oooKey()メソッドたちなどで取れる値はBuffer型。
$ Aと$ Bはコード内には登場していない。
これらは秘密鍵で、DiffieHellman#getPrivateKey()の戻り値が 秘密鍵$ A, $ Bに対応しているはず。
generateKeys()は公開鍵を返す
DiffieHellman#generateKeys()はドキュメントの説明を読む限り、公開鍵と秘密鍵を生成して公開鍵を返すメソッドということ。そのため、DiffieHellman#generateKeys()の戻り値は公開鍵。
ここは結構重要な気がする。メソッド名に複数形のsがついているが、戻ってくるのはkey一個なので。
あと、generateKeys()を読んだ後にgetPublicKey()を呼ばないとエラーする。
computeSecret()の対応関係
以下の画像の説明を見る限り、
https://gyazo.com/bdf4f1bbab4f4830e14f4cb0fba9b977
おそらく以下のように、対応しているはず。
$ B \times A = computeSecret(bobKey)
$ A \times B = computeSecret(aliceKey)
もちろん乗算の交換法則が成り立つため、2つの値は等しい。
これが秘密の値を共有できる仕組みでもあるはず。
重要なことは、共有できた秘密の値$ A \times Bと秘密鍵$ Aと$ Bは別ものというところだと思う。
つまり、getPrivateKey()とcomputeSecret()は別の値を返すと言うこと。