2

The oft-mentioned approach for website password-handling is to use a server-side language to employ a suitable hashing algorithm (stretched or otherwise designed to overly-consume computing resources), combine with a randomised salt, and voila: a safely stored password. I'm over-simplifying, of course.

Whilst this stops stolen database tables from containing potentially-reused passphrases, it still means the password has to be delivered to the server to be hashed, the result of which being compared to the stored hash. SSL secures this during transportation, naturally, but there's still a window of the plaintext passphrase existing for the hashing to be done.

What if the hashing took place on the client-side? The user would still be using a passphrase that doesn't match the stored end-result, and a tech-savvy individual bypassing the JavaScript and sending a hash directly wouldn't achieve anything. Furthermore, server-side hashing could be implemented for clients lacking JavaScript. By doing this, server-load is reduced and a covertly-comprimised server still wouldn't get any passwords as the site continued running.

TL;DR: The only issue I can see is that the client's randomisation for the salt could not be trusted. Is this the only reason this approach isn't more widely recommended?

schroeder
  • 123,438
  • 55
  • 284
  • 319
Louis Jackman
  • 463
  • 2
  • 10
  • 1
    If javascript performance is good enough to achieve a large enough work factor, you can use client side hashing. – CodesInChaos Feb 04 '14 at 16:01
  • @CodesInChaos: I gather the combination of modern JS virtual machines and explicit optimisations like asm.js would perform reasonably well. Ofc any slowdowns shouldn't be used as 'computational complexity' for the algorithm since they could just reimplement it in C from the JavaScript... – Louis Jackman Feb 04 '14 at 16:08
  • From what I understand, and I do not claim to be an expert, you should not soly realy on client-side hashing. You are sending the server a secret, useually this secret is a password/passphrase. When you start hashing client-side the hash will become the secret, unless you do some server-side hashing in addition to the client-side hashing I could login as anyone I want if I have access to the database. It would be limited to anything that uses said database though. – Darsstar Feb 04 '14 at 16:12
  • Surely hashes are used over storing passphrases presisely because hashes are assumed to be a comprimised secret in the case of database comprimise? Also, the only way such a hash could be reasonably generated is by using the mandated hashing function on the correct passphrase, vulnrabilities notwithstanding. As for client-side theft or whatever, I guess such attacks would work for a password submittal too. – Louis Jackman Feb 04 '14 at 20:53

2 Answers2

8

Password hashing must be applied to cope with the inherent weakness of passwords, i.e. the low entropy. Whether the hashing occurs on the client or the server does not matter much for security, as long as it occurs somewhere between the human and the storage. Since good password hashing uses a salt, stored server-side, client-side hashing usually incurs an additional round-trip (client sends the user name, server sends back the corresponding salt, client hashes the password and sends the result). Also, since what the client sends is password equivalent (showing it grants access), and you don't want to store password-equivalent values "as is" in your database, you still need to do some hashing on the server -- but that one can be a simple, unsalted, uniterated hash.


Password hashing with Javascript can be a problem, though: password hashing is an arms race between the defender and the attacker. The password hashing function is made deliberately slow in order to make exhaustive search expensive; but this makes usage expensive for everybody. If the hashing is done in Javascript, then it will happen at Javascript speed, i.e. not very fast. Correspondingly, you won't be able to crank up the iteration count as high as you would like, compared to the situation where hashing occurs on the server.

The above is the generic answer, but details may vary. Javascript interpreters tend to become faster over time. More importantly, a given server may have to handle many clients simultaneously, while each client only has to worry about itself. If the server must handle 100 clients per second and still keep authentication time within one second, then it cannot allocate more than 10ms worth of its CPU per password instance; whereas with client-side hashing, the client can use one full second for it, which might be enough to more-than-compensate the slowness of Javascript.

100 clients per second is a high figure, and though some Javascript clients appear to be quite fast, there also are clients out there which are not (e.g. people with old smartphones -- my own smartphone runs Android 2.2, and the Javascript interpreter in its browser is not a race champion). For this reason, right now, it seems that client-side password hashing with Javascript is not (yet) a winning idea. This may change in the future, or in some specific situations. For instance, client-side hashing has the benefit of much improving the server resistance to some DoS attacks; if resistance to DoS is deemed more important than mobile phone user experience, then client-side hashing is the way to go.

For a general introduction to password hashing, including client-side vs server-side concepts, see this answer.

Tom Leek
  • 168,808
  • 28
  • 337
  • 475
  • I saw a demo of Enscripten, a native-code-to-JS compiler. The subject was an Unreal Tourmanent engine, which actually ran smoothly within a browser window! I guess this means client-side validation is more viable than ever before? – Louis Jackman Feb 04 '14 at 20:55
  • To elaborate, if outputted JavaScript can run a complex FPS game engine smoothly, then maybe stretched hashing has a good chance. That said, much of a game engine's performance is derived from graphics, i.e. fast graphic card hardware which JavaScript won't have access too, so maybe not... – Louis Jackman Feb 04 '14 at 20:58
2

As Tom Leek points out in his excellent answer (which he penned in 2014) - with client-side hashing... 'what the client sends is password equivalent'.

This is why we now have protocols like PAKE and SRP. With PAKE or SRP, the server authenticates the client based on a password known by the client - but without the password (or password-equivalent data) being sent 'over the wire'. In fact, password (or password-equivalent data) is not even through the SSL/TLS connection.

PAKE/SRP also offer the following benefits:

  1. Authentication is mutual. Not only does the server authenticate the client, but the client authenticates the server as well.

  2. The server does not store the password (or password-equivalent data). In the event of a server database breach, the stored information is resilient to dictionary attacks.

  3. As mentioned previously, password (or password-equivalent data) is not sent 'over the wire'. An eavesdropper (or even an attacker that MITM's the SSL/TLS connection) is not able to gain enough information to derive the password from the information sent over the wire. This effectively prevents phishing sites and man-in-the-middle attackers from stealing users' passwords.

See https://blog.1password.com/developers-how-we-use-srp-and-you-can-too/ for a good write-up on how 1password successfully implemented SRP.

mti2935
  • 19,868
  • 2
  • 45
  • 64