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

關於 PHP 密碼加密:為什麼 md5+crypt 不是「無敵」以及現代最佳實踐

     編輯:PHP 綜合知識

原文方案分析

$pass = '123456';
echo md5(crypt($pass, substr($pass, 0, 2)));

作者聲稱:「最後的密碼還是32位,初看都以為是 MD5加密,可無論對方MD5的HASH值多麼龐大,幾個T的數據都無法破解出來」

安全性評估:嚴重不足

問題詳解
crypt() 鹽值極短substr($pass, 0, 2) 僅取密碼前兩字符,熵極低,相同密碼產生相同鹽值,無抗彩虹表能力
雙層哈希無增益md5(crypt(...)) 只是將輸出再哈希一次,不增加計算成本,GPU 依然可高速暴力破解
無成本因子現代算法 (bcrypt/Argon2) 通過 cost factor 強制增加計算時間,此方案無此機制
MD5 已破碎碰撞攻擊、預像攻擊均已實用化,不適用於密碼存儲
固定輸出長度誤導32 位十六進制 ≠ 安全,只是輸出格式

實測破解速度參考 (RTX 3090, Hashcat)

算法                    速度 (H/s)      破解 8 位數字密碼
MD5                    ~500 GH/s        < 1 秒
MD5(MD5($p).$s)        ~300 GH/s        < 1 秒
crypt (DES, 2字符鹽)   ~10 GH/s         幾秒
md5(crypt(...))        ~300 GH/s        < 1 秒
bcrypt (cost=10)       ~20 KH/s         數天
Argon2id (t=3,m=64M,p=4) ~5 KH/s        數周

現代 PHP 密碼存儲標準 (PHP 5.5+)

1. password_hash() / password_verify() (內建、推薦)

<?php
// 註冊/修改密碼
$hash = password_hash($password, PASSWORD_DEFAULT); // 當前為 bcrypt,未來自動升級
// 存入數據庫:$hash (60 字符,含算法、cost、鹽值)

// 登錄驗證
if (password_verify($inputPassword, $hashFromDb)) {
    // 成功
    // 檢查是否需要重新哈希 (算法升級、cost 變更)
    if (password_needs_rehash($hashFromDb, PASSWORD_DEFAULT)) {
        $newHash = password_hash($inputPassword, PASSWORD_DEFAULT);
        // UPDATE users SET password = $newHash WHERE id = ?
    }
}
?>

2. 手動指定 Argon2id (PHP 7.3+,最高安全)

$hash = password_hash($password, PASSWORD_ARGON2ID, [
    'memory_cost' => 1 << 16,  // 64 MB
    'time_cost'   => 4,        // 迭代次數
    'threads'     => 3,        // 並行度
]);
// 驗證同 password_verify()

3. 兼容舊項目:漸進式遷移

function verifyPassword(string $input, string $storedHash): bool {
    // 新格式:password_hash 產生 (以 $2y$ / $argon2i$ / $argon2id$ 開頭)
    if (preg_match('/^\$2y\$|\$argon2/i', $storedHash)) {
        return password_verify($input, $storedHash);
    }
    
    // 舊格式:md5/crypt 等
    if (legacyVerify($input, $storedHash)) {
        // 登錄成功後,靜默升級
        $newHash = password_hash($input, PASSWORD_DEFAULT);
        updateUserHash($userId, $newHash);
        return true;
    }
    return false;
}

完整安全清單

  1. 永不限制密碼長度/字符集:允許 64+ 字符、Unicode、空格
  2. 強制 HTTPS:傳輸層加密,防止中間人竊取明文
  3. 限制嘗試次數:IP/賬號級限流,防暴力破解
  4. 雙因子認證 (2FA):TOTP/WebAuthn,密碼洩露也不會被盜號
  5. 密碼洩露檢測:對接 Have I Been Pwned API,禁止已洩露密碼
  6. 日誌脫敏:絕不記錄密碼、哈希、重置 Token

總結

「md5+crypt 無敵」是危險的錯誤認知。**密碼安全的核心是計算成本非可逆性**。請立即遷移至 password_hash(PASSWORD_DEFAULT) 或 PASSWORD_ARGON2ID,並建立遷移機制處理歷史數據。安全無絕對,只有持續跟進最新標準與威脅情報。

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