要理解 DH 金鑰協商協定,你必須先理解它們的核心操作——DH 函式。
DH 函式通常在記為 Zp* 的群中運作。回想第 9 章:這些群由某個質數 p 之模下的非零整數構成。另一個公開參數是底數 g。所有算術運算都在模 p 下進行。
運作方式#
DH 函式牽涉到通訊雙方從群 Zp* 中隨機選出的兩個私密值 a 與 b:
Alice:私密值 a → 公開值 A = g^a mod p
Bob :私密值 b → 公開值 B = g^b mod p這些公開值透過竊聽者看得見的訊息送給對方。
DH 的魔法在於:把任一方的公開值與另一方的私密值結合,兩邊會得到相同的結果:
A^b = (g^a)^b = g^ab B^a = (g^b)^a = g^ba = g^ab
所得的值 g^ab 就是共享秘密。它接著被送入一個金鑰衍生函式(KDF)來產生一把或多把共享的對稱金鑰。
KDF 是一種雜湊函式,會回傳一個看起來隨機、長度為所需金鑰長度的字串。
就這樣。與許多偉大的科學發現(重力、相對論、量子計算或 RSA)一樣,Diffie–Hellman 這個把戲事後看來簡單得可怕。
但簡單可能會騙人#
DH 不是配上任何質數
p或底數g都能運作。例如某些
g的值會把共享秘密g^ab限制在可能值的一個小子集中,而你期望的是「可能值的數量與Zp*中的元素數量差不多」。
安全質數#
要確保最高的安全性,安全的 DH 參數應該使用一個使
(p − 1) / 2也是質數的質數p。這樣的安全質數(safe prime)保證該群不含會讓 DH 更容易被攻破的小子群。
使用安全質數時,DH 特別可以搭配 g = 2 運作,讓計算稍微快一些。
但產生安全質數
p比產生一個完全隨機的質數花更多時間。
實測時間差#
OpenSSL 工具包的 dhparam 指令只會產生安全的 DH 參數,但演算法中內建的額外檢查大幅增加了執行時間:
$ time openssl dhparam 2048
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
--snip--
-----BEGIN DH PARAMETERS-----
MIIBCAKCAQEAoSIbyA9e844q7V89rcoEV8vd/l2svwhIIjG9EPwWWr7FkfYhYkU9
--snip--
-----END DH PARAMETERS-----
openssl dhparam 2048 154.53s user 0.86s system 99% cpu 2:36.85 total相同系統上產生同樣大小的 RSA 參數(也就是兩個質數 p、q,各為 DH 所用之 p 的一半大小):
$ time openssl genrsa 2048
Generating RSA private key, 2048 bit long modulus
--snip--
openssl genrsa 2048 0.16s user 0.01s system 95% cpu 0.171 total