如何讓PGP短密鑰ID免于碰撞攻擊?
針對開發(fā)人員的碰撞攻擊讓我們發(fā)現(xiàn)Pretty Good Privacy(PGP)短ID的漏洞,該漏洞允許攻擊者創(chuàng)建假ID密鑰,這會給收件人解密或驗證郵件制造問題。那么,這個漏洞的工作原理是什么,以及為什么短密鑰ID會成為問題?
Michael Cobb:當為電子郵件、文檔或文件創(chuàng)建哈希值或者消息摘要時,需要通過使用密碼散列函數(shù)來生成內(nèi)容的短數(shù)字指紋,這種數(shù)學算法會將任意大小的數(shù)據(jù)映射到短的固定長度值作為其唯一標識。哈希值被廣泛用于安全的很多方面,例如數(shù)字簽名和數(shù)據(jù)完整性檢查,人們通常會精心選擇散列函數(shù)以確保它們有較強的抗碰撞性--即兩個不同的輸入無法創(chuàng)建相同的散列值,因為攻擊者的碰撞攻擊會試圖尋找具有相同散列值的兩組不同數(shù)據(jù)片段。
而PGP是對消息或文件進行加密和數(shù)字簽名的加密工具,PGP的用戶會有公鑰和私鑰,公鑰通常在密鑰服務(wù)器發(fā)布。由于這些密鑰都非常長(通常為1024至8096位),所以我們通常使用公鑰的指紋或哈希值來標記密鑰,讓某些密鑰管理工作更容易和更快速,例如驗證屬于其他用戶的密鑰或者驗證證書頒發(fā)機構(gòu)。然而,當轉(zhuǎn)換為十六進制數(shù)字時指紋為40位,這對于人類來說仍然太長而難以使用,因此人們和很多應(yīng)用僅使用指紋的最后八位數(shù)。這被稱為短密鑰ID--長ID是指指紋的最后16位數(shù)字。下面是例子:
指紋: 0D29 F56F 12BD BA07 7B37 15AB 851F 799A B4FF 1057
長ID: 851F 799A B4FF 1057
短ID: B4FF 1057
雖然現(xiàn)代密鑰散列函數(shù)幾乎不存在具有相同哈希值的兩個輸入,但兩個哈希值最后八位數(shù)相同的幾率還是很高。事實上,我們已經(jīng)發(fā)現(xiàn)很多具有相同短密鑰ID的欺騙性PGP密鑰。
多年來,大家已經(jīng)知道這種碰撞攻擊成功的可能性。在2011年,軟件工程師Asheesh Laroia有效證明了這種攻擊的可行性,這個問題在“RFC 4880:OpenPGP Message Format”3.3章節(jié)中也有提及--“不應(yīng)該假定密鑰ID為唯一標識”。盡管如此,使用短密鑰ID仍然是常見做法,并構(gòu)成真正威脅,特別是當涉及文件下載的完整性時,例如Linux內(nèi)核。
盡管PGP本身沒有缺陷或漏洞,但使用短密鑰ID基本上是不安全的糟糕做法。用戶不應(yīng)該信任比公共PGP密鑰完整指紋更短的ID用于驗證;密鑰ID的目的是幫助搜索密鑰,而不是驗證它。用戶和軟件都需要開始顯示和檢查完整指紋,或者至少使用長ID。長密鑰ID也可能存在碰撞,但可能性較小。軟件開發(fā)人員應(yīng)該明確編寫或重新編寫代碼以包含整個指紋,畢竟云計算使得攻擊者可為長密鑰ID生成碰撞攻擊?,F(xiàn)在那些將PGP密鑰短ID印在名片背面的PGP支持者們可能會想要增加指紋的前兩位來幫助他人驗證其密鑰。