MD5 還安全嗎?雜湊演算法安全性比較

先講結論:MD5 不安全

如果你只想知道答案:MD5 用於任何需要對抗惡意攻擊者的場景都不安全,SHA-1 也一樣。這兩者都已被找出實際可行的碰撞攻擊,不應再用於數位簽章、防竄改驗證或密碼儲存。它們唯一還算堪用的場景,是在沒有惡意對手的前提下做快速校驗,例如確認檔案在傳輸過程中沒有意外損壞。

至於為什麼,以及什麼才是正確做法,下面逐一說明。

碰撞攻擊是什麼?

雜湊函數把任意輸入壓成固定長度的輸出,由於輸入無限多、輸出數量有限,理論上一定存在兩個不同輸入產生相同雜湊值的情況,這就叫「碰撞」(Collision)。碰撞無法完全避免,但一個安全的雜湊函數必須讓「刻意製造碰撞」在計算上不可行。

所謂「被攻破」,指的就是有人找到了比暴力破解快得多的方法來製造碰撞:

碰撞為什麼危險?想像攻擊者準備兩份合約,一份無害、一份惡意,兩者 MD5 相同。他讓你對無害版本簽章,事後卻把簽章套到惡意版本上——因為雜湊值一樣,簽章照樣驗證通過。這就是碰撞攻擊的實際威脅。

小提示:碰撞攻擊針對的是「能不能找到任意兩個相同雜湊的輸入」。密碼破解則是另一種攻擊——已知雜湊值,反推出原始密碼,這要靠下面講的彩虹表與字典攻擊。

彩虹表與預運算攻擊

雜湊雖然不可逆,但如果密碼太常見,攻擊者可以「事先把答案算好」。做法是預先計算海量常見密碼的雜湊值,存成一張對照表,破解時直接查表即可。最有名的優化版本叫「彩虹表」(Rainbow Table),它用一種時間換空間的鏈結技巧,大幅縮小儲存量。

結果就是:若你的網站直接把密碼的 MD5 或 SHA-256 存進資料庫,一旦資料庫外洩,攻擊者拿現成的彩虹表一查,大量弱密碼瞬間還原成明文。這裡的問題不在於演算法被攻破,而在於「沒有加鹽」以及「演算法太快」。

加鹽:對抗彩虹表的方法

「鹽」(Salt)是一段隨機字串,在計算雜湊前先和密碼拼接在一起。例如使用者密碼是 1234,系統幫他產生隨機鹽 a8Kx9q,實際儲存的是 hash("1234" + "a8Kx9q"),並把鹽一起存起來。

加鹽帶來兩個關鍵效果:

鹽不需要保密,重點是它必須隨機、夠長,而且每個使用者都不一樣。

密碼別用一般雜湊,請用 bcrypt 或 Argon2

就算加了鹽,MD5、SHA-256 這類通用雜湊還是不適合存密碼,原因是它們「太快」。這些演算法設計目的是高速處理大量資料,但快對密碼來說是缺點——攻擊者拿到外洩的雜湊後,可以用 GPU 每秒嘗試數十億組密碼來暴力破解。

正確做法是使用專為密碼設計的「慢速」雜湊函數,它們刻意耗費運算資源,可調整成本參數讓單次運算花上零點幾秒,對正常登入無感,卻讓大規模暴力破解變得極度昂貴:

這些函數通常內建鹽的處理,你不必自己拼接,使用對應函式庫即可。

小提示:判斷一個系統的密碼儲存是否安全,問一句話就夠了——「你們用什麼演算法存密碼?」若答案是 MD5、SHA-1 甚至 SHA-256,那就有問題;若是 bcrypt 或 Argon2,方向才正確。

各演算法安全性比較

演算法類型抗碰撞適合存密碼
MD5通用雜湊已攻破
SHA-1通用雜湊已攻破
SHA-256通用雜湊目前安全否(太快)
SHA-512通用雜湊目前安全否(太快)
bcrypt密碼雜湊不適用
Argon2密碼雜湊不適用是(首選)

注意「抗碰撞」與「適合存密碼」是兩個不同維度。SHA-256 抗碰撞沒問題,可以放心用於檔案校驗與數位簽章,但因為運算太快,並不適合直接拿來存密碼。

如何選對演算法

想實際體驗 MD5 與 SHA 系列算出來的差異,可以用本站工具同時計算多種演算法,直觀比較它們的輸出長度與結果。

立即使用雜湊值產生器