當前位置: 首頁> 最新文章列表> 為什麼我用crypt() 函數加密相同的內容時,返回的加密結果總是一樣的?

為什麼我用crypt() 函數加密相同的內容時,返回的加密結果總是一樣的?

M66 2025-06-15

在PHP 中, crypt()是一個用於哈希加密的函數,它廣泛應用於密碼處理和數據加密的場景中。然而,許多開發者在使用crypt()函數加密相同內容時,會驚訝地發現:

這篇文章將帶你深入理解這個現象背後的原因,並教你如何正確、安全地使用crypt()

一、認識crypt()函數的基本原理

crypt()的本質是一個哈希函數,它不是為了加密數據,而是為了生成不可逆的哈希值,常用於密碼驗證。

函數原型如下:

 string crypt(string $string, string $salt)

它接收兩個參數:

  • $string :要加密的字符串。

  • $salt :加密時使用的“鹽值”,用於影響哈希結果。

如果你傳遞了相同的$salt ,那麼加密相同的$string ,自然會得到相同的結果。這正是你看到“加密結果總是一樣”的原因。

二、為什麼總是一樣的結果?

這是因為你在調用crypt()時,可能使用了固定的鹽值,或者乾脆沒有傳入第二個參數$salt

PHP 的crypt()在沒有提供$salt時,會嘗試使用某些系統默認機制,但這種機制可能在一些系統上表現為“默認使用相同的salt”,從而導致“同一個輸入,總是得到相同的輸出”。

看看下面的例子:

 echo crypt("mypassword", "m6"); // 使用固定 salt

每次運行這段代碼,無論多少次,輸出都一樣。這意味著,如果攻擊者知道你使用的是固定的salt,他們也可以預計算哈希值表,對你的系統進行攻擊。

三、如何讓每次結果都不同?

**正確做法是:使用隨機的salt 值。 **每次為用戶生成密碼哈希時,都生成一個獨立的salt,並把它存儲在數據庫中。這樣即使兩個用戶密碼相同,他們的哈希值也不同。

PHP 推薦使用帶有自動生成salt 的方式,例如使用password_hash()函數,這是從PHP 5.5+ 引入的更安全的方式:

 $password = 'mypassword';
$hash = password_hash($password, PASSWORD_BCRYPT);

這個函數內部會自動為你生成一個獨特的salt,並將其附加在結果中。每次運行都會得到不同的結果:

 // 每次輸出都不一樣
$hash1 = password_hash('mypassword', PASSWORD_BCRYPT);
$hash2 = password_hash('mypassword', PASSWORD_BCRYPT);

但它們仍然是可以通過password_verify()來驗證原始密碼的。

四、如果非用crypt()怎麼辦?

如果你非得用crypt() ,那就手動生成隨機的salt。下面是一個示例:

 function generate_salt($length = 22) {
    return substr(strtr(base64_encode(random_bytes($length)), '+', '.'), 0, $length);
}

$password = 'mypassword';
$salt = '$2y$10$' . generate_salt(); // 使用 Blowfish 演算法
$hash = crypt($password, $salt);

每次調用都會生成不同的salt,自然也會生成不同的加密結果。

五、存儲與驗證

加密後的結果應該存儲在數據庫中,用於後續驗證。示例代碼如下:

 // 存儲時
$hash = crypt($password, $salt);
// 保存到數據庫

// 驗證時
if (hash_equals($hash, crypt($inputPassword, $hash))) {
    echo "密碼正確";
} else {
    echo "密碼錯誤";
}

注意crypt()的第二個參數可以直接傳入已加密的哈希值,PHP 會自動從中提取salt。

六、總結

  • crypt()返回相同結果,是因為你用了相同的salt。

  • 要想安全,應使用隨機salt,或直接用password_hash()

  • 不建議在新項目中繼續使用crypt() ,除非有特別需求。

  • 始終避免硬編碼salt,防止彩虹表攻擊。

在開發涉及用戶密碼處理的系統時,始終以安全為第一要務。正確理解crypt()的行為,有助於你構建一個更穩固、更可靠的應用系統。