What you are looking at here is more than a password hash, there is a lot of hash metadata included in these lines. In bcrypt terms, the entire string will be considered a bcrypt hash. Here is what it includes:
$ is a delimiter in bcrypt.
$ 2a $ - used bcrypt algorithm.
$ 10 $ is the cost factor that was used. This is why bcrypt is very popular for storing hashes. Each hash has a complexity / cost associated with it, which you can think about how quickly the computer will generate this hash. This number, of course, refers to the speed of computers, since computers are becoming faster and faster over the years, it will take less time to create a hash with a cost of 10. So next year you will increase the cost to 11, then to 12 ... 13 ... and so on. This allows your future hashes to remain strong while maintaining the old hashes. Just note that you cannot change the value of a hash without renaming the original string.
$ QyrjMQf ... is a combination of salt and hash. This is a base64 encoded string.
The first 22 characters are salt.
The remaining characters are a hash when used with algorithm 2a, worth 10 and this salt. The reason for the salt is that the attacker cannot pre-compute the bcrypt hashes to avoid paying the cost of generating them.
Actually, this is the answer to your original question: the reason is that the hashes are different, because if they were the same, you would know that at any time when you saw the line bcrypt $2a$10$QyrjMQfjgGIb4ymtdKQXI.WObnWK0/CzR6yfb6tlGJy0CsVWY0GzO , you know that the password will be abcd , so you can just scan the hash database and quickly find all users with the abcd password by looking at this hash.
You cannot do this using bcrypt, because $2a$10$dQSPyeQmZCzVUOXQ3rGtZONX6pwvnKSBRmsLnq1t1CsvdOTAMQlem also abcd . And there are many more hashes that will result from bcrypt('abcd') . This makes database scanning for abcd passwords next to impossible.
Ryan
source share