在PHP 中, crypt函數常用於密碼哈希處理。它允許通過鹽值(Salt)增強哈希的安全性,防止彩虹表攻擊等安全隱患。然而,許多開發者在使用crypt時習慣於硬編碼鹽值,這會導致安全風險。本文將詳細探討如何避免硬編碼鹽值,從而提升密碼存儲的安全性。
硬編碼鹽值指的是將固定的鹽字符串直接寫進代碼中,比如:
$salt = '$6$rounds=5000$fixedsaltstring$';
$hash = crypt($password, $salt);
這樣做存在明顯的風險:
鹽值重複使用:所有用戶的密碼哈希都用同一個鹽,攻擊者可以通過針對該鹽預計算攻擊。
暴露鹽值:如果源碼洩露,攻擊者知道了鹽,哈希破解難度大幅降低。
難以擴展:若需要更換鹽策略,修改硬編碼的部分極不靈活。
為避免以上問題,推薦動態生成唯一且安全的鹽。以下是幾個關鍵點:
PHP 的random_bytes()函數可生成高強度隨機字節,結合Base64 或類似編碼即可生成鹽。
function generateSalt($length = 16) {
$bytes = random_bytes($length);
return substr(strtr(base64_encode($bytes), '+', '.'), 0, $length);
}
不同算法對鹽的格式要求不同。以SHA-512 ( $6$ ) 為例,格式是:
$6$rounds=5000$saltstring$
結合動態鹽:
$saltString = '$6$rounds=5000$' . generateSalt() . '$';
$hash = crypt($password, $saltString);
crypt返回的哈希包含了鹽信息,存儲時只需存儲完整哈希即可,無需單獨保存鹽。
驗證時直接用輸入密碼和存儲哈希調用crypt ,對比結果:
function verifyPassword($inputPassword, $storedHash) {
return crypt($inputPassword, $storedHash) === $storedHash;
}
<?php
// 生成動態鹽
function generateSalt($length = 16) {
$bytes = random_bytes($length);
return substr(strtr(base64_encode($bytes), '+', '.'), 0, $length);
}
// 創建密碼哈希
function createHash($password) {
$salt = '$6$rounds=5000$' . generateSalt() . '$';
return crypt($password, $salt);
}
// 驗證密碼
function verifyPassword($inputPassword, $storedHash) {
return crypt($inputPassword, $storedHash) === $storedHash;
}
// 示例用法
$password = 'mypassword123';
$hash = createHash($password);
echo "哈希值: $hash\n";
if (verifyPassword('mypassword123', $hash)) {
echo "密碼驗證成功!\n";
} else {
echo "密碼驗證失敗!\n";
}
?>
避免硬編碼鹽值能顯著提高密碼哈希的安全性。通過使用PHP 的隨機數生成函數,動態創建唯一鹽值,並且將完整哈希存儲於數據庫中,能有效抵禦多種攻擊手段。