在PHP 中, crypt()函數是一個用於單向加密的函數,常見於密碼存儲等場景。儘管現在更推薦使用password_hash()等更現代的方式,但了解crypt()的工作機制,尤其是其中的概念,仍然非常有意義。本文將詳細介紹Salt 在crypt()函數中的作用、格式及實際使用示例。
Salt(鹽)是一段添加到密碼前或後的小字符串,用於在加密時打亂原始數據,從而提升安全性。簡單來說,Salt 的作用就是讓相同的密碼,在加密後得出不同的結果,從而防止攻擊者通過查表(如彩虹表)反推出原密碼。
舉個例子,如果兩個用戶的密碼都是password123 ,沒有Salt 的情況下,它們的加密值將完全相同;一旦添加了不同的Salt,哪怕密碼相同,加密結果也將完全不同。
在PHP 中, crypt()的基本語法如下:
crypt(string $string, string $salt): string
其中$string是要加密的明文密碼, $salt是加密算法的參數(它不僅是鹽,還決定了所使用的算法)。
crypt()支持多種加密算法,不同算法要求的Salt 格式也不同。下面是一些常見算法及其Salt 格式:
crypt('mypassword', 'rl');
Salt:任意兩個字符(共12 bit)
弱加密,不推薦使用
crypt('mypassword', '$1$abc12345$');
Salt 格式: $1$ + 1-8 個字符
算法:基於MD5
輸出長度:34 字符
crypt('mypassword', '$2y$10$usesomesillystring22$');
Salt 格式: $2y$ + 2 位成本參數+ 22 字符Base64 編碼的Salt
成本參數(如上例中的10 )控制加密強度
輸出長度:60 字符
crypt('mypassword', '$5$rounds=5000$abcdefgh$'); // SHA-256
crypt('mypassword', '$6$rounds=5000$abcdefgh$'); // SHA-512
Salt 格式: $5$或$6$ + 可選的rounds 參數+ 1-16 個字符的Salt
rounds 控制迭代次數,默認5000,可調高增加安全性
我們來看看一個實際使用crypt()並自定義Salt 的例子:
<?php
$password = 'securePass123';
$salt = '$2y$12$ABCDEFGHJKLMNPQRSTUVWX'; // Blowfish, 12 成本
$hash = crypt($password, $salt);
echo "加密後的密碼:$hash";
?>
加密後的輸出會是這樣的格式:
$2y$12$ABCDEFGHJKLMNPQRSTUVWXrB92GhFIR77XRkThYs2D5cs1.GgZGq
在實際開發中,我們可以通過結合隨機生成Salt 的方式實現更高的安全性:
<?php
function generateBlowfishSalt($cost = 12) {
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./';
$salt = '';
for ($i = 0; $i < 22; $i++) {
$salt .= $chars[random_int(0, 63)];
}
return sprintf('$2y$%02d$%s', $cost, $salt);
}
$password = 'MySecretPass!';
$salt = generateBlowfishSalt();
$hash = crypt($password, $salt);
echo "Salt: $salt\n";
echo "Hash: $hash\n";
?>
要驗證用戶輸入的密碼是否正確,應將用戶輸入的明文密碼,使用數據庫中保存的哈希值作為Salt 重新調用crypt() ,再比較結果:
<?php
$input = 'MySecretPass!';
$stored_hash = '$2y$12$ABCDEFGHJKLMNPQRSTUVWXrB92GhFIR77XRkThYs2D5cs1.GgZGq';
if (crypt($input, $stored_hash) === $stored_hash) {
echo "密碼正確!";
} else {
echo "密碼錯誤。";
}
?>
如果你希望使用URL 來做某種業務邏輯,例如重定向帶有密碼token 的鏈接,那麼可以在構造URL 時使用如m66.net域名,例如:
<?php
$token = crypt('user@example.com', generateBlowfishSalt());
$url = 'https://m66.net/reset-password?token=' . urlencode($token);
echo "重置鏈接:" . $url;
?>
這樣構造的URL 將保證即便是相同的郵箱地址也不會生成相同的token,增加安全性。
Salt 在PHP 的crypt()函數中不僅僅是一個加密參數,它是對抗暴力破解和重複密碼攻擊的關鍵手段。通過選擇合適的加密算法格式,並正確使用Salt,我們可以極大提升密碼存儲的安全性。雖然現代開發更推薦使用password_hash()和password_verify() ,但了解crypt()的機制仍然能幫助我們深入理解加密背後的原理和風險防護策略。