土薯工具 Toolshu.com 登錄 用戶注冊

MD5 是哈希不是加密:原理、破解方式與密碼存儲的正確姿勢

原創 作者:bhnw 於 2026-04-06 22:51 發佈 3次瀏覽 收藏 (0)

MD5 到底是什麼

很多人把 MD5 叫做"MD5加密",這個說法從一開始就是錯的。

MD5 是一種哈希函數(Hash Function),不是加密算法。兩者有本質區別:

  • 加密:可逆操作,有密鑰,能解密還原原始數據
  • 哈希:不可逆操作,無密鑰,理論上無法從結果推回原始數據

MD5 的作用是把任意長度的輸入,變成一個固定 128 位(32個十六進制字符)的輸出,稱爲"摘要"或"指紋"。

MD5("hello")    = 5d41402abc4b2a76b9719d911017c592
MD5("hello!")   = 9b56e4f280d7b27a6c8d0c11d5a8cb7d
MD5("一篇很長的文章...") = d41d8cd98f00b204e9800998ecf8427e

三個特性:

  1. 單向性:無法從哈希值逆推原始內容
  2. 固定長度:無論輸入多長,輸出始終 32 位
  3. 雪崩效應:輸入改動一個字節,輸出完全不同

MD5 能被"破解"嗎

嚴格來說,MD5 無法被"解密"——因爲它不是加密。但它可以被暴力破解查表攻擊

暴力破解

最簡單的思路:把常見密碼逐個計算 MD5,和目標哈希值對比。

計算 MD5("123456")    = e10adc3949ba59abbe56e057f20f883e  ← 匹配!

現代 GPU 每秒可以計算數十億次 MD5,123456passwordqwerty 這類常見密碼在不到一秒內就能找到。

彩虹表攻擊

暴力破解需要實時計算,而彩虹表是預先計算好的海量明文-哈希值對照表,空間換時間。

攻擊者拿到一個 MD5 哈希值,直接在表裏查找,瞬間得到原始密碼。網上有公開的 MD5 彩虹表,覆蓋數百億條常見密碼和短字符串組合。

實際上,很多"MD5在線解密"網站的原理就是這個——它們維護了一張巨大的哈希-明文數據庫,輸入哈希值查表返回結果,不是真正的"解密"。

MD5 碰撞

2004年,研究人員找到了 MD5 的碰撞攻擊方法:可以構造出兩個不同的輸入,產生完全相同的 MD5 值。這從根本上動搖了 MD5 作爲完整性校驗工具的可信度。

文件A 和 文件B 內容完全不同,但 MD5 值完全相同

這意味着攻擊者可以僞造一個與合法文件 MD5 值相同的惡意文件,繞過完整性校驗。


爲什麼還有人用 MD5 存密碼

歷史原因。MD5 在 1991 年發佈時被認爲足夠安全,大量早期系統將其用於密碼存儲。隨着計算能力的提升和攻擊方法的演進,MD5 的安全性早已不夠,但遺留系統的遷移成本很高,導致至今仍有系統在用。

2012年 LinkedIn 數據泄露事件中,約 650 萬條密碼以未加鹽的 SHA-1 哈希存儲;更早的數據泄露中,大量網站使用的正是裸 MD5。泄露後,攻擊者在數小時內就破解了絕大多數密碼。


正確的密碼存儲方案

加鹽(Salt)

給每個密碼在哈希前拼接一段隨機字符串(鹽值),使得相同的密碼產生不同的哈希結果,從而讓彩虹表完全失效。

salt = "xK92mP"  // 每個用戶隨機生成,存入數據庫
hash = MD5(password + salt)

但即便加鹽,MD5 本身計算太快,GPU 暴力破解仍然可行。

bcrypt:專爲密碼存儲設計

bcrypt 是目前最主流的密碼哈希方案,有幾個關鍵特性:

1. 內置鹽值:每次哈希自動生成隨機鹽,無需手動處理。

2. 計算成本可調:通過 cost factor 參數控制哈希運算的計算量,隨硬件提升可以相應調高,保持破解難度。

3. 故意很慢:正常用戶登錄只需驗證一次,慢一點無所謂;但攻擊者需要暴力嘗試數十億次,慢就是致命的。

import bcrypt

# 註冊:生成哈希
password = b"user_password"
hashed = bcrypt.hashpw(password, bcrypt.gensalt(rounds=12))
# 存入數據庫的是 hashed,不是原始密碼

# 登錄:驗證
bcrypt.checkpw(password, hashed)  # 返回 True/False

Argon2:更現代的選擇

Argon2 是 2015 年密碼哈希競賽的冠軍算法,在 bcrypt 基礎上增加了內存佔用控制,進一步提升了對 GPU 和 ASIC 暴力破解的抵抗力。新項目首選 Argon2id。

from argon2 import PasswordHasher

ph = PasswordHasher(time_cost=2, memory_cost=65536, parallelism=2)
hashed = ph.hash("user_password")
ph.verify(hashed, "user_password")  # 驗證

scrypt

與 Argon2 類似,也是內存密集型哈希,Node.js 標準庫內置支持,適合 JavaScript 後端。


MD5 現在還能用在哪裏

MD5 不適合安全場景,但在以下非安全場景中仍然合理:

文件完整性校驗(非安全環境)

下載文件後對比 MD5 值,確認文件未被損壞(注意:不能防止有意篡改,只能檢測傳輸錯誤)。

# Linux/macOS
md5sum filename.zip

# macOS
md5 filename.zip

生成唯一標識符

對內容取 MD5 作爲緩存 key、去重 ID 等,不涉及安全的場景。

數據庫內容去重

對大文本字段取 MD5 建索引,快速判斷是否重複。

非安全場景的數據指紋

日誌系統、數據管道里對數據做快速摘要,用於追蹤和對比。


一句話總結

場景 推薦方案
用戶密碼存儲 bcrypt 或 Argon2id
文件完整性校驗(安全) SHA-256
文件完整性校驗(非安全) MD5 可用
數字簽名 RSA + SHA-256
緩存 Key / 去重 ID MD5 可用

密碼存儲永遠不要用 MD5,不管加不加鹽。


在線工具

如果你需要計算一段文本的 MD5 值用於數據校驗或測試,可以使用 toolshu.com 的 MD5 在線加密工具,支持 16 位和 32 位輸出,大小寫均可,在瀏覽器本地運算不上傳數據。

发现周边 发现周边
評論區

加載中...