104

There are very few websites that hash the users password before submitting it to the server. Javascript doesn't even have support for SHA or other algorithms.

But I can think of quite a few advantages, like protection against cross-site leaks or malicious admins, which SSL does not provide.

So why is this practise so uncommon among websites?

6
  • 13
    What advantages do you think there are to client side hashing of passwords? Mar 18, 2014 at 10:34
  • 10
    @TimLamballais A typical client can spend far more time on hashing than a server. So if you have a high performance implementation in the client (which rules out javascript in current browsers) you can use more expensive and thus stronger password hashes. It also means that the server never sees the password itself. Client side hashing is also a prerequisite for augmented PAKE protocols like SRP where impersonating the server doesn't give you access to the password. Mar 18, 2014 at 10:58
  • 6
    Javascript isn't really that slow anymore. Modern javascript engines have become so fast that they are on-par with compiled languages and recent additions like typed arrays provide the proper tools for the number-crunching required for cryptography.
    – Philipp
    Mar 18, 2014 at 11:57
  • 10
    @TimLamballais One advantage would be that the server never sees my real password, and cannot possibly leak it (yes, they can still leak the hash, but it should be salted by the domainname, so useless for login to other sites). But for the largest advantage see my comment to Phillip's answer.
    – Maestro
    Mar 18, 2014 at 13:43
  • 3
    A lot of people question whether any extra security is gained with this practice. One thing it does do is reduce risk. If you always hash or encrypt (I've seen steam/valve encrypt with a public key and I bet they are not decrypting) there is no chance of you ever having an embarrassing plaintext breech. No...it isn't any more secure but it isn't pointless
    – user11869
    Mar 18, 2014 at 14:34

12 Answers 12

71

Inventor of JavaScript password hashing here

Way back in 1998 I was building a Wiki, the first web site I'd built with a login system. There was no way I could afford hosting with SSL, but I was concerned about plaintext passwords going over the Internet. I'd read about CHAP (challenge hash authentication protocol) and realised I could implement it in JavaScript. I ended up publishing JavaScript MD5 as a standalone project and it has become the most popular open source I've developed. The wiki never got beyond alpha.

Compared to SSL it has a number of weaknesses:

  • Only protects against passive eavesdropping. An active MITM can tamper with the JavaScript and disable hashing.
  • Server-side hashes become password equivalents. At least in the common implementation; there are variations that avoid this.
  • Captured hashes can be brute forced. It is theoretically possible to avoid this using JavaScript RSA.

I've always stated these limitations up front. I used to periodically get flamed for them. But I maintain the original principle to this day: If you've not got SSL for whatever reason, this is better than plaintext passwords. In the early 2000s a number of large providers (most notably Yahoo!) used this for logins. They believed that SSL even just for logins would have too much overhead. I think they switched to SSL just for logins in 2006, and around 2011 when Firesheep was released, most providers switched to full SSL.

So the short answer is: Client-side hashing is rare because people use SSL instead.

There are still some potential benefits of client-side hashing:

  • Some software doesn't know if it will be deployed with SSL or not, so it makes some sense to include hashing. vBulletin was a common example of this.
  • Server relief - with computationally expensive hashes, it makes sense for the client to do some of the work. See this question.
  • Malicious admins or compromised server - client-side hashing can prevent them from seeing plaintext passwords. This is usually dismissed because they could modify the JavaScript and disable hashing. But in fairness, that action increases their chances of being detected, so there is some merit to this.

Ultimately though these benefits are minor, and add a lot of complexity - there's a real risk that you'll introduce a more serious vulnerability in your attempt to improve security. And for people who want more security than password, multi-factor authentication is a better solution.

So the second short answer is: because multi-factor authentication provides more security than client-side password hashing.

12
  • 5
    What if, the server has been compromised by a cracker and he'd like to gather plain passwords from clients to use them at other places? No safeguard but client-side hashing. Why must we force clients to trust the server? Feb 4, 2019 at 7:16
  • 1
    @КонстантинВан - please refer to the "compromised server" part of the answer
    – paj28
    Feb 4, 2019 at 10:04
  • 3
    Another drawback of client side hashing is that you cannot enforce password policy on the server. Basically you cannot validate that the user selected password is strong enough
    – Michael
    Apr 16, 2019 at 6:24
  • 7
    @Michael That's a good thing in my opinion, since password policies on most servers are ridiculous. Many password characters are forbidden for no reason. Jun 18, 2019 at 10:04
  • Clientside-salted hashing completely ELIMINATES the need for any for password policies. THIS IS WHY IT SHOULD BE DONE.
    – 8vtwo
    Aug 9, 2021 at 5:41
55
+50

To understand this problem, first you have to understand why we hash passwords. It is completely possible to store a password in plain text on a server and simply compare the password transmitted to the password received. As long as the password is protected in transit, this is a secure means of authentication (shared secret).

The reason that passwords are hashed is because the problem isn't the authentication, but the storage. If the server is ever compromised, the attacker would immediately have access to all user accounts as they would now know the secret used for authentication of the users.

Hashing acts as a barrier to this. Since the server doesn't know the actual input required to authenticate, even a compromise to the DB does not grant an attacker access to the user accounts. They would still need to figure out the input to give to reach the hash values the application checks against. Sure they could alter all the values to something they know, but this would rapidly throw up suspicion and the system would be shut down and secured.

So, the problem with client side hashing is that it effectively makes the result of the hash the password rather than the password. There is nothing to stop an attacker from bypassing the official client and simply sending the finished hash to the server directly. It provides no additional (or loss) of security during the authentication, but under the situation that hashing is designed to protect against, it offers nothing since the hash stored in the DB is actually the shared secret transmitted to the server.

That said, there are two notable thing client side hashing does give you. While it doesn't help protect your system at all, it may help protect your user. If you are insecurely transmitting the password or the transmission gets compromised without the client code getting compromised, you will still protect the user's password (which they may reuse on other sites) from being leaked.

The other is that you can provide additional iterations of a hash to make an offline attack against the DB more difficult without having to use server cycles (while also extending the length of the "intermediate password that the client submits"), but you still need sufficient server cycles to protect the lengthened password against a rogue client. Again, the primary protection this offers is preventing the original password from being discovered but does nothing for helping protect the authentication mechanism of your site.

Put another way, while it does provide some minor protections, from the point of view of the server, the client side hash should be treated as if it was the user's direct password. It provides no more or no less security on the server than if the user had directly given their password and should be protected as such.

If you want to be able to provide that extra level of security, I would recommend two hashes. Hash once client side to build a new, unique password, then hash that password on the server to make a value you store in the DB. This way you get the best of both worlds.

For the most part, SSL is trusted sufficiently to protect the exchange that the initial hash prior to transmission is seen as unnecessary though and a compromised server could always alter the code sent to the client such that the initial hash isn't performed. It simply isn't an effective alternative to SSL and doesn't offer enough additional advantage to be worth the costs and complexity.

26
  • 5
    @Muis - my point is simply that you should treat the hash generated client side as if it was the user's own password when dealing with it server side. It isn't bad to use a client side hash to protect the user's password from being exposed to the server, but it practically acts like the user's direct password as far as the server is concerned. Mar 18, 2014 at 13:52
  • 1
    My main worry is that the leaked password can be used to login to OTHER sites, where the customer used the same username/password combination. This will be prevented by adding the domainname to the hash (since I cannot store an unique value persistently in javascript).
    – Maestro
    Mar 18, 2014 at 14:10
  • 6
    Why not simply do both then? Hash on the client side to avoid leaking the actual clear-text password and hash again on the server side to avoid the hash-becoming-the-password problem.
    – Xaser
    Aug 27, 2016 at 8:29
  • 3
    @uhfocuz No. Not at all, for a great many reasons. The primary issue is that for login purposes, the client side hash would be the user's password, not whatever the user types, as the server can't verify what the client side did. Further, without protection on the channel providing the content of the page, a man in the middle could simply strip the client side hash entirely and capture the user's password. Finally, even without these issues, unless the password represents the same degree of entropy as the key used in SSL, it would be easier to brute force a hash collision. Aug 28, 2016 at 5:19
  • 1
    @uhfocuz that's my point. It doesn't provide a more secure medium. Two different hashing algorithms doesn't really matter. I never said you couldn't do a client side hash, just that the nature of a client side hash really doesn't offer you much of anything in terms of security. It only protects a user that is using the same strong password in more than one place from having the password sent to the server. That's a very limited advantage for quite a lot of work and potential increased xss surface area. Aug 28, 2016 at 17:45
22

If you have quite a few advantages, then you should list them in your question so that people will find out whether they are truly useful (and you may become famous if so ;)

People don't favor client-side hashing because they have better ways of protecting users private information. Let's think about the places with potential information leaks and there are three of them:

  • The client.
  • Between the client and the server.
  • The server.

Then let's see why or why not client-side hashing will help in these places.

  • The client.

    If there are malwares on your own computer, for example, if your browser is compromised or your computer is implanted with key-logging software, client-side hashing doesn't prevent a hacker from getting your password. The reason is obvious.

  • Between the client and the server.

    There is the communication channel between client and server. If there is an eavesdropper listening for the communication, then client-side hashing can make the leak of password more difficult because the eavesdropper has to recover the original password from its hash. It's indeed useful here.

    However, this vulnerability is based on the presupposition of an insecure communication channel. In reality, there are protocols whose existence tries to solve this problem exactly. Their major task is to establish a secure channel over an insecure one. The most famous and widely deployed example is SSL/TLS, and it provides more functionality and better security than client-side hashing.

    The conclusion is that client-side hashing is helpful in the channel, but here are better tools.

  • The server.

    Users information may be leaked on the server if the server is compromised by a hacker. The hacker can fetch user passwords from database if they are stored in plaintext. That's why today most servers don't do that. Instead, they store hashes of passwords so that hackers can't easily restore the original passwords from their information at hand (i.e. hashes).

    You may be tempted to believe things still work well if the server simply stores hashes computed on the client side. But this is severely wrong. In that situation the hashes themselves become password equivalents. The hacker can pass authentication by simply handing over the hash without reversing it. The goal of a hacker is not reversing a hash, but breaking into your account. The importance lies in the server's verification process on client data, not on the fact that the data is a hash value. Therefore the benefit of client-side hashing is trivial here and the server must rehash anyway.

To summarize, client-side hashing is helpful in protecting user information, but the protection largely applies to the communication channel. Since we have better approaches there (SSL/TLS), the application of client-side hashing is greatly surpressed. It's simply not the best tool for the task at hand.

12
  • 27
    Re: this statement: "The goal of a hacker is not reversing a hash, but breaking into your account." I would say that depends on what the site is. Oftentimes the user's password is more valuable than access to the site, with the hopes that the password may be used on other sites where gaining access would have more value.
    – TTT
    Nov 29, 2016 at 15:00
  • @TTT From its context, this sentence actually means the hacker doesn't care about whether it's a hash or a plaintext password as long as he gets the private information he wants.
    – Cyker
    Nov 30, 2016 at 2:39
  • 1
    This answer is super helpful.
    – NDiaz
    Nov 30, 2016 at 19:31
  • 7
    I agree with TTT. I disagree that it is "better" (as you've said) for the client to send their password in plaintext instead of a salted hash. This opens up the risk that some server-side agent steals or leaks the client password, either by malicious intent or negligence. Since many users re-use password cross-side, it's a very concerning risk. Dec 24, 2016 at 2:32
  • 1
    @Cyker Yep, if everyone would use a password manager with unique, random passwords, we would not have to have this discussion! But that's just not the case, we all know how frequently sites get hacked and that the data is used to hack the users on other sites, where they re-used their password. It's indeed not your job to protect the user, but neither is it your job to fix water in Africa. Still, countries that can afford it pay development aid (and in democratic countries, people collectively agree on it). We help other people where we can, so if we can just hash in a better spot, why not?
    – Luc
    Jan 10, 2019 at 0:07
8

It is good practice to hash on the client side, then salt the password and hash again on the server side. This is an extra layer of protection against man in the middle attacks. SSL is the first layer however Snowden's revelations made it clear that SSL can be compromised by organisations such as the NSA with relative ease.

5
  • 5
    This answer provides nothing that the other answers don't, and misses the point that to a MitM, the client's hash of the password can be used as if it were the password itself.
    – Mark
    May 5, 2015 at 8:29
  • 4
    @Mark Um no Mark. This does indeed help with mitm. Mayhem is stating at hashing the hashed password yet again. Jan 28, 2016 at 22:02
  • This is a good idea I haven't thought of. Hash on the client side to hide the plain-text password, then hash on the server side to protect from a server-side breach. Thanks for sharing! Apr 15, 2016 at 23:55
  • 1
    @Karl, The 'man in the middle' would still be providing the same request parameters as the target user. Just because it isn't a password, doesn't mean the attacker can't intercept the hash and provide that same hash on to the server (to let it "hash the hash" and succeed at a match).
    – zyglobe
    Oct 26, 2016 at 3:25
  • 1
    @RedGlobe That however is true. But it does help, because a looot of internet users use the same password for everything. I agree it might not help against that particular system, but it will help on a broader scale. Oct 26, 2016 at 8:48
6

What advantages would client-sided password hashing have?

Well, the password wouldn't be sent over the net in clear-text. But you should really be using TLS encryption when you log in, so password sniffing should not be an issue.

Another reason could be that you don't want the server to ever be aware of the users password, not even for a microsecond. That means you give the server the password hash on registration and then log in using that password hash. Unfortunately this doesn't solve anything: The shared secret to log into the account is now the hash, not the password. When you obtain knowledge of the hash, you can log in without knowing the actual password (because the server doesn't know it either).

9
  • 2
    The advantage for me would be that I can use the user's password to encrypt some local data in my app, and proof that the server is never able to decrypt that data (since it only knows the hash). Otherwise I would have two prompt the end-user for two different passwords (1 for login, 1 for encryption).
    – Maestro
    Mar 18, 2014 at 13:41
  • @Muis In that case the answer would be "Because nobody has such exotic requirements like you do".
    – Philipp
    Mar 18, 2014 at 13:54
  • 10
    @Muis That's not how salting works. Salts only protect against precomputed rainbow tables, not against dictionary attacks.
    – Philipp
    Mar 18, 2014 at 16:01
  • 2
    @Philipp, salt does guard against dictionary attacks where the attacker just wants one out of many captured hashes. It does not help against dictionary attacks on a single hash.
    – mikeazo
    Mar 18, 2014 at 16:53
  • 1
    @muis in that case use a private symmetric key that is password protected. This will generally provide far better security for the encrypted data due to the higher entropy of the symmetric key while also ensuring that the server does not have the ability to decrypt (as it does not have the private key). Don't roll your own... use established and known secure patterns. Aug 28, 2016 at 11:12
3

Since you are talking about web application...

In a database we have a table call dbo.useracc we are storing these hashes password

User        Password
--------       ----------
user1       5f4dcc3b5aa765d61d8327deb882cf99
user2       202cb962ac59075b964b07152d234b70
user3       098f6bcd4621d373cade4e832627b4f6

and our login function in web application be something like

if (user == $user and password == $pass) {
           return auth.token
}

Let's say an attacker successfully hacked and stole the database and saved our dbo.useracc data. He now has our hashed password.

If your login hashes process is stored in the client, the attacker can still accesses your account with the hashed password by just hooking up the HTTP POST method altering the password field to send your hashed password and he is still able to login. Remember your application data are communicating with the server through the POST method eventually after it's hashed to be checked against.

However if the hashing process is in the server, it's another story.

$pass = md5.hash($pass);

if (user == $user and password == $pass) {
           return auth.token;
}

If the hacker use the hashed password to login, it will be a hash 'hashed password' checking against a hashed password.

In this case let's say the attacker post

$user = user1 $pass = 5f4dcc3b5aa765d61d8327deb882cf99

After the server side doing $pass = md5.hash(5f4dcc3b5aa765d61d8327deb882cf99) it will return '696d29e0940a4957748fe3fc9efd22a3' which is returning a false statement.

This is to fence off attacker who has successfully stolen the database data and trying to access through the web application using the hashed password. And of course the attacker still can hack into the accounts if they successfully bruteforce / crack the hashes through dictionary attacks and so. However the hacker requires longer time if the password is a good password after compromising the system and the server admin could just reset the password and email the users.

Also it is also used to internal threats like employees in an enterprise. In an enterprise, there will be Database Administrator and Developers. They are different roles. Now to prevent the employee users to access to the sensitive data, they need to have access to both application and DB to get access to the data. Of course you might argue a DBA can still alter the database data through the database itself, but it is not accessible by the developers and it is easier to pinpoint where is the attack from. It is about access control rights and minimizing the risks and threats.

2
  • 1
    You're correct that it doesnt make it harder for an attacker to enter MY site using the stolen hash, but it makes it harder to login to ANOTHER site, since the other site most likely dont use exactly the same salt + hashing algorithm.
    – Maestro
    Mar 18, 2014 at 14:04
  • There's no way the attacker can access ANOTHER site with the hashed password too as long as the ANOTHER website don't practice hashing in the client and is a good password that is hard to be bruteforce by dictionary or rainbow table attacks. And as a developer, why would you even care about "ANOTHER" site in the first place. If the users value their other data a lot, they should practice not to use a global password instead.
    – Sky
    Mar 18, 2014 at 14:11
3

Though the topic has some concrete leak points, as pointed out by @Cyker, the discussion is a little brisk here ... I'd like to add one point that I didn't see mentioned.

It's simply that if you hash ASAP, then you reduce the programming risks of accidentally passing a clear text password somewhere that it shouldn't go. We already take measures like secure strings and secure arrays to try to destroy the clear text ASAP; and hashing at the moment that you get the password is another measure like that ... As code evolves, etc. the risks seem to still be reduced.

I just wrote a little C# "Box" that takes the SecureString clear text and hashes it immediately --- this way I simply know that it will never be logged or passed to a library I don't expect. This is not so much about a protocol as it is just the programmer here sitting and looking at a password --- I don't wan't to touch it! (It's still a password equivalent in some aspects, but it is at least immediately concealed from folly like moving a closing parenthesis in a chained method call and passing clear text to the wrong place. And a secure array is still not concealed.)

2

I agree that if SSL/TLS is available the advantage of client-side hashing to protect the authentication process is limited. However, SSL / TLS does not resolve the vulnerability to custom hardware attacks if the attacker has access to the stored hashes (AFTER the process). Functions such as simple salted hashes or schemes like PBKDF2 are very vulnerable to these attacks because of their low memory requirements. The cracking of passwords, protected with theses schemes is cheap and fast. And that is at least one of the main problems of password hashing.

At first glance, this has nothing to do with client-side hashing versus SSL/TLS - but: When a sever implements a memory-hard password hashing scheme such as Scrypt, Argon2 or Catena to protect custom hardware attacks, the server‘s hardware requirements increase dramatically. In reality, services therefore reduce the memory-hardness or switch to vulnerable schemes. Client-side hashing helps a bit to get around this problem. When the clients compute these expensive (memory hard) functions, the service can use them without the need for better hardware.

Modern password hashing schemes therefore offer the possibility to delegate the most expensive (memory-hard) parts of the function to the client. This feature is called server relief and is offered by Argon2 and Catena.

Conclusion: Using modern password hashing schemes, which are much less vulnerable to custom hardware attacks, will increase or at least should increase the use of client-side hashing in the future – of course along with SSL/TLS.

2

Most websites send the password as plain, or base-64 encoding (basic auth), and rely on the TLS layer for hiding the password. This is common practice, and is as safe as the TLS layer is really secured.

But TLS is not perfect either. In practice, most corporations include an Interception Proxy in their security chain. They added their own root CA to the corporate client devices, and actually intercept outgoing TLS requests, for security or regulatory reasons (e.g. log, monitoring). So the password is plain not only on the client and server side, but also at the interception proxy level.

We should therefore not rely on TLS for truly hiding sensitive information. Client side hashing seems mandatory if you expect a truly secure use of your secret password.

In addition to plain password hash, you may consider for additional security, and to avoid replay attacks:

  • To include a server-side challenge: server sends random A, client hashes A + password and sends this value;
  • To include server-side and client-side challenges: server sends random A, client computes random B, client hashes A + B + password and sends both B + hash;
  • To include a client-side puzzle (blockchain-like proof): server sends random A, client loops computing some random B and hashing A + B + password until the hash starts with n zeros (the bigger the more computer intensive), client sends B and it is easy and cheap for the server to verify B.

Proven protocols always include client-side and server-side challenges, to avoid replay attacks. Hashing and challenging is uncommon on WebSites because:

  • Client-side hashing is slow if done in plain JavaScript, so the most sophisticated proven means like client-side puzzle may be quite resource consuming - even JITted hash computation is far behind optimized OpenSSL library code for instance.
  • It is not trivial to implement a proper authentication protocol, so most developers rely on the well-known TLS layer for the security. Reinventing the wheel is not a good idea in a security context.
  • Security Auditors don't like custom protocols. They prefer to have a known TLS, and check the WebServer settings, e.g. the TLS versions and enabled ciphers list. It is easy to verify, even if not fully secure.

On a corporate level, you may consider using a proven authentication algorithm like Kerberos/Negotiate, and a domain controller, then you will have a known client-side hashing with server-side and client-side challenge, and other benefits like single sign-on, and - most of all - centralized user management for authentication (even if authorization could be delegated at the web application level).

Security Auditors would easily recognize and validate it, and your manager would like the fact that the development cost is low, if the server is part of the domain controller. You may consider securing your most valuable resources using this authentication, and only allowing basic authentication for the main/insensitive parts of your website.

1

I'm going to jump in here with the express purpose of weighing in favor of the client-side hashing mechanism. Let's see how this benefits us:

Client-side: No improvement.

In transit: Protects the password in case of SSLstrip in which the password ends up being transmitted in cleartext. However, if HSTS is implemented, then most people would say that SSLStrip would have no effect. Right? No.

On entry to the server: Finally, we see the major benefit. What happens if someone has compromised the server? They get a continuous flow of cleartext passwords if they just boot up Wireshark/TCPDump and export the server's private key. Now they can sit on the wire for a couple of months, and for high-volume servers (millions of user registrations per month), they get their massive plaintext breach. This is assuming that it is more valuable to grab the passwords for the people on the service than to have RCE on their server, of course.

On the server: Performance benefits if it doesn't have to run bcrypt on every incoming password, which offloads some computational cost onto the client without introducing any new vulnerabilities. This seems to be a good thing for your server's administrator as well as your hardware costs.

Still, it looks like best practice would be to incorporate password hashing into the client side unless it creates unbearable page load times for the users.

2
  • I am curious to hear why someone downvoted this answer. SSLStrip is a little dated, but not wrong, and the rest of the answer sounds accurate to me.
    – Luc
    Jan 9, 2019 at 23:33
  • I certainly don't know. Re-reading my commentary from several years ago, I can't see any obvious flaws in my reasoning.
    – DeepS1X
    Mar 13, 2019 at 6:03
0

I think client-side hash has one upside and one drawback:

pro : You hide the password in case of dns/phishing/whatever, which is useful for the user, since most people reuse passwords on several service. As other devs said, this does nothing for your own security.

cons : Your server does not get the password, which prevents stuff like warning the user about password strength. I know some will say this can/should be client-side, but when you have multiple clients, this can be nice to centralize server-side.

1
  • 1
    (I did not downvote, would be nice if people could explain downvotes.) Password advice should really be done client-side. I would recommend a library like zxcvbn which is available in many different languages and seems very goal-oriented and well-designed. That would also limit having to incorporate the advice in all clients' code separately.
    – Luc
    Jan 9, 2019 at 23:34
-5

i think the probability of being hacked in client-side is more higher than that in server-side. (Because there are some IT expert look after the server) . if your computer is already being hacked. the client-side 's algorithms which used for hashing your password also can be stolen by hacker . Aso soon as your algorithms is no longer a secret. i think,it become useless.

4
  • 4
    We generally frown on secret algorithm (See Kerckhoffs's principle and security-through-obscurity. Password hashing certainly doesn't need to rely on this. At most we apply a key and hope that the attacker doesn't find even if they manage to steal the database. Mar 18, 2014 at 11:03
  • 1
    The "server is more secure" argument makes little sense in this context. 1) The client knows the plaintext password, so a trojan can trivially steal it with a key-logger. 2) Password hashing only offers an advantage over plaintext passwords when the server gets hacked and the database gets stolen. Mar 18, 2014 at 11:05
  • 4
    The way twitter works is that you follow people whose tweets you find interesting. No need to ask for permission. Mar 18, 2014 at 11:20
  • 1
    A server with all its user data is a way more valuable target than one single user.
    – Gumbo
    Mar 18, 2014 at 14:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.