Hash 算法與數字摘要

定義

Hash(哈希或散列)算法,又常被稱為指紋(fingerprint)或摘要(digest)算法,是非常基礎也非常重要的一類算法。可以將任意長度的二進制明文串映射為較短的(通常是固定長度的)二進制串(Hash 值),並且不同的明文很難映射為相同的 Hash 值。

例如計算 “hello blockchain world, this is yeasy@github” 的 SHA-256 Hash 值。

$ echo "hello blockchain world, this is yeasy@github"|shasum -a 256
db8305d71a9f2f90a3e118a9b49a4c381d2b80cf7bcef81930f30ab1832a3c90

對於某個文件,無需查看其內容,只要其 SHA-256 Hash 計算後結果同樣為 db8305d71a9f2f90a3e118a9b49a4c381d2b80cf7bcef81930f30ab1832a3c90,則說明文件內容(極大的概率)就是 “hello blockchain world, this is yeasy@github”。

除了快速對比內容外,Hash 思想也經常被應用到基於內容的編址或命名算法中。

一個優秀的 Hash 算法,將能滿足:

  • 正向快速:給定原文和 Hash 算法,在有限時間和有限資源內能計算得到 Hash 值;

  • 逆向困難:給定(若干)Hash 值,在有限時間內無法(基本不可能)逆推出原文;

  • 輸入敏感:原始輸入信息發生任何改變,新產生的 Hash 值都應該發生很大變化;

  • 碰撞避免:很難找到兩段內容不同的明文,使得它們的 Hash 值一致(即發生碰撞)。

碰撞避免有時候又被稱為“抗碰撞性”,可分為“弱抗碰撞性”和“強抗碰撞性”。給定原文前提下,無法找到與之碰撞的其它原文,則算法具有“弱抗碰撞性”;更一般地,如果無法找到任意兩個可碰撞的原文,則稱算法具有“強抗碰撞性”。

很多場景下,也往往要求算法對於任意長的輸入內容,輸出為定長的 Hash 結果。

常見算法

目前常見的 Hash 算法包括國際上的 Message Digest(MD)系列和 Secure Hash Algorithm(SHA)系列算法,以及國內的 SM3 算法。

MD 算法主要包括 MD4 和 MD5 兩個算法。MD4(RFC 1320)是 MIT 的 Ronald L. Rivest 在 1990 年設計的,其輸出為 128 位。MD4 已證明不夠安全。MD5(RFC 1321)是 Rivest 於 1991 年對 MD4 的改進版本。它對輸入仍以 512 位進行分組,其輸出是 128 位。MD5 比 MD4 更加安全,但過程更加複雜,計算速度要慢一點。MD5 已於 2004 年被成功碰撞,其安全性已不足應用於商業場景。。

SHA 算法由美國國家標準與技術院(National Institute of Standards and Technology,NIST)徵集制定。首個實現 SHA-0 算法於 1993 年問世,1998 年即遭破解。隨後的修訂版本 SHA-1 算法在 1995 年面世,它的輸出為長度 160 位的 Hash 值,安全性更好。SHA-1 設計採用了 MD4 算法類似原理。SHA-1 已於 2005 年被成功碰撞,意味著無法滿足商用需求。

為了提高安全性,NIST 後來制定出更安全的 SHA-224、SHA-256、SHA-384,和 SHA-512 算法(統稱為 SHA-2 算法)。新一代的 SHA-3 相關算法也正在研究中。

此外,中國密碼管理局於 2010 年 12 月 17 日發佈了GM/T 0004-2012 《SM3 密碼雜湊算法》,建立了國內商用密碼體系中的公開 Hash 算法標準,已經被廣泛應用在數字簽名和認證等場景中。

注:MD5 和 SHA-1 算法的破解工作都是由清華大學教授、中國科學院院士王小云主導完成。

性能

大多數 Hash 算法都是計算敏感型算法,在強大的計算芯片上完成的更快。因此要提升 Hash 計算的性能可以考慮硬件加速。例如採用普通 FPGA 來計算 SHA-256 值,可以輕易達到數 Gbps 的吞吐量,使用專用芯片甚至會更高。

也有一些 Hash 算法不是計算敏感型的。例如 scrypt算法,計算過程需要大量的內存資源,因此很難通過選用高性能芯片來加速 Hash 計算。這樣的算法可以有效防範採用專用芯片進行算力攻擊。

數字摘要

數字摘要是 Hash 算法重要用途之一。顧名思義,數字摘要是對原始的數字內容進行 Hash 運算,獲取唯一的摘要值。

利用 Hash 函數抗碰撞性特點,數字摘要可以檢測內容是否被篡改過。

細心的讀者可能會注意到,有些網站在提供文件下載時,會同時提供相應的數字摘要值。用戶下載原始文件後可以在本地自行計算摘要值,並與所提供摘要值進行比對,以確保文件內容沒有被篡改過。

Hash 攻擊與防護

Hash 算法並不是一種加密算法,不能用於對信息的保護。

但 Hash 算法可被應用到對登錄口令的保存上。例如網站登錄時需要驗證用戶名和密碼,如果網站後臺直接保存用戶的口令原文,一旦發生數據庫洩露後果不堪設想(事實上,網站數據庫洩露事件在國內外都不少見)。

利用 Hash 的防碰撞特性,後臺數據庫可以僅保存用戶口令的 Hash 值,這樣每次通過 Hash 值比對,即可判斷輸入口令是否正確。即便數據庫洩露了,攻擊者也無法輕易從 Hash 值還原回口令。

然而,有時用戶設置口令的安全強度不夠,採用了一些常見的字符串,如 password、123456 等。有人專門蒐集了這些常見口令,計算對應的 Hash 值,製作成字典。這樣通過 Hash 值可以快速反查到原始口令。這一類型以空間換時間的攻擊方法包括字典攻擊和彩虹表攻擊(只保存一條 Hash 鏈的首尾值,相對字典攻擊可以節省存儲空間)等。

為了防範這一類攻擊,可以採用加鹽(Salt)的方法。保存的不是原文的直接 Hash 值,而是原文再加上一段隨機字符串(即“鹽”)之後的 Hash 值。Hash 結果和“鹽”分別存放在不同的地方,這樣只要不是兩者同時洩露,攻擊者很難進行破解。

Last updated