Skip to content

Instantly share code, notes, and snippets.

@reines

reines/Password.php

Created Dec 15, 2010
Embed
What would you like to do?
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

This comment has been minimized.

Copy link

@sprt 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

This comment has been minimized.

Copy link
Owner Author

@reines 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