Password_Hash Returns Different Value Every Time

password_hash returns different value every time

So let's take it one part at a time

but it returns a different hash every time

That's the idea. password_hash is designed to generate a random salt every time. This means you have to break each hash individually instead of guessing one salt used for everything and having a huge leg up.

There's no need to MD5 or do any other hashing. If you want to raise the security of password_hash you pass a higher cost (default cost is 10)

$password = password_hash($password4, PASSWORD_DEFAULT, ['cost' => 15]);

As to verify

if(password_verify($password4, $dbpassword))

So $password4 should be your unhashed password and $dbpassword should be the hash you've stored in your database

password_hash seems to return a random variable

This is the expected behavior. password_hash generates a salt which is used along with the plaintext password to generate a hash. The salt is generated randomly so the output will be different each time you call password_hash.

Use password_verify to verify passwords.

http://php.net/manual/en/function.password-verify.php

All of the information necessary for password_verify to verify a plaintext password is contained in the hash itself. The anatomy of a hash depends on the algorithm used, for the password hash you provided:

$2y$10$wAJr0Z1spRtOcK4cLhIkguUCKgwZKYrwm.nRhm6AtCfDH8ri7ylJu
  • $2y$ This prefix indicates that this is a bcrypt hash
  • 10 This is the cost parameter
  • wAJr0Z1spRtOcK4cLhIkgu The first 22 character is the salt
  • UCKgwZKYrwm.nRhm6AtCfDH8ri7ylJu The remaining 31 characters is the hash

https://en.wikipedia.org/wiki/Bcrypt

PHP password_hash changing every time

The reason you may see a new hash each time your run password_hash this way is because it will automatically generate a new random salt, which will result in a different hash even if the input password is the same.

While, as of PHP 7 the salt option is deprecated, it is definitely not removed from password_hash. Though, you should note that the reason it is deprecated is because it is planned for removal (probably in the next minor release of PHP). The reason it is planned for removal is because it discourages people from using inferior means of generating their salt. Since the function can generate good random salts for you automatically there's really very little reason to want to provide your own.

In any case, password_hash is just a thin wrapper over crypt, which exposes more of the primitives of the underlying API. So if you wanted to provide your own salt through crypt you still could. Though I highly discourage it when PHP can just do it for you with password_hash and in a manner which is not likely to result in error.

Can password_hash create the same hash in different times with the same parameters?

password_hash will add a random salt value. Unique salt values will result in unique hashes with a very very high probability. The random salt will be taken from the best random number generator available on the system, so the probability of it being unique is very very high.

No, there is no guarantee that the salt will be unique, or that the hash will be unique. But it is extremely improbable for you to find a duplicate ever, unless you're generating billions of hashes every second.

If you're just interested in a unique token, just get a random number instead of abusing password hashing functions for something they weren't designed for. Preferably use random_bytes for this.

PHP password_verify with differnet hashes

As noted on the manual page for the password_hash() function,

The used algorithm, cost and salt are returned as part of the hash. Therefore, all information that's needed to verify the hash is included in it. This allows the password_verify() function to verify the hash without needing separate storage for the salt or algorithm information.

When the same inputs - algorithm, cost, salt and password - are fed into the password calculation, the same output will be generated. Thus, the password_verify() takes the algorithm, cost and salt from the original calculation, generates a new hash using the password being tested, and compares the previous result with the newly generated one. If they match, the verification succeeds, otherwise it's an error.

Working with Password_hash and password_verify

The password hash includes a so-called salt, a small random value, which is here to prevent dictionary attacks, here is what PHP manual says:

If omitted, a random salt will be generated by password_hash()
for each password hashed. This is the intended mode of operation.

The value you get as the output, is not really a plain hash, but a
string made of - algorithm id, salt and HASH(password,salt).

The used algorithm, cost and salt are returned as part of the hash.
Therefore, all information that's needed to verify the hash is included.
in it. This allows the password_verify() function to verify the hash
without needing separate storage for the salt or algorithm information.

Issue Migrating Hashing Algorithm in PHP

Theoretically the result of 2. and 3. above should be the same, and would need to be for this to work - but they are not.

No, they shouldn't, and they don't have to be. BCrypt generates its own cryptographic salt which is unique and random, producing a unique random hash for same input.

You don't need (or want!) the same hash produced each time. You can still compare the candidate password (passed through SHA*) against the stored bcrypt hash.

You do not run password_hash(hash('SHA1', '11111111'), PASSWORD_BCRYPT) to test a candidate password against a stored bcrypt hash. You use password_verify which takes care of salting the input and performing the comparison.



Related Topics



Leave a reply



Submit