note 94326 added to function.sha1

From: 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

« previous php.notes (#162217) next »