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?

- 65,582
- 24
- 185
- 221

- 13
- 4
2 Answers
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.

- 15,696
- 5
- 45
- 51
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.

- 65,582
- 24
- 185
- 221
password_hash
andpassword_verify
currently use eitherbcrypt
orargon2
which both use the PHC string format. The salt is included in the hash format. It's not derived bypassword_verify
, it's literally just right there in the hash you give it. – AndrolGenhald Mar 27 '18 at 14:22password_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:39password_hash()
is a deterministic hash value, calculated by a specified hashing algorithm being run a specified number of times on the given inputs of plaintext and random salt. Given that hash value output, doesn'tpassword_verify()
need the original value of the salt to "reconstruct" the output ofpassword_hash()
and compare this against the stored output ofpassword_hash()
? – user1100793 Mar 27 '18 at 14:58password_hash()
is itself part of a hash (it is hashed), therefore obtaining its original value is exceedingly difficult, right? What am I missing? – user1100793 Mar 27 '18 at 14:58password_hash
is a string in the PHC format that specifies the hash used, parameter(s), the salt, and the final hash. The salt is stored right there in the string before being hashed.password_verify
obtains the salt by extracting it from the string you pass it. – AndrolGenhald Mar 27 '18 at 15:08