首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 密碼儲存安全指南:從 MD5 到 Bcrypt 再到 Password Hashing API 最佳實踐

     編輯:PHP 綜合知識

頻發的「脫庫」事件證明:明文儲存、單一 MD5、無鹽雜湊都是嚴重安全缺陷。用戶習慣跨站複用密碼,一家洩露、全線崩盤。本文梳理密碼儲存演進史,確立現代 PHP 專案的黃金標準。

演進時間軸與風險

階段做法風險
1. 明文直接存密碼內部人員/駭客直接可見
2. 單向雜湊md5($pwd)彩虹表反查、碰撞攻擊
3. 加鹽雜湊hash('sha256', $pwd . $salt)固定演算法可被 GPU 大規模並行破解
4. 慢速雜湊Bcrypt / PBKDF2 / Argon2✅ 計算緩慢、記憶體硬化、抗 GPU/ASIC

方案 1:Bcrypt(PHP 5.3+ 內建)

Blowfish 加密 + crypt(),自帶鹽值、Cost 因子(迴圈次數)。

<?php
function bcryptHash(string $pwd): string {
    if (!defined('CRYPT_BLOWFISH') || !CRYPT_BLOWFISH) {
        throw new RuntimeException('Bcrypt 不支援');
    }
    // $2y$ = Blowfish, 11 = cost (2^11 輪), 22 字元鹽值
    $salt = '$2y$11$' . substr(md5(uniqid(rand(), true)), 0, 22);
    return crypt($pwd, $salt);
}

function bcryptVerify(string $pwd, string $hash): bool {
    return crypt($pwd, $hash) === $hash;
}
?>

注意:鹽值必須以 $2y$ 或 $2a$ 開頭,Cost 建議 10-12(視伺服器 CPU 調整)。

方案 2:Password Hashing API(PHP 5.5+ 官方推薦)⭐

封裝 Bcrypt(預設)或 Argon2(PHP 7.2+),自動處理鹽值、Cost、演算法標識,開發者零負擔。

核心四函數

<?php
// 1. 雜湊(自動生成鹽值、Cost=10、演算法標識)
$hash = password_hash($password, PASSWORD_DEFAULT); // 目前 = Bcrypt
// 指定 Cost
$hash = password_hash($password, PASSWORD_DEFAULT, ['cost' => 12]);
// 指定 Argon2id(PHP 7.3+)
$hash = password_hash($password, PASSWORD_ARGON2ID, ['memory_cost' => 65536, 'time_cost' => 4, 'threads' => 3]);

// 2. 驗證(自動解析 hash 中的演算法/鹽值/Cost)
if (password_verify($password, $hash)) { /* 通過 */ }

// 3. 需重新雜湊?(演算法升級、Cost 變更)
if (password_needs_rehash($hash, PASSWORD_DEFAULT, ['cost' => 12])) {
    $hash = password_hash($password, PASSWORD_DEFAULT, ['cost' => 12]);
    // 更新資料庫
}

// 4. 取得雜湊資訊
$info = password_get_info($hash); // ['algo' => 1, 'algoName' => 'bcrypt', 'options' => ['cost' => 10]]
?>

資料庫欄位設計

  • password VARCHAR(255):PASSWORD_DEFAULT 目前輸出 60 字元,未來 Argon2 可能更長,預留 255 最保險。
  • 若固定用 PASSWORD_BCRYPT,CHAR(60) 足夠。

遷移舊系統(MD5/SHA1)策略

  1. 新增 password_hash VARCHAR(255) 欄位,legacy_hash 保留舊值。
  2. 登入時:先驗證新欄位 → 失敗則驗證舊邏輯 → 成功則用 password_hash() 重新雜湊存入新欄位、清空舊欄位。
  3. 漸進式遷移,無需強制用戶重設密碼。

常見誤區

  • ❌ md5(md5($pwd).$salt) 雙層 MD5 仍屬快速雜湊,GPU 秒破。
  • ❌ 自行設計「加密演算法」,密碼學極難,必有漏洞。
  • ❌ 密碼長度限制 < 72 字元(Bcrypt 截斷限制),建議前端限制 72 內或預先 SHA256 再 Bcrypt。
  • ✅ 使用 password_hash() + password_verify(),定期檢視 password_needs_rehash() 升級演算法。

結語

2024 年後,新專案直接用 password_hash($pwd, PASSWORD_ARGON2ID),舊專案遷移至 PASSWORD_DEFAULT。密碼安全不是選擇題,是底線。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved