| It stops them from using the password to log in to your other accounts. It stops a compromised server from silently leaking unhashed passwords. It makes password hashing user auditable. You could even do a call and response model to stop the hashed password to log in at all. Here is a primitive scheme for such a model (public key crypto probably enables more clever schemes, not sure): - Upon signup, generate hashes of "$password$site$i" for i in 1 to 1000. Send these to the server and have the server hash them again. - Upon login, after the user has entered their password into the box, send an integer from i from 1 to 1000 to the browser, have the browser send back the hash of "$password$site$i". Now a compromised hash can only let you log in 1 time in 1000. Combine that fact with the other available signals for "is this who we think it is" and you should be able to reject people who stole the hash reasonably reliably. Meanwhile since you are still hashing the password on the server (again) you have lost literally nothing but a tiny bit of computation time. |
There's nothing stopping you from hashing your own passwords client side and sending your bcrypt hash up to the server except some sites still truncate the passwords to 32/16 chars etc.
When you have the need for the level of security, client side hashing will not be as good as dedicated HSMs that many services now use on authentication.
Writing your own crypto flows can be extremely dangerous as you open yourself to all kinds of side channel attacks.