0

Regarding the PHP function password_verify(), how is the "unhashed" random salt derived from the output of password_hash(), given that hashing functions are deterministic? It seems to me that, if the original salt is able to be derived from the final hash, then the salt was only used to produce the final hash after the hashing function has completed its iteration count. If this is the case, why use a salt in the first place? Why not just provide some arbitrary (but still large) iteration count?

  • 1
    password_hash and password_verify currently use either bcrypt or argon2 which both use the PHC string format. The salt is included in the hash format. It's not derived by password_verify, it's literally just right there in the hash you give it. – AndrolGenhald Mar 27 '18 at 14:22
  • 1
    @AndrolGenhald You could probably post that as an answer, Androl. – Adonalsium Mar 27 '18 at 14:38
  • @AndrolGenhald Thanks for your comment, but I'm still not understanding. I do understand that the salt is included in the output of password_verify, but isn't that salt hashed as well? Meaning that its original value cannot be obtained for use in verification (in a reasonable amount of time, anyway). – user1100793 Mar 27 '18 at 14:39
  • 1
    @user1100793 Do you understand why salts are used? All that is required of a salt is that it be universally unique, it's not supposed to be any more secret than the hash. – AndrolGenhald Mar 27 '18 at 14:43
  • This seems more like a question about salts in general than a question about the implementation in php. Please edit your question to make clear what you are acutally interested in. Note though, that there are already a lot of questions concerning salts on this site. – Tom K. Mar 27 '18 at 14:55
4

password_hash and password_verify currently use either bcrypt or argon2 which both use the PHC string format. The salt is included in the hash format. It's not derived by password_verify, it's literally just right there in the hash you give it. This is not a weakness because a salt is not required to be secret, it must only be universally unique.

Your confusion about how password_verify obtains the salt seems to be caused by conflicting terminology. The word "hash" is often used to refer to the entire PHC format string (including the hash function identifier, parameters, salt, and actual hash value), as well as the actual hash output by a hashing function.

See here for why salts are used. If you want a secret that an attacker would have to know to hash passwords, that's called a pepper.

0

Take a look at this extreme simplification of what goes on under the hood in PHP:

password_hash(password):
    salt = get_random_salt()
    hash = actual_hashing_function(salt + password)
    return salt + hash
password_verify(password, password_hash):
    salt, actual_hash = split(password_hash)
    compare_hash = actual_hashing_function(salt + password)
    return actual_hash == compare_hash

As you can see, password_hash can not be deterministic as part of the output - the salt - depends on a random function. However, actual_hashing_function is deterministic.

The confusion here stems from somewhat imprecise terminology. In a cryptography context, "hash function" probably referes to something like actual_hashing_function in the example, and a "hash" means it's output. However, in a more applied context like programming, "hash function" might mean something like password_hash and a "hash" it's non deterministic output that includes the salt.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.