MD5 是什麼?雜湊函數原理、碰撞風險與正確使用情境

下載一個大型檔案後,網站旁邊通常會附上一串像 d41d8cd98f00b204e9800998ecf8427e 的奇怪字串,旁邊寫著「MD5」。這是什麼?它能告訴你什麼?本文從雜湊函數的基本概念出發,完整說明 MD5 的工作原理、安全性現況,以及在不同場景下應該如何選擇合適的雜湊演算法。

1. 什麼是雜湊函數?

雜湊函數(Hash Function)是一種將任意長度的輸入資料轉換成固定長度輸出值(稱為「雜湊值」或「摘要」)的數學函數。好的雜湊函數具備以下性質:

  • 確定性:相同的輸入永遠產生相同的輸出
  • 固定長度輸出:不論輸入多長,輸出長度固定(MD5 為 128 位元 = 32 個十六進位字元)
  • 雪崩效應:輸入改變一個位元,輸出結果會大幅改變(約 50% 的位元翻轉)
  • 單向性:從雜湊值無法(或極難)反推原始輸入
  • 抗碰撞性:難以找到兩個不同的輸入產生相同的輸出
雜湊 ≠ 加密
加密是可逆的(有金鑰才能解密),雜湊是單向的(無法還原)。兩者用途不同,不應混淆。

2. MD5 的運作原理

MD5(Message Digest Algorithm 5)由 Ron Rivest 於 1991 年設計,是 MD4 的改良版。它的輸出為 128 位元(16 位元組),通常以 32 個十六進位字元表示。

2.1 處理流程概述

  1. 填充(Padding):將輸入資料填充至長度符合特定規格(模 512 = 448 位元),末尾附上原始長度的 64 位元表示
  2. 初始化:設定四個 32 位元的初始雜湊值(A、B、C、D)
  3. 分塊處理:將填充後的資料切成 512 位元的區塊,每塊通過 4 輪共 64 次非線性運算處理
  4. 輸出:將最終的四個 32 位元值(A、B、C、D)串接,得到 128 位元的摘要

2.2 範例

同樣的輸入永遠得到同樣的 MD5:

MD5("") = d41d8cd98f00b204e9800998ecf8427e
MD5("hello") = 5d41402abc4b2a76b9719d911017c592
MD5("Hello") = 8b1a9953c4611296a827abf8c47804d7

注意 "hello" 與 "Hello" 僅差一個大小寫,MD5 值卻完全不同——這就是「雪崩效應」的體現。

3. MD5 的安全性問題

3.1 碰撞攻擊(Collision Attack)

2004 年,王小雲教授團隊成功找到 MD5 的碰撞——即兩個不同的輸入,產生完全相同的 MD5 值。這意味著攻擊者可以偽造一個與合法檔案 MD5 相同的惡意檔案,繞過完整性驗證。

2008 年,研究人員更進一步利用 MD5 碰撞偽造了 SSL 憑證,展示了現實世界的攻擊可能性。

3.2 彩虹表攻擊(Rainbow Table Attack)

由於 MD5 運算速度極快(現代 GPU 每秒可計算數十億個 MD5),攻擊者可以預先建立大量「原文→MD5 值」的對照表(彩虹表),以空間換時間,快速反查密碼的明文。

這就是為什麼現代密碼儲存絕對不應直接使用 MD5(或 SHA-1、SHA-256)——即使加了「加鹽(salt)」,也不如專為密碼設計的函數安全。

3.3 長度延伸攻擊(Length Extension Attack)

MD5(以及 SHA-1、SHA-256)存在長度延伸攻擊的弱點,攻擊者在不知道原始資料的情況下,仍可能偽造有效的 MAC(訊息認證碼)。SHA-3 和 HMAC 結構不受此攻擊影響。

4. MD5 vs 其他雜湊演算法

演算法輸出長度安全性速度適用場景
MD5 128 bit 已破解(碰撞已知) 極快 非安全性用途的校驗碼
SHA-1 160 bit 已破解(2017 年實際碰撞) 不建議新系統使用
SHA-256 256 bit 安全(目前無已知碰撞) 中等 數位簽章、憑證、一般安全用途
SHA-3 可變 安全(不同設計原理) 較慢 高安全性需求
bcrypt 固定 專為密碼設計,抗暴力破解 慢(刻意設計) 密碼儲存
Argon2 可變 密碼雜湊冠軍(PHC 2015) 慢(刻意設計) 密碼儲存(推薦)

5. MD5 的正確使用場景

儘管 MD5 存在安全問題,仍有一些場景適合使用它:

5.1 ✅ 非安全性的檔案完整性驗證

確認檔案在下載或傳輸過程中沒有損毀(注意:無法防止惡意竄改)。例如:軟體官網提供 MD5 讓使用者確認下載檔案未損壞。若擔心遭到惡意篡改,應改用 SHA-256。

5.2 ✅ 資料去重與快取鍵

用 MD5 作為資料內容的唯一識別碼,判斷兩份資料是否相同,或作為快取系統的鍵值。這不涉及安全性,僅利用 MD5 的確定性與速度。

5.3 ✅ 非密碼性的資料索引

對大量文字(如使用者輸入、URL)計算 MD5 作為資料庫索引鍵,利用其固定長度與均勻分布的特性,提升查詢效率。

5.4 ❌ 密碼儲存

絕對不要用 MD5(或任何通用雜湊函數)儲存密碼。應使用 bcrypt、Argon2、scrypt 等專為密碼設計的函數,它們的慢速計算特性能有效抵抗暴力破解。

5.5 ❌ 數位簽章與憑證

MD5 的碰撞弱點使其不適合用於 X.509 憑證簽章、程式碼簽署或任何需要防偽造的情境。應使用 SHA-256 或更強的演算法。

5.6 ❌ HMAC 的底層雜湊

雖然 HMAC-MD5 在理論上比裸 MD5 安全,但現代系統仍建議改用 HMAC-SHA256。

6. 如何計算 MD5?

各種環境下計算 MD5 的方法:

# 命令列(Linux/macOS)
md5sum file.txt          # Linux
md5 file.txt             # macOS

# PHP
md5('hello')             // 5d41402abc4b2a76b9719d911017c592
md5_file('file.txt')     // 計算檔案的 MD5

# Python
import hashlib
hashlib.md5(b'hello').hexdigest()

# JavaScript
// 需要外部套件,如 crypto-js
CryptoJS.MD5('hello').toString()

或使用本站的 MD5 工具,直接在瀏覽器中計算文字的 MD5 值,無需安裝任何軟體。

7. 常見問題

7.1 MD5 與 Base64 有什麼不同?

MD5 是雜湊(單向,不可逆),Base64 是編碼(雙向,可逆)。兩者性質完全不同,混淆使用會造成安全問題。

7.2 加鹽(Salt)能讓 MD5 用於密碼儲存嗎?

加鹽可以防止彩虹表攻擊,但無法解決 MD5 速度過快的根本問題。即使加了鹽,現代 GPU 仍可每秒嘗試數十億次,短密碼仍在幾秒內被破解。請改用 bcrypt 或 Argon2。

7.3 什麼是「MD5 碰撞」,為什麼重要?

碰撞指兩個不同的輸入產生相同的 MD5 值。現實中已有工具可在幾秒內生成 MD5 碰撞,這意味著攻擊者可以製造一個「看起來合法」(MD5 相同)的惡意檔案,欺騙依賴 MD5 驗證的系統。

8. 小結

MD5 是一個設計優秀、使用廣泛的雜湊演算法,但其安全性已在密碼學上被攻破。理解 MD5 的適用邊界,是每位開發者的基本素養:它適合用於非安全性的完整性驗證與資料識別,但不應用於密碼儲存、數位簽章或任何需要抵抗惡意攻擊的場景。在這些情境下,SHA-256(一般用途)或 Argon2(密碼)是更安全的選擇。