別再用 MD5 了!PHP password_hash 隨機 SALT 才是正確做法

2013 年,Yahoo 發生了史上最大規模的資料外洩事件之一,超過 30 億筆帳號 資料被竊取。當時他們所採用的密碼儲存方式是 MD5 雜湊。這在早期曾被廣泛使用,但後來被證實安全性不足。結果一旦資料庫外洩,駭客便能透過彩虹表或暴力破解,在短時間內還原大量使用者密碼。這起事件讓 Yahoo 的品牌信任度大幅受損,也成為資安領域裡經常被引用的「經典案例」,提醒開發者:弱雜湊演算法等同於沒有防護
👉 相關報導:Sophos – Yahoo breach: I’ve closed my account because it uses MD5

什麼是 password_hash

password_hash() 是 PHP 從 5.5 版本開始內建的密碼雜湊函式。它的設計初衷,就是要讓開發者不用再自己手動產生 SALT,也不用擔心演算法是否足夠安全。呼叫這個函式時,PHP 會自動幫你:

  1. 產生一組隨機 SALT。
  2. 使用強度更高的演算法(如 bcrypt 或 argon2)。
  3. 輸出包含演算法、成本參數與 SALT 的完整字串,方便未來驗證。

對開發者而言,password_hash() 最大的優勢就是「安全性與便利性兼具」。你不需要自行處理隨機數產生器或演算法更新的細節,只要呼叫一行程式碼,就能得到比 MD5 強上數百倍的安全性。

為什麼要用 password_hash?隨機 SALT 的保護機制

傳統的 MD5 或 SHA1,雖然能把明文密碼轉換成一段固定長度的字串,但有一個致命缺陷:相同的密碼永遠會得到相同的結果。這意味著只要駭客準備好一份「彩虹表」(Rainbow Table),就能快速比對出使用者的密碼。
password_hash() 與這些演算法最大的差別,在於它會自動產生 隨機 SALT(鹽值)。每次呼叫時,即使輸入同一個密碼,最終雜湊結果也完全不同。這樣一來,彩虹表攻擊幾乎失效,因為駭客無法用一組固定對照表去解所有密碼。再加上 password_hash() 支援像 bcryptargon2 這類計算成本更高的演算法,能有效抵擋暴力破解,讓密碼安全性大幅提升。

password_hash 與驗證流程:實際範例

理論講再多,不如直接看程式碼。以下是一個最簡單的範例,示範如何在註冊與登入流程中使用 password_hash()password_verify()

🔐 PHP 使用 password_hash() 建立與驗證密碼

<?php
// 註冊時:建立雜湊密碼
$password = "MySecurePassword123!";
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);

echo "雜湊後的結果:" . $hashedPassword . "\n";

// 登入時:驗證密碼
$inputPassword = "MySecurePassword123!";

if (password_verify($inputPassword, $hashedPassword)) {
    echo "登入成功,密碼正確!";
} else {
    echo "登入失敗,密碼錯誤!";
}
?>

在這段程式碼中:

  • password_hash():會自動產生隨機 SALT,並將密碼雜湊後存入資料庫。
  • password_verify():在登入時,把使用者輸入的密碼與資料庫裡的雜湊結果做比對。
  • 輸出的雜湊字串除了密碼雜湊本身,還包含演算法與 SALT 資訊,因此 PHP 可以正確驗證,不需要你手動管理 SALT。

這樣的設計讓整個密碼驗證流程既簡單又安全,也避免了新手常犯的「自己生 SALT、結果出錯」的問題。

常見迷思:雜湊就是加密?

很多開發者會誤以為「用 MD5 或 SHA1 把密碼轉換一下」就很安全,甚至把這稱作「加密」。事實上,這是一個錯誤的觀念:

  • 加密(Encryption):設計上可以被「解密」還原明文(例如 AES)。
  • 雜湊(Hashing):單向不可逆運算,設計上不能直接還原。

問題是,像 MD5、SHA1 這些演算法計算速度太快,加上彩虹表、GPU 暴力破解的出現,使得它們早已不適合用來存密碼。
真正安全的做法,就是使用專門設計給密碼的演算法(bcrypt、argon2),並透過 password_hash() 自動處理 SALT 與成本參數,才能抵擋現代的攻擊手法。

最佳實務:如何正確使用 password_hash

要讓密碼防護真正發揮效果,開發者在使用 password_hash() 時,還需要注意以下幾點:

  1. 選擇合適的演算法
    • 建議優先使用 PASSWORD_ARGON2ID(若 PHP 環境支援),因為 Argon2 在抗 GPU 與抗平行化攻擊上更強。
    • 若環境不支援 Argon2,PASSWORD_BCRYPT 依然是安全且廣泛支援的選擇。
  2. 設定合理的成本參數(cost)
    • bcrypt 預設 cost = 10,但你可以依伺服器效能調整。
    • 原則是「讓單次雜湊花費 0.2~0.5 秒」,確保對駭客來說破解成本極高。
  3. 定期檢查並重新雜湊
    • PHP 提供 password_needs_rehash(),可以在演算法升級或 cost 調整時,自動偵測並更新使用者的密碼雜湊。
    • 這能確保舊用戶的資料也跟著提升安全性,而不需要他們重新設定密碼。
  4. 搭配多層資安機制
    • HTTPS 傳輸加密、防爆力破解機制(登入錯誤次數限制)、雙因子驗證(2FA)。
    • 雜湊只是最後一道防線,其他環節也要一起補強。

👉 我的專業建議
如果你現在的系統還在使用 MD5 或 SHA1,務必要立即規劃升級,改用 password_hash() 來儲存密碼,並設置合適的成本參數。這不只是提升技術,更是保護使用者信任與公司品牌的基本責任。

常見問題 FAQ

想提升網站資安嗎?

密碼外洩不是新聞,而是每天都在發生的風險。
如果你還在用 MD5SHA1,是時候升級到 password_hash()
讓你的網站具備現代化的密碼保護機制。

👉 有網站安全或程式開發的需求嗎?歡迎留言跟我聊聊,
我可以分享更多實務經驗,幫你把網站打造得更安全!

立即聯絡我,讓我幫你升級安全防護 →
返回頂端