$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 位十六進制 ≠ 安全,只是輸出格式 |
算法 速度 (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
// 註冊/修改密碼
$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 = ?
}
}
?>
$hash = password_hash($password, PASSWORD_ARGON2ID, [
'memory_cost' => 1 << 16, // 64 MB
'time_cost' => 4, // 迭代次數
'threads' => 3, // 並行度
]);
// 驗證同 password_verify()
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;
}
「md5+crypt 無敵」是危險的錯誤認知。**密碼安全的核心是計算成本非可逆性**。請立即遷移至 password_hash(PASSWORD_DEFAULT) 或 PASSWORD_ARGON2ID,並建立遷移機制處理歷史數據。安全無絕對,只有持續跟進最新標準與威脅情報。