寫給開發人員的實用密碼學 - Hash算法

說到Hash(哈希),開發人員應該不陌生,比如Hash表是一種非常常用的數據結構,通過Hash表能夠根據鍵值快速找到數據。哈希函數將文本(或其他數據)映射爲整數,從而能夠提高檢索效率。

密碼學中的Hash算法和普通的Hash算法不是同一個概念,從安全的角度考慮,密碼學中的Hash算法除了有普通Hash算法的特性之外,還有其他的一些特性。

密碼學Hash算法也通常稱作摘要算法,是密碼學中的基礎算法,是現代密碼學中的核心組成部分。2004年山東大學王小云教授發表論文,指出了MD5和SHA-1兩種Hash算法的漏洞,引起了業界的恐慌,足以說明Hash算法的重要性。密碼學中有很多密碼學Hash算法,比如MD5、SHA-1、SHA128、SHA256、SHA512等,國家商用密碼中也有一個Hash算法SM3。我們不用理解Hash算法的內部實現原理,更應該關注其特性、用途以及使用中需要注意的點。

在密碼學中,Hash函數將任意大小(例如文本消息)的輸入數據轉換爲固定大小(例如256位)的結果,這稱爲哈希值(或哈希碼、消息摘要)。比如SHA-256和SHA3-256,可將任意輸入轉換爲256位輸出。

哈希算法

密碼學Hash算法示例

我們可以藉助 OpenSSL 附帶的命令行工具計算字符串"hello"的SHA256算法哈希值:

$ echo -n "hello" | openssl sha256
(stdin)= 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

也可以藉助開源國密算法庫 GmSSL 的命令行工具,計算 SM3 算法的哈希值:

$ echo -n "hello" | gmssl dgst -sm3
(stdin)= becbbfaae6548b8bf0cfcad5a27183cd1be6093b1cceccc303d9c61d0a645268

密碼學Hash算法的特點

設計一個Hash算法並不難,但要設計一個能用於密碼學上的Hash算法非常難,需要有非常深厚的數學和密碼學功底。一個設計良好的密碼學Hash算法需要具有如下特點:

  1. 確定性:相同的消息總是能得到同樣的摘要值,特定的Hash算法,不管消息長度是多少,最終的摘要值長度是相同的。

  2. 快速:計算任何給定消息的哈希值應該很快。

  3. 難以分析:對輸入消息的微小修改將完全改變輸出哈希值。

  4. 不可逆:通過摘要值很難逆向計算出原始消息,Hash算法具備單向性,摘要值是不可逆的,這也是非常重要的特性。爲了逆向計算出原始消息,唯一的方法就是採用暴力攻擊、字典攻擊、彩虹表

  5. 沒有碰撞:找到兩個具有相同哈希值的不同消息非常困難(或幾乎不可能)。

注意第5點,沒有衝突是一種理想情況,考慮到最後生成的摘要值只有固定的有限位,必然存在不同消息具有相同哈希值的情況,但這裏強調的是找到它們非常困難。後面談到 MD5 的破解將會談到。

密碼學Hash算法的用途

密碼學哈希算法用途很廣,下面看看最常見的幾個用途:

  • 文檔/消息完整性

驗證文件/文檔/消息的完整性。比如我們在網站下載文件時,網站通常會給出文件的 MD5 值或 SHA256 值。

OpenSSL源碼Hash值

通過對比哈希值,我們可以確保自己下載的文件和服務器上是一致的。

  • 存儲密碼

這個開發人員應該很熟悉,當然也有菜鳥程序員直接往數據庫中存儲明文密碼(從曝光的拖庫攻擊事件中,發現這麼做的公司還不少)。開發人員通常不將純文本密碼保存在數據庫中,而保存密碼散列值或從密碼派生的更復雜的值(例如,Scrypt派生的值)。

/etc/shadow文件

上面的示例來自現代 Linux 系統中的 /etc/shadow 文件,裏面的密碼存儲爲帶鹽的多輪SHA-512哈希值。

採用這種解決方案,即使數據庫或數據文件泄露,攻擊者也無法通過口令的摘要值計算出原始口令,攻擊者很難僞造用戶進行攻擊。

系統具體如何校驗用戶密碼呢?大概的步驟如下:

  • 用戶輸入用戶名和口令登錄。

  • 系統使用Hash算法計算出口令的摘要值。

  • 系統使用用戶名和摘要值在數據庫表中進行檢索,一旦匹配到就說明該用戶輸入的口令是正確的。

  • 生成唯一ID

生成特定文檔/消息的(幾乎)唯一ID。密碼散列函數幾乎根據文檔的內容唯一地標識文檔。當然從理論上講,任何哈希函數都可能發生碰撞,但是這種碰撞不太可能發生,因此大多數系統(如Git)都假定它們使用的哈希函數不存在碰撞。

這樣的示例有 git 版本管理系統,其每一個提交通過一個哈希值標記。

git通過哈希值標記一個提交

這個特性還可以用來比較大文件,通過計算兩個文件的Hash值,比較Hash值就可以判斷兩個文件是否相同。

  • 僞隨機數生成

僞隨機數生成和密鑰派生。生成隨機序列的一種簡單方法是這樣的:從隨機種子開始(例如鍵盤單擊或鼠標移動)。附加“1”並計算散列以獲得第一個隨機數,然後附加“2”並計算散列獲得第二個隨機數,以此類推。

  • 工作量證明算法

主要用在比特幣,也就是俗稱的挖礦。大多數工作量證明算法計算的哈希值大於特定值(稱爲挖掘難度)。爲了找到此哈希值,礦工計算了數十億個不同的哈希,並採用其中的最大哈希值,因爲哈希數是不可預測的。例如,工作證明問題的定義如下:找到一個數字p,以使hash(x + p)的開頭保留10個零位。

Hash算法一覽

在過去,軟件開發人員設計了許多密碼哈希算法。其中有些已證明不安全(例如 MD5 和 SHA1 ),有些仍被認爲是安全的(例如 SHA-2 、SHA-3 和 BLAKE2 )。下面讓我們瞭解一下目前廣泛使用的加密哈希算法。

  • MD5

MD5是一種比較常用的Hash算法,摘要值長度固定是 128 比特, MD5 算法目前被證明已經不安全了,不建議使用。

  • SHA-1

SHA-1算法類似於MD5算法,輸出的長度固定是160比特。SHA-1算法在嚴謹的加密學中已經被證明是不安全的,但在實際中仍然有使用,因爲在現實世界中要構造出碰撞還是非常困難的,需要經過大量的運算。當然在新的應用中要避免使用。

  • SHA-2

SHA-2是一系列強大的密碼哈希函數:SHA-256(256位哈希)、SHA-384(384位哈希)、SHA-512(512位哈希)等。SHA-2算法是目前建議使用的Hash算法,在美國作爲官方加密標準發佈。

從設計上講,哈希輸出的位數越多,一般而言具有更高的安全性和更高的抗衝突性。通常,128位哈希函數要比256位哈希函數要弱,而256位哈希函數要比512位哈希函數弱。因此,SHA-512比SHA-256更強大。

  • SHA-3

SHA-3算法並不是爲了取代SHA-2算法,而是一種在設計上和SHA-2完全不同的算法,主要有四種算法,分別是SHA3-256、SHA3-512、SHA3-224、SHA3-384,輸出的長度分別是256比特、512比特、224比特、384比特。

在相同的哈希長度下,SHA-3比SHA-2更安全。例如,SHA3-256比SHA-256提供更多的加密強度。

SHA-3被認爲是高度安全的,在美國作爲官方推薦的加密標準發佈。

  • SM3

SM3是國密密碼雜湊算法標準,由國家密碼管理局於2010年12月公佈。SM3的輸出雜湊值長度爲256比特(32字節),與國際標準SHA-256等長。SM3設計安全性爲128比特,安全性與256比特橢圓曲線/SM2、SM4/SMS4、AES-128等同。

小知識:王小云院士真的破解了 MD5 嗎?

2004年8月,在美國加州聖巴巴拉召開的國際密碼大會上,王小云宣讀了自己和研究團隊對於MD4、MD5、HAVAL-128和RIPEMD四個國際著名密碼算法的破譯結果。

這被認爲是2004年密碼學界最具突破性的結果,堪稱學術界的一場強烈地震。當年國際密碼大會總結報告上寫道:我們該怎麼辦?MD5被重創了,它即將從應用中淘汰。

2005年,美國《新科學家》雜誌在一篇文章中,用了頗具震撼力的標題——《崩潰!密碼學的危機》,報道了王小云團隊花10年時間取得的學術成果。

所謂的“破解”其實誤導了很多人,並不是說扔給王小云一個 MD5 散列值,然後她馬上就能算出一個原文來。從密文推算出明文理論上是不可能的,所以王小云的研究成果並不能通過 MD5 的散列值逆向推算出明文。即給定 Hash 值,王小云不能逆向計算出 M。

MD5(M)=Hash

其中 M 指密碼的明文,Hash 表示密碼散列後的密文。

實際上,王小云的研究成果如下:

MD5(M1)=MD5(M2)

即給定消息 M1,能夠計算獲取 M2,使得 M2 產生的散列值與 M1 產生的散列值相同。如此,MD5 的抗碰撞性就已經不滿足了,使得 MD5 不再是安全的散列算法。這樣一來,MD5 用於數字簽名將存在嚴重問題,因爲可以篡改原始消息,而生成相同的 Hash 值。

這裏,簡單地用王教授的碰撞法給大家舉個簡單的例子。假如用戶 A 給 B 寫了個 Email 內容爲 Hello,然後通過王教授的碰撞法,可能得到 Fuck 這個字符串的摘要信息和 Hello 這個字符串產生的摘要信息是一樣的。如果 B 收到的 Email 內容爲 Fuck,經過 MD5 計算後的,B 也將認爲 Email 並沒有被修改!但事實並非如此。

王小云院士的研究報告表明,MD4,MD5,HAVAL-128,RIPEMD 和 SHA-1 均已被證實存在上面的漏洞,即給定消息 M1,能夠找到不同消息 M2 產生相同的散列值,即產生 Hash 碰撞。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章