在PHP 中進行密碼哈希和驗證時, crypt()和password_verify()是兩個經常被提及的函數。雖然它們都涉及密碼安全處理,但它們的使用方式和設計目的有所不同。因此,開發者可能會疑問:
crypt()是PHP 早期用於加密密碼的函數。它支持多種算法,如:
DES(默認)
MD5(以$1$開頭)
Blowfish(以$2a$ , $2y$等開頭)
SHA-256、SHA-512(以$5$ , $6$開頭)
一個典型的crypt()用法如下:
$password = 'mySecret';
$salt = '$2y$10$' . substr(strtr(base64_encode(random_bytes(16)), '+', '.'), 0, 22);
$hash = crypt($password, $salt);
password_verify()是在PHP 5.5 引入的,專門為驗證使用password_hash()生成的哈希設計的函數。它自動識別哈希使用的算法(如Bcrypt、Argon2)並根據輸入的明文密碼進行比對。
if (password_verify('mySecret', $hashFromDatabase)) {
echo '密碼正確';
}
簡短回答:不建議,也沒有意義。
雖然password_verify()背後確實是調用了類似crypt()的底層機制,但它只支持其“自家”函數password_hash()生成的哈希格式。如果你使用crypt()自定義哈希,再使用password_verify()來驗證,會出現以下問題:
如果哈希格式不符合password_verify()預期,它將返回false;
PHP 內部並沒有保證未來版本對crypt()生成的非標準格式哈希的支持;
password_verify()對於錯誤格式的哈希可能根本無法解析,導致驗證始終失敗。
換句話說,兩者雖有關聯,但不是設計為互通的函數對。
手動管理鹽值和算法選擇,易出錯;
如果使用不當(如使用默認DES 算法或弱鹽值),容易遭受暴力破解;
不具備自動更新算法的機制;
未來兼容性無法保證。
自動選擇安全默認算法(如Bcrypt);
自動生成鹽值;
算法封裝良好,開發者無需關心底層實現;
可通過password_needs_rehash()實現平滑算法升級;
安全性經過現代標準審查。
為了獲得更好的安全性和未來兼容性,建議始終使用password_hash()與password_verify()搭配使用:
// 註冊或修改密碼時
$hash = password_hash('mySecret', PASSWORD_DEFAULT);
// 登錄時驗證
if (password_verify('mySecret', $hash)) {
// 驗證成功
}
如果你在舊系統中使用了crypt() ,建議在用戶登錄成功後,使用password_hash()重新生成哈希,並更新數據庫中的值。這種方式可以逐步平滑過渡到更安全的加密方法。
雖然crypt()是PHP 中的一員老將,但在密碼處理領域,它已經逐漸被更現代、更安全的password_hash()和password_verify()所取代。將crypt()和password_verify()結合使用並不能帶來預期的安全性提升,反而可能因不兼容而帶來驗證失敗等問題。因此,最佳實踐是完全採用PHP 提供的password_系列函數來處理用戶密碼*,確保系統的安全性與可維護性。
如需更進一步的安全措施,可以結合使用Argon2 算法: