I was writing a basic register- and login script yesterday, and when I did the part where it hashes the password with a salt I realized that there should be a more secure way to store passwords than just running them through md5() or sha1(), so I wrote this function:
function password($password, $username, $saltglob = '2c62f9eb917de737b8184b8e5a793c89') { /* save string length of username, password and salt */ $userlen = strlen($username); $passlen = strlen($password); $saltlen = strlen($saltglob); /* split username, password and salt into string length + 1 */ $user = ($userlen < 4) ? array($username, $username) : str_split($username, ($userlen/2)+1); $pass = ($passlen < 4) ? array($password, $password) : str_split($password, ($passlen/2)+1); $salt = ($saltlen < 4) ? array($saltglob, $saltglob) : str_split($saltglob, ($saltlen/2)+1); /* save ascii value of username, password and salt */ $userval = ord($username); $passval = ord($password); $saltval = ord($saltglob); /* prepare an array of arguments and a format for vsprintf */ $format = '%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s'; $args = array($username, $userlen, $passlen, $saltlen, $saltglob, $user[0], $user[1], $pass[0], $pass[1], $salt[0], $salt[1], $userval, $password, $passval, $saltval); /* vsprintf the arguments */ $string[] = vsprintf($format, $args); /* rsort the arguments and run vsprinf again */ rsort($args); $string[] = vsprintf($format, $args); /* sort the arguments and run vsprintf again */ sort($args); $string[] = vsprintf($format, $args); /* hash each vsprintf result with md5 (raw) */ foreach($string as $value) $password = hash_hmac('md5', $value, $password, true); /* hash with sha512 (raw) */ $password = hash_hmac('sha512', $password, $saltglob, true); /* return an md5 hash */ return hash_hmac('md5', $password, $username); }
This way, even if someone can produce a bruteforce against the algorithm they will never know where in the hash the salt pieces where placed. And of course we’ll salt it with a global salt (third parameter) which is hidden deep in a configuration file on our server, which requires the script kiddie to actually access your files to get it.
One thing’s for sure, I’ll use this for all my projects
.
Edit: This function has been updated several times since the initial post because I like to make stuff more complicated than they actually have to be. The most recent one is the one above though (and is kinda overkill)