So I was just thinking about token_authenticatable setup from devise (rails gem), and this thought occurred to me:

Could we strengthen web security by hashing username/password with javascript before sending it to the server?

Obviously we should always use SSL, but even SSL is vulnerable to MITM attacks, wouldn't it be safer if, instead of a password, web servers stored a hash of the username and password, so that even if a user's login hash was recovered, it would only work on one website. Right?

Because lets say that joe shmoe has his gmail account, with a username of [email protected] and a password of joeshmoe. Now Mr. Shmoe signs up with mylazywebsite.com which doesn't use SSL, using the same password as his gmail account, now his whole online identity has been compromised.

2 Answers 2


If the protocol you use is vulnerable to Man-in-the-Middle attacks, then you lose anyway, regardless of how much hashing you apply: the MitM attacker can just wait for your authentication to be performed, and then hijacks the connection at that point. I must say, though, that SSL is NOT vulnerable to MitM, as long as nobody does anything stupid (for instance, looking at a big red warning from the browser which says "this server uses an invalid certificate" and clicking "shuddup I want to connect anyway" is "something stupid").

So we are talking about a user who did something bad enough to breach SSL; and the same user also reused the same password on several sites. Unfortunately, there are many users who do such things. Your proposal suffers from two main issues:

  • Password storage should use password hashing, with salts and slowness. A large number of iterations is applied, so that an attacker who could dump the server's database still suffers a lot when trying to crack the passwords. But in your case, this hashing MUST necessarily occur on the client side, in Javascript. Javascript is far (very far) from having enough muscle to do that. This would imply dividing the iteration count by at least 10 (probably more) so that login time remains tolerable, thus dividing by at least 10 security against an offline dictionary attack.

  • Javascript. The code which does the hashing has just been served by the server itself, over the connection that we assumed to be under a MitM attack. Such an attacker can modify this Javascript at will. Namely, he can add a tiny bit of extra Javascript which also sends the login and password (as entered by the user) to his own evil server.

The second point makes the discussion moot: if an attacker can run a successful MitM, then he can grab the password from the source, i.e. the entry field in the Web page, and no amount of Javascript can change anything to that.

  • 1
    as long as nobody does anything stupid (for instance, looking at a big red warning from the browser which says "this server uses an invalid certificate" and clicking "shuddup I want to connect anyway" is "something stupid" - don't worry, at least 90% of people will Commented Sep 22, 2013 at 19:37
  • I guess that if someone can run MiTM, they can also run MITB which then defeats the purpose. Good point. Commented Sep 22, 2013 at 19:38
  • @bwheeler96: Running MITB is much more difficult. For example, running MiTM is often as simple as running a wifi hotspot and seeing who uses it (and hoping they don't use SSL). MITB attacks require tricking the user into downloading a vulnerable browser or taking advantage of an unpatched vulnerability.
    – Brian
    Commented Sep 23, 2013 at 16:38

Yes. Per Tom Leek, this cannot be done server-side. There are browser extensions which hash passwords (using the domain as part of the unhashed password) before sending it to a server. This does not provide protection against all MiTM attacks, though it does protect against some types of attacks.

There are a few benefits to this approach:
1. Users can use the same password on every site, without the associated vulnerabilities.
2. Phishing sites are given the "wrong" password.
3. The hashed password is usually cryptographically stronger than the original password.

And a few downsides:
1. User must trust the extension.
2. If the extension uses broken hashing, the user's situation is not substantially better than if the user had used the same password on every site.
3. The generated password may not be accepted on some sites (e.g., consider two sites, one which won't accept passwords contains symbols and another which requires symbols). Making this configurable is possible, but makes the program more difficult to use.
4. This protection may fail if the user types the password directly into the site, since the site could be listening via javascript. Well-designed hashing tools will mitigate such attacks by using a unique private key as part of the hash.
5. Assuming the user has a private key, logging into a site will fail if the user is on a different computer or their current computer somehow loses the key (due to an upgrade or the like). If this private key is password-based, then the hash-based solution because pointless; at that point it's a glorified password manager.

  • Right, this is essentially what I was looking for. It doesn't protect against the MITM attack itself, but it could protect against the identity-wide implications. Commented Sep 23, 2013 at 18:34
  • Actually, it doesn't protect you from those, either. An attacker could copy your hash from a known site (his phishing site, for example), and brute force recover your secret password, unless you used PBKDF2 (which is beyond the capability of JavaScript) or a very very long and strong password. Commented Sep 23, 2013 at 19:07
  • @JohnDeters: As my proposal is about a browser extension, the use of PBKDF2 is feasible (and it's perfectly possible to implement PBKDF2 in javascript). And there's nothing stopping the extension's generated secret from being very complex. So, reversing the hash from via brute force would impossible (since the user's original password is mostly random, from the hacker's perspective, and thus there is no way to differentiate the password from other passwords which yield the same hash). This assumes the use of a unique private key, as mentioned in downside #4.
    – Brian
    Commented Sep 23, 2013 at 19:29
  • A random javascript PBKDF2 implementation: anandam.name/pbkdf2
    – Brian
    Commented Sep 23, 2013 at 19:31

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .