在PHP 中, crypt()函數是一種常用的密碼哈希工具,它利用指定的“鹽”(Salt)來增強密碼的安全性。鹽的作用是增加哈希的隨機性,防止彩虹表攻擊。理解如何從crypt()函數生成的哈希中提取並驗證鹽,是掌握密碼處理安全的重要環節。
本文將介紹如何使用PHP 的substr()函數從crypt()的返回值中提取鹽部分,並對其進行簡單的驗證。
Salt 是在加密時與原始密碼結合的一段隨機字符串。它確保即使兩個用戶的密碼相同,生成的哈希值也不同。
在crypt()函數中,Salt 的格式和長度根據加密算法的不同而不同,例如:
DES :2 個字符鹽
MD5 :以$1$開頭,後面跟著最多8 個字符的鹽
Blowfish :以$2a$或$2y$開頭,後跟兩位成本因子和22 個字符鹽
假設你使用的是MD5 算法,它的Salt 格式如下:
$1$ + 8字符鹽
例如,一個典型的MD5 哈希值:
$hash = crypt('password', '$1$abcdefgh$');
返回的哈希可能是:
$1$abcdefgh$ZxR0LnxZPbQ5Cj7JlYiGp0
鹽就是前12 個字符: $1$abcdefgh$
<?php
$hash = crypt('password', '$1$abcdefgh$');
// 提取鹽的長度為12個字符
$salt = substr($hash, 0, 12);
echo "提取的鹽是: " . $salt;
?>
我們可以通過正則表達式來驗證提取的鹽是否符合預期。例如,MD5 鹽的正則表達式:
/^(\$1\$[\.\/0-9a-zA-Z]{1,8}\$)$/
示例代碼:
<?php
$salt = substr($hash, 0, 12);
if (preg_match('/^\$1\$[\.\/0-9a-zA-Z]{1,8}\$/', $salt)) {
echo "鹽格式正確";
} else {
echo "鹽格式不正確";
}
?>
下面是一個完整的示例,包含生成哈希、提取鹽和驗證鹽:
<?php
$password = 'mypassword';
// 使用 MD5 算法生成鹽($1$ + 8個隨機字符 + $)
$salt = '$1$' . substr(strtr(base64_encode(random_bytes(6)), '+', '.'), 0, 8) . '$';
// 生成哈希
$hash = crypt($password, $salt);
echo "生成的哈希: $hash\n";
// 從哈希中提取鹽
$extracted_salt = substr($hash, 0, 12);
echo "提取的鹽: $extracted_salt\n";
// 驗證鹽格式
if (preg_match('/^\$1\$[\.\/0-9a-zA-Z]{1,8}\$/', $extracted_salt)) {
echo "鹽格式驗證通過\n";
} else {
echo "鹽格式驗證失敗\n";
}
?>
crypt()函數的鹽格式與加密算法有關,長度和結構不同。
使用substr()可以方便地從哈希中提取鹽部分。
用正則表達式對鹽格式進行驗證,可以保證鹽符合加密算法要求,提升安全性。