Crypt password validation?

For password storage, I always used MD5 hash. i.e.


$username = isset($_POST['username']) ? $_POST['username'] : '';
$password = isset($_POST['password']) ? $_POST['password'] : '';
$hashed    = md5($password);

$q =  "INSERT INTO users (username,password)VALUES (:username,:hashed)"
$data = array(':username' => $username, :hashed' => $hashed);
$q->execute($data);

However, some members of the forum told me that this was not really safe. So I am trying to adjust.it . So instead of :


$hashed    = md5($password);

I use:


$salt       = 'zandzeepsodemineraalwatersteenstralen';
$hashed = crypt($password, '$2a$07$' . $salt);
$sql= "INSERT INTO operators (v_naam, a_naam, username, password, salt) VALUES (:username,:hashed ,:salt)";

The insert is working fine. The only problem I have is how to validate the password within the login function with the hashed password in combination with salt. When I still used MD5 I would use:


$stmt->execute(array(':username' => $username, 'password' => md5($password)));

But how do I do that using salt and hased?

Thank you in advance.

Hi Donboe, how you doing?

The best practice for password hashing in PHP is to use the built-in password_* functions (if you’re using PHP 5.5 or higher) or the [URL=“https://github.com/ircmaxell/password_compat”]backwards compatibility library (for PHP 5.3.7 or higher).

Hi fretburner. Thank you for the reply.

Yes I am fine, and your self? I hope the people over there are not to upset after the dramatic lost of Brazil yesterday.

I have been looking into the password_* functions especially at Example #3 password_hash() example setting salt manually. I tried this:



<?php
$options = [
    'cost' => 11,
    'salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM),
];
echo password_hash("rasmuslerdorf", PASSWORD_BCRYPT, $options)."\
";
?>

But I get a syntax error, 2 red marked lines in dreamweaver on the first line $options = [ and on the third line ‘salt’ => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM),

And this is the first time I have been looking into this I don’t knwo what is wrong or right. Is there no way that I can check the password in the old situation for the time beeing?

I’m doing well thanks. They’re pretty disappointed about it, but I don’t think many people were expecting Brazil to win.

I’d stick with the recommendation in the manual and let the function generate the salt for you automatically (Example #1) unless you have a specific reason not to. Note that the salt is part of the returned string, so you don’t need a separate field for it in the DB.

In the first case, I expect your version of Dreamweaver doesn’t recognise the short array syntax. As for the second error I’m not sure, but it’s probably for similar reasons. Your code should still run OK.

Hi fretburner. Thanks again for the reply. I will for sure have a look into this tomorrow

+1

For some reason I am struggling to make this work. I try to follow the advise from fretburner using the build-in password function I have no problem hashing the password, i.e.

$hash = password_hash("$password", PASSWORD_DEFAULT).;

I rather have problems verifying the password in my function: This is how it was before fretburner adviced me to use the build in function:

	      
 $salt = 'zandzeepsodemineraalwatersteenstralen'; 
$hash = crypt($password, '$2a$07$' . $salt);

As you can see did I use a separated salt and hash. For verifying I used:


function attempt($username, $password){
	global $pdo;
	
	$stmt = $pdo->prepare('
		SELECT *
		FROM   operators
		WHERE  username = :username AND password = :password
		LIMIT 1');
		
		$stmt->execute(array(':username' => $username, ':password' => crypt($password, '$2a$07$' . $salt)));	

	if ($data = $stmt->fetch( PDO::FETCH_OBJ )) {
		# set session
		$_SESSION['user_id']     = $data->user_id;
		$_SESSION['user']          = $data->v_naam;
		$_SESSION['username'] = $data->username;
		return true;
	} else {
		return false;
	}
}

So where I have problems with is this part:

':password' => crypt($password, '$2a$07$' . $salt)

How do I accomplish the same using password_verify

Thank you in advance

Rather than comparing the password in SQL, you’ll have to always fetch the user and compare the password in PHP.

function attempt($username, $password){
    global $pdo;

    $stmt = $pdo->prepare('
        SELECT *
        FROM   operators
        [COLOR="#FF0000"]WHERE  username = :username[/COLOR]
        LIMIT 1');

        [COLOR="#FF0000"]$stmt->execute(array(':username' => $username));[/COLOR]

    if ($data = $stmt->fetch( PDO::FETCH_OBJ )) {
        [COLOR="#FF0000"]if (password_verify($password, $data['password'])) {[/COLOR]
            # set session
            $_SESSION['user_id']     = $data->user_id;
            $_SESSION['user']          = $data->v_naam;
            $_SESSION['username'] = $data->username;
            return true;
[COLOR="#FF0000"]        } else {
            // The password didn't match
            return false;
        }[/COLOR]
    } else {
        // The username doesn't exist in the database
        return false;
    }
}

EDIT: The reason you need to do it this way is because you need to read the stored password hash (or, more specifically, the salt and cost stored with the password hash) in order to generate the verification hash.

Hi Jeff. Thank you very much for the reply and the explanation. I have one last question. I just implemented your changes but suddenly get the following error:

Cannot use object of type stdClass as array

What can that be?

Ahh, my fault. $data[‘password’] should actually be $data->password

:tup: Thank you very very much Jeff. Works great.