Diffie–Hellman 函式是多數已部署公鑰協商協定的核心。然而並不存在單一個「Diffie–Hellman 協定」,而是有多種使用 DH 函式建立共享秘密的方式。

以下依慣例把雙方稱為 Alice 與 Bob,攻擊者稱為 Eve;g 是算術運算所用群的底數,Alice 與 Bob 事先知道且固定。

匿名 Diffie–Hellman#

匿名 Diffie–Hellman 是最簡單的 DH 協定。稱為匿名,是因為它未經鑑別——參與者沒有任何一方能驗證的身分,雙方也不持有長期金鑰。Alice 無法向 Bob 證明她是 Alice,反之亦然。

Alice                          Bob
挑隨機指數 a                    挑隨機指數 b
設 A = g^a       ── A ──→       算 A^b = (g^a)^b = g^ab
算 B^a = g^ab    ←── B ──       設 B = g^b

圖 11-2:匿名 Diffie–Hellman 協定

純粹、簡單——但只對最懶的攻擊者安全

中間人攻擊#

匿名 DH 可以被中間人攻擊擊垮。竊聽者只要攔截訊息,對 Alice 假裝是 Bob、對 Bob 假裝是 Alice:

Alice              攻擊者 Eve                    Bob
挑隨機指數 a                                     挑隨機指數 b
設 A = g^a    →   丟棄 A
                  挑隨機指數 c
                  送 C = g^c 給 Bob      →      以為收到 Alice 的 C
                                                算 C^b = g^bc
                  丟棄 B                 ←      設 B = g^b
                  算 B^c = g^bc
                  挑隨機指數 d
算 D^a = g^ad ←   送 D = g^d 給 Alice
                  算 A^d = g^ad

結果:Eve 與 Alice 共享一個秘密 g^ad,與 Bob 共享另一個秘密 g^bc,而 Alice 與 Bob 都以為他們彼此共享單一個秘密。

協定執行完後,Alice 會從 g^ad 導出對稱金鑰來加密送給 Bob 的資料,而 Eve 會攔截這些加密訊息、解密它們(可能還修改明文),再用從 g^bc 導出的另一組金鑰重新加密送給 Bob。這一切都在 Alice 與 Bob 毫不知情的情況下發生。

要挫敗這個攻擊,你需要一個鑑別雙方身分的方法。

圖 11-3:對匿名 Diffie–Hellman 協定的中間人攻擊

鑑別式 Diffie–Hellman#

鑑別式 Diffie–Hellman 就是為了處理匿名 DH 的中間人攻擊而發展的。它讓雙方各持有一把私鑰與一把公鑰,使 Alice 與 Bob 能簽署他們的訊息,阻止 Eve 代表他們送訊息。

這裡的簽章不是用 DH 函式計算的,而是用 RSA-PSS 這類公鑰簽章方案。

因此攻擊者要成功代表 Alice 送訊息,就得偽造一個有效簽章——這在安全的簽章方案下是不可能的。

Alice (privA, pubB)                          Bob (privB, pubA)
挑隨機指數 a                                  挑隨機指數 b
設 A = g^a
設 sigA = sign(privA, A)   ── A, sigA ──→     用 pubA 驗證 sigA
                                              簽章無效則中止
                                              算 A^b = g^ab
用 pubB 驗證 sigB          ←── B, sigB ──      設 B = g^b
簽章無效則中止                                 設 sigB = sign(privB, B)
算 B^a = g^ab

圖 11-4:鑑別式 Diffie–Hellman 協定

「Alice (privA, pubB)」表示 Alice 持有自己的私鑰 privA 與 Bob 的公鑰 pubB。這種 priv/pub 金鑰對稱為長期金鑰,因為它事先固定,並在協定的連續執行中保持不變。

對竊聽者的安全性#

鑑別式 DH 對竊聽者是安全的——攻擊者不知道 DH 指數,因此學不到共享秘密 g^ab 的任何一個位元。

它也提供前向保密:即使攻擊者在某個時間點攻陷了任一方(入侵模型),他們會學到私有簽章金鑰,但學不到任何短暫的 DH 指數,因此無法得知任何先前共享秘密的值。

鑑別式 DH 也防止任一方控制共享秘密的值:Alice 無法精心構造一個特殊的 a 來預測 g^ab,因為她不控制 b,而 bg^ab 的影響與 a 一樣大。

一個例外是 Alice 選 a = 0,此時對任何 b 都有 g^ab = 1。但 0 不是被允許的值,協定應該拒絕它

弱點一:重放#

Eve 可以錄下先前的 AsigA,稍後重播給 Bob,藉此假裝是 Alice。Bob 就會相信自己在與 Alice 共享一個秘密——儘管 Eve 無法得知那個秘密

解法:金鑰確認(key confirmation)——Alice 與 Bob 互相證明他們擁有該共享秘密。例如雙方分別送出:

Alice → Bob:Hash(pubA ‖ pubB, g^ab)
Bob → Alice:Hash(pubB ‖ pubA, g^ab)

雙方都能用 pubApubBg^ab 驗證這些雜湊值的正確性。

弱點二:資料外洩#

鑑別式 DH 對資料外洩攻擊者的脆弱性更值得擔憂。

在這類攻擊中,攻擊者學到短暫秘密(指數 ab)的值,並用它冒充其中一方。

若 Eve 能學到某個指數 a 以及送給 Bob 的對應 AsigA,她就能發起一次新的協定執行並冒充 Alice

Eve (a, A, sigA, pubB)                    Bob (privB, pubA)
                                           挑隨機指數 b
                   ── A, sigA ──→          用 pubA 驗證 sigA(會通過)
                                           算 A^b = g^ab
用 pubB 驗證 sigB  ←── B, sigB ──          設 B = g^b
用竊得的 a 算 B^a = g^ab                   設 sigB = sign(privB, B)

結果雙方擁有一個共享秘密,而 Bob 相信自己在跟 Alice 對話

讓鑑別式 DH 能抵抗短暫秘密外洩的方法之一,是把長期金鑰整合進共享秘密的計算中,使得不知道長期秘密就無法決定共享秘密。

圖 11-5:對鑑別式 Diffie–Hellman 協定的冒充攻擊

MQV#

**Menezes–Qu–Vanstone(MQV)**協定是 DH 系協定歷史上的里程碑。它設計於 1998 年,曾被 NSA 納入 Suite B(用於保護機密資訊的演算法組合),核准用來保護最關鍵的資產。

NSA 最終捨棄了 MQV,據稱是因為它沒被使用。原因見後述。

MQV 是打了類固醇的 Diffie–Hellman。 它比鑑別式 DH 更安全,也改善了效能:

  • 使用者只需送兩則訊息,彼此獨立,順序任意
  • 訊息比鑑別式 DH 更短
  • 不需要送明確的簽章或驗證訊息——換句話說,除了 DH 函式之外,你不需要額外使用簽章方案。

運作方式#

與鑑別式 DH 一樣,Alice 與 Bob 各持有一把長期私鑰與對方的長期公鑰。差別在於 MQV 的金鑰不是簽章金鑰,而是由私有指數 x 與公開值 g^x 組成。

Alice (x, Y = g^y)                    Bob (y, X = g^x)
挑隨機指數 a                           挑隨機指數 b
設 A = g^a          ── A ──→           設 B = g^b
算 (B × Y^B)^(a+xA) ←── B ──           算 (A × X^A)^(b+yB)

驗證兩邊得到同樣的值

Alice:(B × Y^B)^(a+xA) = (g^b × (g^y)^B)^(a+xA) = (g^(b+yB))^(a+xA) = g^((b+yB)(a+xA))

Bob:  (A × X^A)^(b+yB) = (g^a × (g^x)^A)^(b+yB) = (g^(a+xA))^(b+yB) = g^((a+xA)(b+yB))

圖 11-6:MQV 協定

兩者相同,都是 g^((b+yB)(a+xA))——Alice 與 Bob 共享同一個秘密。

安全性#

與鑑別式 DH 不同,MQV 無法僅靠短暫秘密外洩來攻破

知道 ab 不會讓攻擊者判定最終的共享秘密,因為他們還需要長期私鑰才能算出它。

在最強的入侵模型下呢? 若 Eve 攻陷了 Alice 的長期私鑰 x,先前建立的共享秘密仍然安全——因為它們的計算也牽涉到 Alice 的短暫私鑰。

MQV 不提供完美的前向保密,因為下面這個攻擊:

假設 Eve 攔截 Alice 的 A 訊息,換成她自己選的 A = g^a。同時 Bob 把 B 送給 Alice(Eve 記下 B 的值)並算出共享金鑰。

若 Eve 稍後攻陷了 Alice 的長期私鑰 x,她就能判定 Bob 在該工作階段所算出的金鑰——這破壞了前向保密,因為 Eve 還原了先前一次協定執行的共享秘密。

實務上這個風險可以被金鑰確認步驟消除:Alice 與 Bob 會發現他們並未共享同一把金鑰,因而在導出任何工作階段金鑰之前就中止協定。

為什麼很少人用#

儘管優雅又安全,MQV 在實務上很少被使用

  • 它曾受專利束縛,妨礙了廣泛採用。
  • 實務上要把 MQV 做對,比它看起來更難。

事實上,權衡其增加的複雜度後,MQV 的安全好處相較於更簡單的鑑別式 DH,往往被認為並不划算。