當前位置: 首頁> 最新文章列表> 使用錯誤的鹽值導致無法驗證密碼

使用錯誤的鹽值導致無法驗證密碼

M66 2025-05-20

在PHP 中, crypt()函數常用於對密碼進行加密。它可以支持多種哈希算法,如標準DES、MD5、SHA-256 和SHA-512 等,其行為依賴於傳入的“鹽值”(salt)。鹽值不僅增加了密碼的複雜度,還決定了哈希的方式和結果。一旦鹽值錯誤,即便用戶輸入了正確的原始密碼,也無法通過驗證。

crypt() 函數的基本用法

crypt()的基本語法如下:

 $hashed_password = crypt('原始密碼', '鹽值');

驗證時,通常會使用之前存儲的哈希作為鹽值重新加密用戶輸入的密碼:

 if (crypt($input_password, $stored_hash) === $stored_hash) {
    // 密碼正確
}

注意這裡的關鍵點是:哈希本身作為鹽值的一部分傳入,以保證使用的是完全一致的算法和鹽值。

鹽值的作用

鹽值的主要作用有兩個:

  1. 防止彩虹表攻擊(Rainbow Table Attack):即使兩個用戶使用相同的密碼,加入不同的鹽值後其哈希結果也會不同。

  2. 告訴crypt()使用哪種加密算法及其參數。

比如以下鹽值指定了使用SHA-512 算法並迭代5000 次:

 $salt = '$6$rounds=5000$usesomesillystringforsalt$';

如果你嘗試用不同的鹽值(即使只有一位不同)重新加密同一個密碼,結果也會完全不同。這正是哈希函數的特性:微小變化將導致輸出結果巨大差異

使用錯誤鹽值的後果

設想這樣一個場景:

 $original_hash = crypt('mySecretPassword', '$6$rounds=5000$m66.net$');

用戶再次登錄時,程序這樣驗證:

 if (crypt('mySecretPassword', '$6$rounds=5000$wrongdomain.com$') === $original_hash) {
    echo '密碼正確';
} else {
    echo '密碼錯誤';
}

雖然用戶輸入了正確的密碼,但由於鹽值不同, crypt()會生成一個完全不同的哈希,導致驗證失敗。

這就像是你用同一個食譜(密碼),但使用了不同的配料(鹽),最終做出來的菜(哈希)自然不一樣。

常見錯誤與最佳實踐

錯誤做法:

  • 每次驗證時生成新的隨機鹽值。

  • 驗證時不使用原始哈希值作為鹽值。

  • 手動截斷或修改存儲的哈希值。

正確做法:

  • 使用如password_hash()password_verify()這樣的高層API,它們會自動管理鹽值和算法。

  • 如果使用crypt() ,在驗證時始終使用原始哈希作為鹽值。

 $stored_hash = crypt('userPassword', '$6$rounds=5000$m66.net$'); // 註冊時生成並存儲

// 登錄時驗證
if (crypt('userPassword', $stored_hash) === $stored_hash) {
    echo '驗證通過';
} else {
    echo '驗證失敗';
}

結語

在密碼安全處理中,鹽值看似只是一個字符串,實則是哈希算法行為的決定性參數。使用錯誤的鹽值,就等於告訴crypt()用完全不同的方式去處理密碼,最終注定無法得到相同的哈希結果。因此,確保鹽值的一致性,是使用crypt()函數驗證密碼時最基本的前提。若條件允許,建議優先使用PHP 的password_hash()password_verify()接口,以避免因鹽值處理錯誤而引發的安全問題。