Skip to content

Instantly share code, notes, and snippets.

@reines
Created December 15, 2010 12:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reines/741901 to your computer and use it in GitHub Desktop.
Save reines/741901 to your computer and use it in GitHub Desktop.
Password hashing framework
<?php
/**
* Password hashing framework.
* Hashes take the form $<ALGORITHM>$<ITERATIONS>$<SALT>$<HASH>$
* Partially based upon the Portable PHP password
* hashing framework by Solar Designer (http://www.openwall.com/phpass/).
*/
class Password
{
/**
* Hashes the given password.
*
* @param string The password to hash.
* @param string The hash algorithm to use. Must be one of hash_algos(). Defaults to sha256.
* @param int How many hash iterations to use. Defaults to 4096.
*
* @return string Returns the generated hash, in the format $<ALGORITHM>$<ITERATIONS>$<SALT>$<HASH>$
*/
public static function hash($password, $algo = 'sha256', $iterations = 4096)
{
// Generate a random salt
$salt = sha1(uniqid(rand(), true));
return self::crypt($password, $algo, $iterations, $salt);
}
/**
* Checks if the given password matches the given hash.
*
* @param string The password to check.
* @param string The stored password hash to check against, in the format $<ALGORITHM>$<ITERATIONS>$<SALT>$<HASH>$
*
* @return bool Returns true if the password is correct, otherwise false.
*/
public static function check($password, $hash)
{
list ($algo, $iterations, $salt) = explode('$', substr($hash, 1, -1));
return $hash === self::crypt($password, $algo, $iterations, $salt);
}
/**
* Hashes the given password using the given settings.
*
* @param string The password to hash.
* @param string The hash algorithm to use. Must be one of hash_algos().
* @param int How many hash iterations to use.
* @param string A salt to salt the password hash.
*
* @return string Returns the generated hash, in the format $<ALGORITHM>$<ITERATIONS>$<SALT>$<HASH>$
*/
protected static function crypt($password, $algo, $iterations, $salt)
{
// calculate the hash using repeated hashing
$hash = hash($algo, $salt.$password, true); // salt + password
for ($i = 0;$i < $iterations;$i++)
$hash = hash($algo, $salt.$hash, true); // salt + hash
$hash = unpack('H*', $hash);
return sprintf('$%s$%d$%s$%s$', $algo, $iterations, $salt, $hash[1]);
}
}
@sprt
Copy link

sprt commented Feb 12, 2011

uniqid(null, false) takes 0.0236 second when uniqid(null, true) takes 0.5447 second with 4,096 iterations on my laptop. So it depends on the security level you need but hey. Also, mt_rand() is "4 times faster" than rand().

@reines
Copy link
Author

reines commented Feb 12, 2011

The random part only generates the initial salt, it isn't used in the repeated hashing. If we were to use this in FluxBB 2.0 (not decided yet, it might be smarter to use an existing standard), we would probably want to make our own random function which reads from /dev/urandom, and falls back to something like rand/mt_rand.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment