Encryption with bcrypt + random salt

Asked

Viewed 946 times

3

I have a simple question about encryption using bcrypt with salt.

When in old projects I used md5, to check in a login form if the user typed the correct password and authenticate, it was customary to take the value that the user typed and encrypt in md5 and search in the bd.

But as in bcrypt using random salt does not to do this, so I did the following:

I take the email or Cpf that the user typed in the login field, look in the bd for the corresponding record and use the password stored in the bd(hash) as salt and the password entered by the user as the string in the crypt($string, $salt) function and the return of the function compares with the password stored in the bd, and by logic the function must generate exactly the hash itself.

Follow a piece of my code just so you’ll understand better what I’m talking about

 //Exemplo da busca com cpf
 $buscar = $con->prepare("SELECT * FROM usuarios WHERE cpf =:cpf");
 $buscar->bindValue(":cpf", $login);
 $buscar->execute();
 $row = $buscar->fetch();

 //Armazena a senha que esta no bd
 $senha_armazenada = $row['senha'];

 //Comparação que estou fazendo
 if(crypt($senha_digitada, $senha_armazenada) === $senha_armazenada)

And it’s working, but I want to know if it’s the right way to do it.

2 answers

3


First, never do that:

if(crypt($senha_digitada, $senha_armazenada) === $senha_armazenada)

Any string is a secret should never be compared using == or ===, This is not constant time and exposes the timming-Attack. This does not occur if use password_verify() and neither hash_equals.


The salt is generated within the function itself, including they already inform that defining a custom salt is "obsolete". Nor will I get into the merit of why they did it.

When you do:

password_hash('senha_legal', PASSWORD_BCRYPT, ['cost' => 15])

The function itself obtains a safe salt (from a safe PRNG) and makes the derivation of the key based on the defined force. There is no need for you to generate a salt, because the chance for you to do it wrong (using rand(), mt_rand() or even time()) is much bigger.


In PHP 7.2 there is PASSWORD_ARGON2I, which uses Argon2i (PHC winner) instead of Bcrypt, in this case use:

password_hash('senha_legal', PASSWORD_ARGON2I, ['memory_cost' => 1<<18, 'time_cost' => 4, 'threads' => 4])

You can also use the sodium_crypto_pwhash_str() which also uses Argon2i, it is already available as long as you install PECL.


About use of Pepper there is not much information about it, in the case of Bcrypt this can get worse, because it will reduce the use of up to 72 bytes.


Also, ensure that the password entered by the user does not have 0x00 (null bytes), if not this var_dump(password_verify('a', password_hash(pack('H*', '6100626364'), PASSWORD_DEFAULT))); will return true, as I have used as an example in other answers.

  • I’ve been reading the php documentation about password_hash and it contains the following information about PASWORD_DEFAULT "Note that this constant is designed to change over time as new and stronger algorithms are added to PHP". Given the information contained in this excerpt of the documentation, wouldn’t it be better to always use PASSWORD_DEFAULT instead of using some specific algorithm? Since php will always keep the most effective algorithm as standard?

  • 1

    They will always take an entire version to change, if really change. They can only do this in PHP version 7.3 and not in PHP 7.2, which will already have these features. I believe it’s better that you choose than wait for others to choose for you, but there’s already a question about it here.

1

  • From what I understood of these functions then I don’t need to generate a random salt? the password_hash() function itself will take care of this? And if I do something like: password_hash("string", PASWORD_DEFAULT) it would already generate a hash with bcrypt and salt?

  • 1

    That’s it. From what I understand the advantage of bcrypt about the md5 is that the former works in a slower way purposefully to avoid brute force attacks and in the case of the hash_password he uses the bcrypt but he himself creates the salt without need of its intervention as in bcrypt.

  • 1

    Oh and even with this extra security, I recommend studying the google api recaptcha or similar. Then yes you rule out brute force attack on your site. It’s quite easy to implement. https://www.google.com/recaptcha/intro/android.html

Browser other questions tagged

You are not signed in. Login or sign up in order to post.