跳至內容
Toova
所有工具

MD5 vs SHA-256 — 為什麼應該停止使用 MD5

Toova

MD5 無所不在。它隨著每種程式語言、每個資料庫、每個雲端供應商的 SDK 一同出貨。開發者出於習慣使用它 — 它快速、產出整齊的 32 字元十六進位字串,API 只需兩行程式碼。問題是:MD5 自 2004 年起就在密碼學上被破解,而攻擊只變得更快、更便宜。

這並非理論。2012 年針對伊朗基礎設施的網路攻擊 — Flame 惡意軟體 — 透過利用 MD5 碰撞偽造了微軟程式碼簽署憑證。學術密碼學家在論文中展示的相同技術,變成了地緣政治間諜活動中使用的武器。MD5 並非略為削弱;它對任何攻擊者能選擇輸入的應用都已根本受損。

SHA-256 屬於 NIST 標準化的 SHA-2 家族,沒有已知的碰撞攻擊,在 2026 年仍是密碼學完整性的標準。本文準確解釋差異代表的意義、何時 MD5 仍可接受(罕見),以及如何安全遷移。你可以使用 Toova MD5 雜湊Toova SHA-256 雜湊工具即時運算兩種雜湊。

雜湊函數如何運作

密碼學雜湊函數接受任意長度的輸入,並產出具下列特性的固定長度輸出(摘要):

  • 具決定性:相同輸入永遠產出相同輸出。
  • 雪崩效應:輸入中單一位元變動會完全改變輸出。
  • 原像抗性:給定雜湊,在運算上不可行找出輸入。
  • 碰撞抗性:在運算上不可行找出兩個產出相同雜湊的不同輸入。

雪崩效應是為何 MD5 與 SHA-256 乍看相似的原因:

MD5("The quick brown fox jumps over the lazy dog")
= 9e107d9d372bb6826bd81d3542a419d6

MD5("The quick brown fox jumps over the lazy cog")
= 1055d3e698d289f2af8663725127bd4b
SHA-256("The quick brown fox jumps over the lazy dog")
= d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592

SHA-256("The quick brown fox jumps over the lazy cog")
= e4c4d8f3bf76b692de791a173e05321150f7a345b46484fe427f6acc7ecc81be

輸入中改了一個字元("dog" → "cog"),輸出卻完全不同。此特性對兩種演算法都成立。差異在於當「攻擊者」刻意嘗試找出碰撞時會發生什麼事。

MD5 — 失敗的時間軸(1996–2025)

MD5 由 Ron Rivest 於 1991 年設計,作為 MD4 的替代品。到 1996 年,Hans Dobbertin 在 MD5 的壓縮函數中找到碰撞 — 並非完整演算法,但這是設計脆弱的警訊。資安社群開始建議遷移到 SHA-1。多數系統忽略了這點。

2004 — 展示完整碰撞

2004 年 8 月,王小雲與余宏波在 CRYPTO 會議上發表了 MD5 的實際碰撞攻擊。他們能在叢集上一小時內產出兩個具相同 MD5 雜湊的不同 1,024 位元訊息。MD5 的基本保證 — 碰撞抗性 — 被破解了。

NIST 立即開始為聯邦使用棄用 MD5。多數產業指引隨後跟進。MD5 在生產系統中的實際部署幾乎未改變。

2008 — 流氓 CA 憑證

一群研究者(Sotirov、Stevens 等人)展示了他們能建立會被所有主要瀏覽器信任的流氓憑證頒發機構憑證。攻擊利用了多家憑證頒發機構仍以 MD5 簽署憑證的事實。研究者在看似合法的憑證請求與自製 CA 憑證之間產生碰撞 — 然後讓真正的 CA 簽署合法的那個,產出對偽造的 CA 憑證也有效的簽章。

每個主要瀏覽器立即封鎖了 MD5 簽署的憑證。多數憑證頒發機構停止頒發。一項主要教訓:當攻擊者能控制雜湊函數的輸入時,密碼學弱點就會變得可被利用。

2012 — Flame 惡意軟體

2012 年發現並歸因於國家行動者的 Flame 網路間諜惡意軟體,利用選擇前綴 MD5 碰撞偽造了微軟 Windows Update 憑證。攻擊比 2008 年的展示更精密:攻擊者能在微軟簽署基礎設施會不知情合作的條件下,製作出與合法微軟憑證碰撞的惡意載荷。

結果:Flame 能透過 Windows Update 散播自己,看起來像是合法的微軟更新,並具有有效的微軟簽章。伊朗、黎巴嫩、敘利亞與蘇丹有數十萬台 Windows 機器遭感染。這是 MD5 碰撞攻擊在國家層級規模上的真實世界利用。完整歷史請見 Flame 惡意軟體的 Wikipedia 文章

2019–2025 — HashClash 與即時碰撞

HashClash 專案(Marc Stevens,CWI Amsterdam)持續將 MD5 碰撞產生推到實務極限。到 2019 年,選擇前綴 MD5 碰撞 — 攻擊者能為兩個碰撞訊息選擇任意前綴 — 能在一般商用硬體上幾天內產出。到 2022 年,最佳化實作將此縮短至數小時。2024 年,一篇 HashClash 論文展示了在單一現代 GPU 上不到一分鐘的碰撞。

趨勢很清楚:MD5 碰撞攻擊並未因硬體改進而變難 — 而是變得更容易。2004 年需要叢集才能做到的事,2026 年用筆電就能做到。

SHA-256 — 為何屹立不搖

SHA-256 屬於 SHA-2 家族,由 NSA 設計,並由 NIST 於 2001 年標準化。它產出 256 位元(32 位元組)摘要。到 2026 年,沒有針對 SHA-256 的已知實際碰撞攻擊。已發表的最佳攻擊將找出碰撞的理論工作因子降至約 2^187 次運算 — 仍遠超任何存在或可預見的計算資源。

SHA-256 的資安裕度刻意保守。即使硬體改進十億倍(在摩爾定律詞彙中約為 30 次加倍),破解 SHA-256 在運算上仍不可行。MD5 的 2^18 至 2^23 有效碰撞工作因子在 2004 年就已在普通硬體可及範圍內。

SHA-256 也比你想像中快:現代 CPU 包含專用 SHA 指令(Intel SHA Extensions、ARM Cryptography Extensions),讓軟體每核心每秒能運算數百萬次 SHA-256 雜湊。對典型用例而言,它並未明顯比 MD5 慢。

MD5 仍可接受的時機(罕見)

「破解」並不代表「對所有用途都無用」。MD5 在以下情境中仍可接受:

  • 沒有對手:在受信任的內部系統中偵測意外檔案毀損 — 並非驗證來自網際網路的下載,而是檢查檔案複製是否成功完成。
  • 速度比安全更重要:運算快取鍵或分片識別碼,其中碰撞只代表快取未命中,而非資安漏洞。攻擊者模型不存在。
  • 你要對應現有外部系統:某些舊 API 仍傳送 MD5 ETag 或 checksum。你可以接受並運算 MD5 以互通,只要你不用於資安決策即可。
  • 雜湊表分區:依鍵的 MD5 將資料分散到不同桶中。此處的碰撞會造成不平衡,而非資安失敗。

共通點:當應用不依賴碰撞抗性,且沒有能製作輸入的對手時,MD5 可接受。一旦任一條件被破壞 — 出現攻擊者,或碰撞等同於資安失敗 — 就切換到 SHA-256。

關於 MD5 的常見迷思

「加鹽就 OK」

加鹽會改變輸入,讓使用相同密碼的兩個使用者取得不同雜湊 — 它能防止彩虹表攻擊。但它並未修正碰撞問題。擁有加鹽 MD5 雜湊的攻擊者仍能高效暴力破解它,因為 MD5 很快:現代 GPU 每秒運算約 100–300 億次 MD5 雜湊。鹽新增的工作量與搜尋空間成比例,而非與演算法的難度成比例。

對於密碼雜湊,不論是否加鹽,MD5 與 SHA-256 都不合適。請使用 bcrypt、scrypt 或 Argon2。

「我們只在內部使用就 OK」

內部系統會被入侵。「攻擊者無法存取我們的輸入」這個威脅模型,通常會在供應鏈攻擊、內部威脅或設定錯誤暴露系統前都成立。Flame 攻擊發生在那些對內部控制應有類似信心的系統上。

「SHA-256 太過頭 — MD5 比較快」

在具 SHA 加速指令的現代硬體上,SHA-256 約比 MD5 慢 2–5 倍。對於多數應用 — 檔案完整性檢查、API 簽章、快取鍵 — 差異是每次運算數微秒,實務上不會被注意到。MD5 優於 SHA-256 的效能論點只在極高吞吐量情境下才成立,即使如此,通常也有比使用破解演算法更好的解法。

遷移指南 — MD5 至 SHA-256

密碼雜湊

// 錯誤:使用 MD5 進行密碼雜湊
const crypto = require('crypto');
const hash = crypto.createHash('md5').update(password).digest('hex');
// 現代 GPU 破解時間:幾秒到幾分鐘
// 錯誤:使用 SHA-256 進行密碼雜湊(仍然太快)
const crypto = require('crypto');
const hash = crypto.createHash('sha256').update(password).digest('hex');

// 正確:對密碼使用 bcrypt、scrypt 或 Argon2
const bcrypt = require('bcrypt');
const hash = await bcrypt.hash(password, 12);

遷移已儲存的密碼雜湊需要漸進做法。每次成功登入時:對照現有 MD5 雜湊驗證密碼,然後立即用 bcrypt 重新雜湊並取代儲存的值。將每個帳戶標記為已遷移。經過合理期間後(通常 90 天),強制任何仍使用 MD5 雜湊的帳戶重設密碼。

檔案完整性 / checksum

# Linux:驗證下載的檔案
sha256sum -c ubuntu-24.04-desktop-amd64.iso.sha256

# macOS
shasum -a 256 ubuntu-24.04-desktop-amd64.iso

# Windows PowerShell
Get-FileHash ubuntu-24.04-desktop-amd64.iso -Algorithm SHA256

將檔案完整性檢查從 MD5 切換到 SHA-256,通常在程式碼中只是簡單的搜尋取代。兩個陷阱:(1) 儲存在資料庫或檔案中的現有 checksum 需要重新運算與更新 — 沒有捷徑;(2) 提供 MD5 ETag 的外部 API 或儲存系統(例如某些 S3 設定)需要協調以切換。

用於 API 認證的 HMAC

// HMAC-SHA-256 用於訊息認證
const crypto = require('crypto');
const hmac = crypto.createHmac('sha256', process.env.SECRET_KEY)
  .update(message)
  .digest('hex');

如果你使用 HMAC-MD5 進行 API 請求簽署,請切換到 HMAC-SHA-256。HMAC 建構增加了密鑰,限制了部分 MD5 攻擊,但 HMAC-MD5 有長度延伸漏洞,且底層原語仍受損。現代標準(JWT、AWS SigV4、OAuth 2.0)皆規定 HMAC-SHA-256。Toova 的 HMAC 產生器支援 HMAC-SHA-256 與 HMAC-SHA-512 以利測試。

數位簽章與憑證

任何以 MD5 簽署的憑證應立即重新頒發 — 多數憑證頒發機構在 2008 年後停止頒發 MD5 簽署的憑證,所有主要瀏覽器與作業系統都拒絕它們。對於內部 PKI,稽核你的 CA 設定,並確保 SHA-256 是最低允許的簽章演算法。RSA-SHA256 或 ECDSA-SHA256 是目前標準。

MD5 vs SHA-256 — 快速參考

特性 MD5 SHA-256
輸出長度 128 位元(32 個十六進位字元) 256 位元(64 個十六進位字元)
碰撞抗性 已破解(實際攻擊) 安全(無已知攻擊)
密碼雜湊 永不 否(使用 bcrypt/Argon2)
數位簽章 永不
檔案完整性(資安) 永不
非資安 checksum 可接受(無攻擊者) 永遠可以
快取鍵 可接受 永遠可以
TLS 憑證簽署 被瀏覽器拒絕 標準
FIPS 140-3 合規 否(已棄用)

結論

MD5 自 2004 年起就在密碼學上被破解。選擇前綴碰撞 — 驅動 Flame 惡意軟體的技術 — 在運算上現已成本低廉。任何依賴 MD5 進行資安的應用(簽章、完整性驗證、認證)都易受成本僅幾分鐘運算時間就能執行的攻擊。

SHA-256 沒有已知的實際攻擊,在現代 CPU 上有硬體加速,且是 TLS、程式碼簽署與 API 認證中密碼學完整性的標準。對幾乎所有用例而言,相較 MD5 的效能成本可忽略不計。

遷移路徑很直接:檔案完整性檢查是搜尋取代。API 簽章需要協調版本提升。密碼雜湊需要登入時的漸進重新雜湊策略。對於任何新程式碼,SHA-256 應為預設選擇。直接使用 Toova MD5Toova SHA-256 運算並比較雜湊 — 或使用 HMAC 產生器產生 HMAC-SHA-256 認證碼。