note 94326 added to function.sha1
| From: | Anonymous at osu1 dot php dot net | Date: | Thu, 29 Oct 2009 01:48:53 +0000 |
| Subject: | note 94326 added to function.sha1 | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-162217@lists.php.net to get a copy of this message | ||
Another solution to the salted hash with salt included directly in the hash, while keeping the same
length of the result. If you want to generate a hash, call the function without the second argument.
If you want to check a password against a hash, use the hash as the second argument. In this case,
the function returns the hash itself on success, or boolean false on failure. You can also specify a
hash algorithm as the third argument (otherwise SHA-1 will be used).
<?php
function __hash($password, $obscured = NULL, $algorithm = "sha1")
{
// whether to use user specified algorithm
$mode = in_array($algorithm, hash_algos());
// generate random salt
$salt = uniqid(mt_rand(), true);
// hash it
$salt = $mode ? hash($algorithm, $salt) : sha1($salt);
// get the length
$slen = strlen($salt);
// compute the actual length of salt we will use
// 1/8 to 1/4 of the hash, with shorter passwords producing longer salts
$slen = max($slen >> 3, ($slen >> 2) - strlen($password));
// if we are checking password against a hash, harvest the actual salt from it, otherwise just cut
the salt we already have to the proper size
$salt = $obscured ? __harvest($obscured, $slen, $password) : substr($salt, 0, $slen);
// hash the password - this is maybe unnecessary
$hash = $mode ? hash($algorithm, $password) : sha1($password);
// place the salt in it
$hash = __scramble($hash, $salt, $password);
// and hash it again
$hash = $mode ? hash($algorithm, $hash) : sha1($hash);
// cut the result so we can add salt and maintain the same length
$hash = substr($hash, $slen);
// ... do that
$hash = __scramble($hash, $salt, $password);
// and return the result
return $obscured && $obscured !== $hash ? false : $hash;
}
?>
It uses a random, variable length salt, depending on the length of the password. The functions
__scramble() and __harvest() are used to place salt into the hash or pull it out respectively. You
can write your own, and of course the strength of the result greatly depends on them. They can be
relatively simple yet still quite secure:
<?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);
}
?>
Or they can be ridiculously complicated (my favourite kind):
<?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;
}
?>
----
Server IP: 147.32.160.17
Probable Submitter: 90.178.66.185
----
Manual Page -- http://www.php.net/manual/en/function.sha1.php
Edit -- https://master.php.net/note/edit/94326
Del: integrated -- https://master.php.net/note/delete/94326/integrated
Del: useless -- https://master.php.net/note/delete/94326/useless
Del: bad code -- https://master.php.net/note/delete/94326/bad+code
Del: spam -- https://master.php.net/note/delete/94326/spam
Del: non-english -- https://master.php.net/note/delete/94326/non-english
Del: in docs -- https://master.php.net/note/delete/94326/in+docs
Del: other reasons-- https://master.php.net/note/delete/94326
Reject -- https://master.php.net/note/reject/94326
Search -- https://master.php.net/manage/user-notes.php