Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can someone point me to a good PHP/MySQL salted hashed password implementation?

After reading about salts password hashing Id like to implement a simple version for an admin area to a site Im building.

If you have any good links with code that have implemented this idea well, I would appreciate it if you could share.

Thanks,

like image 306
barfoon Avatar asked Jun 08 '10 15:06

barfoon


2 Answers

Registration process: User enters a password. System generates a salt value from random data (could be a hash of the time & PID or something). Systems generates a hash value of the password & salt value and stores both of these in the registration table.

Login process: User enters a password. System pulls the salt value from the database and hashes it and the password and compares that against the hashed password value put into the database during registration.

The plaintext password is never stored in the database. The salt value is never visible to the client.

like image 87
Trevor Tippins Avatar answered Sep 24 '22 23:09

Trevor Tippins


Well, here's what I would do:

function makeToken($length = 16) {
    if ($length > 16) {
        $ret = '';
        while ($length > 0) {
            $ret .= makeToken(16);
            $length -= 16;
        }
        if ($length < 0) {
            $ret = substr($ret, 0, $length);
        }
        return $ret;
    }
    $stub = '';
    for ($i = 0; $i < 100; $i++) {
        $stub .= chr(mt_rand(1, 254));                
    }
    $hash = sha1($stub);
    $hashLen = strlen($hash);
    $ret = '';
    for ($i = 0; $i < $length; $i++) {
        $ret .= $hash[mt_rand(0, $hashLen - 1)];
    }
    return $ret;
}

function makeSaltedHash($string, $salt = '') {
    if (empty($salt)) { 
        $salt = makeToken();
    }
    $hash = '';
    for ($i = 0; $i < 200; $i++) {
        $hash = sha1($hash . $salt . $string);
    }
    return $hash . ':' . $salt;
}

function verifySaltedHash($string, $hash) {
    if (strpos($string, ':') === false) return false;
    list ($base, $salt) = explode(':', $hash);
    $test = makeSaltedHash($string, $salt);
    return $test === $hash;
}

The rational is this:

First, generate a random salt (this will always return a hex string, so it can be used for tokens etc). Then loop over a hashing function (sha1 in this case) more than 1 time. This is so that it becomes more expensive to generate a rainbow table (200x as expensive in this case) while adding relatively little expense to generation.

Usage:

To generate a hash:

$hash = makeSaltedHash($password);

To verify the hash:

$bool = verifySaltedHash($password, $savedHash);

To generate a token (CSRF protection, session_id, etc), you can do it a few ways:

Fixed Length:

$token = makeToken(32);

Random Length:

$token = makeToken(mt_rand(64,128));

Edit: Increased the repetitions on sha1 in the hashing function.

like image 37
ircmaxell Avatar answered Sep 25 '22 23:09

ircmaxell