https security - should password be hashed server-side or client-side?

If you hash on the client side, the hashed password becomes the actual password (with the hashing algorithm being nothing more than a means to convert a user-held mnemonic to the actual password).

This means that you will be storing the full "plain-text" password (the hash) in the database, and you will have lost all benefit of hashing in the first place.

If you decide to go this route, you might as well forgo any hashing and simply transmit and store the user's raw password (which, incidentally, I wouldn't particularly recommend).


Hashing on the client makes sense only if you do not trust the server in some way, and do not want to show it the "actual" password (the one which the human user remembers). Why would you not want to show the password to the very site on which the said password has any use ? Because you have reused the password elsewhere ! Now that's usually bad, but there is a relatively safe version which is incarnated in myriads of browser extensions or bookmarklets such as this one or that one (I don't vouch for their quality). These are tools where the human user remembers a "master password", from which a site-specific password is generated, using the site domain name as a kind of salt, so that two distinct sites get distinct passwords.

While this scenario makes sense, doing it with Javascript sent by the server itself does not. Indeed, the point of hashing the password client side is that the server is potentially hostile (e.g. subverted by an attacker), and thus Javascript code sent by that server is, at the very least, suspect. You do not want to enter your precious password in some hostile Javascript...


Another case for client-side hashing is about slow hashing. Since passwords are, by definition, weak, you want to thwart dictionary attacks. You assume that the bad guy got a copy of the server database, and will "try passwords" on his own machines (see this blog post for some discussion on this). To slow down the adversary, you employ an inherently slow hashing process (such as bcrypt), but this will make the processing slow for everybody, including the server. To help the server, you might want to offload some of the work on the client, hence do at least part of it in some Javascript code running in the client browser...

Unfortunately, Javascript is awfully slow at this kind of job (typically 20 to 100 times slower than decent C code), and the client system will not be able to contribute a substantial part to the hashing effort. The idea is sound but will have to wait for better technology (it would have worked with a Java client, though: with a decent JVM, optimized Java code is about 2 to 4 times slower than optimized C code, for a hashing job).


To sum up, there is no really good case for doing client-side password hashing, from Javascript code sent by the server itself. Just send the password "as is" to the server through an HTTPS tunnel (the login page, the form destination URL, and whatever page are protected by the password, shall all be served over SSL, otherwise you have more pressing security issues than the use of passwords).


I find all your concerns sound, but my recommendation would be to do it server-side.

There's always a fairly big chance that a user will leave their terminal unlocked, allowing manipulaton. And also; if your hashing logic is client-side you're exposing it.

Another option would be to generate the passwords server-side; then you're not sending in a clear-text password. But you'd still need to communicate the password to the user. And since most users still don't use encrypted email, I consider that less secure.

I've seen solutions to send passwords through an encrypted tunnel to a cellphone; but I doubt the security is better than the SSL. Perhaps someone could prove/disprove this?