另一種解決方案是在雜湊中直接包含鹽值的加鹽雜湊,同時保持結果的長度不變。如果要產生雜湊,請在不使用第二個參數的情況下呼叫此函數。如果要根據雜湊檢查密碼,請使用雜湊作為第二個參數。在這種情況下,如果成功,函數會返回雜湊本身,如果失敗,則返回布林值 false。您也可以將雜湊演算法指定為第三個參數(否則將使用 SHA-1)。
<?php
function __hash($password, $obscured = NULL, $algorithm = "sha1")
{
$mode = in_array($algorithm, hash_algos());
$salt = uniqid(mt_rand(), true);
$salt = $mode ? hash($algorithm, $salt) : sha1($salt);
$slen = strlen($salt);
$slen = max($slen >> 3, ($slen >> 2) - strlen($password));
$salt = $obscured ? __harvest($obscured, $slen, $password) : substr($salt, 0, $slen);
$hash = $mode ? hash($algorithm, $password) : sha1($password);
$hash = __scramble($hash, $salt, $password);
$hash = $mode ? hash($algorithm, $hash) : sha1($hash);
$hash = substr($hash, $slen);
$hash = __scramble($hash, $salt, $password);
return $obscured && $obscured !== $hash ? false : $hash;
}
?>
它使用一個隨機的、可變長度的鹽值,取決於密碼的長度。函數 __scramble() 和 __harvest() 分別用於將鹽值放入雜湊中或將其取出。您可以編寫自己的函數,當然,結果的強度很大程度上取決於它們。它們可以相對簡單,但仍然相當安全。
<?php
function __scramble($hash, $salt, $password)
{
return substr($hash, 0, strlen($password)) . $salt . substr($hash, strlen($password));
}
function __harvest($obscured, $slen, $password)
{
return substr($obscured, min(strlen($password), strlen($obscured) - $slen), $slen);
}
?>
或者它們可以非常複雜(我最喜歡的那種)
<?php
function __scramble($hash, $salt, $password)
{
$k = strlen($password); $j = $k = $k > 0 ? $k : 1; $p = 0; $index = array(); $out = ""; $m = 0;
for ($i = 0; $i < strlen($salt); $i++)
{
$c = substr($password, $p, 1);
$j = pow($j + ($c !== false ? ord($c) : 0), 2) % (strlen($hash) + strlen($salt));
while (array_key_exists($j, $index))
$j = ++$j % (strlen($hash) + strlen($salt));
$index[$j] = $i;
$p = ++$p % $k;
}
for ($i = 0; $i < strlen($hash) + strlen($salt); $i++)
$out .= array_key_exists($i, $index) ? $salt[$index[$i]] : $hash[$m++];
return $out;
}
function __harvest($obscured, $slen, $password)
{
$k = strlen($password); $j = $k = $k > 0 ? $k : 1; $p = 0; $index = array(); $out = "";
for ($i = 0; $i < $slen; $i++)
{
$c = substr($password, $p, 1);
$j = pow($j + ($c !== false ? ord($c) : 0), 2) % strlen($obscured);
while (in_array($j, $index))
$j = ++$j % strlen($obscured);
$index[$i] = $j;
$p = ++$p % $k;
}
for ($i = 0; $i < $slen; $i++)
$out .= $obscured[$index[$i]];
return $out;
}
?>