Bcrypt and randomly generated salts

So, I experimented with bcrypt. I have a class (shown below, which I got from http://www.firedartstudios.com/articles/read/php-security-how-to-safely-store-your-passwords ), which has 3 functions. The first one must create a random salt, the second one to generate a hash using the 1st generated salt, and the last one to verify the password provided, comparing it with the hashed password.

<?php /* Bcrypt Example */ class bcrypt { private $rounds; public function __construct($rounds = 12) { if(CRYPT_BLOWFISH != 1) { throw new Exception("Bcrypt is not supported on this server, please see the following to learn more: http://php.net/crypt"); } $this->rounds = $rounds; } /* Gen Salt */ public function genSalt() { /* openssl_random_pseudo_bytes(16) Fallback */ $seed = ''; for($i = 0; $i < 16; $i++) { $seed .= chr(mt_rand(0, 255)); } /* GenSalt */ $salt = substr(strtr(base64_encode($seed), '+', '.'), 0, 22); /* Return */ return $salt; } /* Gen Hash */ public function genHash($password) { /* Explain '$2y$' . $this->rounds . '$' */ /* 2a selects bcrypt algorithm */ /* $this->rounds is the workload factor */ /* GenHash */ $hash = crypt($password, '$2y$' . $this->rounds . '$' . $this->genSalt()); /* Return */ return $hash; } /* Verify Password */ public function verify($password, $existingHash) { /* Hash new password with old hash */ $hash = crypt($password, $existingHash); /* Do Hashs match? */ if($hash === $existingHash) { return true; } else { return false; } } } /* Next the Usage */ /* Start Instance */ $bcrypt = new bcrypt(12); /* Two create a Hash you do */ echo 'Bcrypt Password: ' . $bcrypt->genHash('password'); /* Two verify a hash you do */ $HashFromDB = $bcrypt->genHash('password'); /* This is an example you would draw the hash from your db */ echo 'Verify Password: ' . $bcrypt->verify('password', $HashFromDB); ?> 

Now, if I create a hash with a "password", for example, I get a hashed password that took the received Randmonly Salt. Then, if I enter the password again and use the verification function, I get a true value, meaning that the passwords match. If I enter the wrong password, I get false. My question is how is this possible? What about randomly generated salt? Why does this have no effect?

+4
source share
1 answer

A good look at the values ​​you are dealing with. The resulting random salt will be, say:

 abcdefg... 

What is served in crypt as follows:

 crypt($password, '$2y$10$abcdefg...') | | | | | +- the salt | +- the cost parameter +- the algorithm type 

The result looks like this:

 $2y$10$abcdefg...123456789... | | | | | | | +- the password hash | | +- the salt | +- the cost parameter +- the algorithm type 

In other words, the first part of the resulting hash matches the original input to the crypt function; it contains the type and parameters of the algorithm, a random salt, and a hash result.

 Input: $password + $2y$10$abcdefg... Output: $2y$10$abcdefg...123456789... ^^^^^^^^^^^^^^^^^ first part identical 

When you confirm the password, you again need the same original salt. Only with the same salt will the same password hash with the same hash. And it is still present in the hash, in a format that can be transferred to crypt , as well as repeating the same operation as when generating the hash. To do this, you need to pass the password and hash to the verification function:

 crypt($passwordToCheck, '$2y$10$abcdefg...123456789...') 

crypt takes the first specified number of characters, up to abcdefg... and includes the rest (why salt should be a fixed number of characters). Therefore, it is equal to the same operation as before:

 crypt($passwordToCheck, '$2y$10$abcdefg...') 

And it will generate the same hash, if and only if $passwordToCheck is the same.

+13
source

Source: https://habr.com/ru/post/1482574/


All Articles