當前位置: 首頁> 最新文章列表> 如何避免硬編碼Salt 值

如何避免硬編碼Salt 值

M66 2025-05-24

在PHP 中, crypt函數常用於密碼哈希處理。它允許通過鹽值(Salt)增強哈希的安全性,防止彩虹表攻擊等安全隱患。然而,許多開發者在使用crypt時習慣於硬編碼鹽值,這會導致安全風險。本文將詳細探討如何避免硬編碼鹽值,從而提升密碼存儲的安全性。

為什麼不應該硬編碼Salt?

硬編碼鹽值指的是將固定的鹽字符串直接寫進代碼中,比如:

 $salt = '$6$rounds=5000$fixedsaltstring$';
$hash = crypt($password, $salt);

這樣做存在明顯的風險:

  • 鹽值重複使用:所有用戶的密碼哈希都用同一個鹽,攻擊者可以通過針對該鹽預計算攻擊。

  • 暴露鹽值:如果源碼洩露,攻擊者知道了鹽,哈希破解難度大幅降低。

  • 難以擴展:若需要更換鹽策略,修改硬編碼的部分極不靈活。

動態生成鹽值的最佳實踐

為避免以上問題,推薦動態生成唯一且安全的鹽。以下是幾個關鍵點:

1. 使用隨機安全的字節生成鹽

PHP 的random_bytes()函數可生成高強度隨機字節,結合Base64 或類似編碼即可生成鹽。

 function generateSalt($length = 16) {
    $bytes = random_bytes($length);
    return substr(strtr(base64_encode($bytes), '+', '.'), 0, $length);
}

2. 結合算法和參數構造鹽字符串

不同算法對鹽的格式要求不同。以SHA-512 ( $6$ ) 為例,格式是:

 $6$rounds=5000$saltstring$

結合動態鹽:

 $saltString = '$6$rounds=5000$' . generateSalt() . '$';
$hash = crypt($password, $saltString);

3. 存儲完整哈希

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 的隨機數生成函數,動態創建唯一鹽值,並且將完整哈希存儲於數據庫中,能有效抵禦多種攻擊手段。