另一种将盐值直接包含在哈希中的加盐哈希解决方案,同时保持结果的长度相同。如果要生成哈希,请在没有第二个参数的情况下调用该函数。如果要根据哈希检查密码,请使用哈希作为第二个参数。在这种情况下,该函数在成功时返回哈希本身,在失败时返回布尔值 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;
}
?>