2

In most protocols I have encountered in which a passphrase is used for authentication it is stored not in plaintext, but a PBKDF digest of it instead. This is obviously good.

However what does not seem to be standard practice is to compute this PBKDF digest on the client-side while registering/updating a passphrase. Instead, it is often sent to the server and then the user is left to only hope they handle it properly.

Why is this so? Am I missing something?


EDIT: Because this was unclear to some, I don't mean to suggest the server-side should not hash. The server should. I'm asking why it's common practice to not hash client-side at all.

1

4 Answers 4

4

I think the main issue are the client side languages (normally JavaScript), they are relatively slow. This would often lead to fewer hashing rounds and therefore weakens security.

If your client side language is fast enough, you could calculate the expensive PBKDF client side, then calculate a cheap hash on server side (SHA512 for example). To get the plaintext passwords an attacker still had to calculate the slow PBKDF. It is also not possible to use the PBKDF directly as password, because only the hash of the PBKDF is stored (the output of a PBKDF2 can be seen as a very strong "password", so it is safe to use a cheap hash function).

One downside is, that the handling will become more complex, you need to send salt and cost factor to the client for verification of the entered password. Another problem is to ensure integrity of the client side code, if somebody could alter the delivered JavaScript code, he could return a known string and you would store the now unsafe PBKDF.

6
  • 1
    Why was this downvoted? This seems like a perfectly reasonable answer.
    – Levi
    Commented Mar 21, 2014 at 16:32
  • 2
    Follow-up: I see some other discussion that it's easy to reverse-engineer hashes, and that's why PBKDF2 is used in the first place. This is not correct: hashes are assumed to be difficult to reverse (see "preimage resistance"), so attackers are required to fall back to rainbow tables or brute-forcing the input. Since rainbow tables don't work for high-entropy input (such as the result of a PBKDF2 operation), the attacker must brute-force the hash input, which is equivalent in cost to brute-forcing the PBKDF2 result.
    – Levi
    Commented Mar 21, 2014 at 16:54
  • It's not that hashes are bad, it's just that PBKDF is better. Well, tbh un-salted hashes are bad, as is evident from some recent breaches, so at least use salt.
    – xkcd
    Commented Mar 21, 2014 at 17:29
  • @xkcd - What Levi tried to explain is, that it is absolutely safe to store an unsalted non interated hash, if the "password" is strong enough. Salting and key-stretching is necessary, because people choose relatively weak passwords, which they can remenber. The output of a PBKDF2 on the other side is a very strong "password", and can be hashed with a hash algorithm like SHA512 even without a salt. Commented Mar 21, 2014 at 21:12
  • @martinstoeckli - Thanks for the clarification. Yes, he is right then of course, but confusing terminology ... I didn't get password = input :)
    – xkcd
    Commented Mar 21, 2014 at 22:18
0

Look at it from two extremes:-

  1. Server is using PBKDF properly

    If the server is doing PBKDF properly, it would be a useless duplication of effort and resources if you do the same thing on the client-side too. You will have to implement or use a client-side software that will run PBKDF on your password and then send that to the server, and the server will then run PBKDF on the out-put of the client-side PBKDF and store that in its database. I hope you can see the use of the additional resources without any additional benefit.

  2. Server is not using PBKDF at all

    So if the server is storing passwords in plaintext, the output of your client-side PBKDF will be stored as it is on the server. So when an attacker steals the server database, it won't make a difference if your password was PBKDFed on the client-side, to the server (and the attacker) it will be exactly same as a plaintext password like hunter1 :)

So to answer your why, the general principal is that its the entity that is controling the resource that is responsible for its security, which in this case is access control. Or as a saying in my mother language, "the thirsty man has to go to the well, the well doesn't come to the thirsty" :)

11
  • I disagree with scenario 2. If your database gets leaked and all passphrases were processed client-side, then the attacker will only get digests, and never gets to see the actual passphrases. This is very important as passphrases are often re-used between websites, or contain personal information.
    – orlp
    Commented Mar 21, 2014 at 14:35
  • 1
    They do not know the password for your other sites, but they can no gain your authorizations on that site since they can just replay back the value they now have. E.g., they compromised the db, but not the app, now they can just use the app as a normal user.
    – Eric G
    Commented Mar 21, 2014 at 14:49
  • @nightcracker To better understand scenario 2, think that when you created your account on the server, lets say via a web form, did you write your password in the form or its PBKDF digest? If you wrote your password, the server stored your password in plaintext. If you wrote the digest, the server stored that in plaintext (plaintext meaning without any change). Whether it was the password or the digest, the server checks only that to allow access. So it doesn't matter whatever you do on the client-side, the server (and attacker) are only interested in what is there in the server database.
    – xkcd
    Commented Mar 21, 2014 at 15:57
  • @xkcd - If you had calculated a server side hash, then even with the hash-values (from SQL-injection for example) you could not login. If you store the client side hash directly, you can login as soon as you know the stored hash-values. Commented Mar 21, 2014 at 16:06
  • @martinstoeckli - You are right, as long as the attacker doesn't know other parameters like salt, PRF and c etc. used on the server side. But I didn't cover this scenario in my post, I was just giving the two extreme cases on the opposite side of the spectrum to show why this is not done.
    – xkcd
    Commented Mar 21, 2014 at 16:17
0

I realized that this was brought up long ago, but here's my take anyways. If KDF processing is done on server side, then the sysadmin of the server is to be considered within the adversary model, as he/she could manage to somehow sniff process memory and learn clear text user passwords. In my eyes, this scenario (malicious sysadmin after some sort of impersonation attack) might be more common/feasible than the one when the attacker grabs a copy of the authentication database of KDF processed credentials. Just my two cents.

1
  • OTOH if the sysadmin is competent enough to do that he should have no problem just changing the javascript that gets sent to the browser. The case for client-side KDF is a bit stronger for native applications, but you still have to trust the developer. Commented May 14, 2019 at 18:32
-1

A bit of background first:

The reason why passwords are not stored as plain text usually is to provide defence in depth. That is, in the case of a database compromise (which is something that should obviously be prevented), it should prevent the attacker from gaining access to the original user passwords. This usually makes gaining access to the PBKDF2 secured passwords less valuable to the attacker. Of course, this only holds true when the passwords are strong themselves.


To answer your question:

If the PBKDF2 were computed on the client-side, then once the attacker gains access to the database, the attacker can make use of the PBKDF2 output (stored in the database) to login as the victim users through the web interface. That is, the attacker does not need to gain access to the original password to login. The attacker can simply send the username and PBKDF2 value of the unknown password to the server and get logged in just like a legitimate user. The only difference is that the legitimate user makes use of JavaScript or some other client-side mechanism to compute the PBKDF2 value while the attacker would have it in the database.

As a result, the original premise of making gaining access to the hashed passwords less valuable does not hold any more since access to that information does have value (gives the attacker access to the victim users account). It has less value to the attacker than gaining access to the original password (before performing the PBKDF2 operation) but has more value than if it were encrypted on the server-side.

There are other problems with client-side PBKDF2 that I think should be mentioned:

  • a static salt would have to be used (i.e. it cannot be random as it would produce a different PBKDF2 value)
  • other values passed to the client-side PBKDF2 client-side function would also need to be static, thus removing a number of security features (such as changing the number of iterations)
  • just like in the case of server-side PBKDF2, the original password can be retrieved by injecting JavaScript code to read keystokes or input values in the case of a web application compromise (e.g. XSS and various other vectors); so that the potential security gains of client-side PBKDF2 there are lost
2
  • "If the PBKDF2 were computed on the client-side, then once the attacker gains access to the database, the attacker can make use of the PBKDF2 output (stored in the database) to login as the victim users through the web interface." I'm sorry, but this assumes that you do not hash on the server side AS WELL. OF COURSE you hash on the server side. And all your other concerns are invalid too, the server could send the required parameters for the PBKDF. And suggesting Javascript injection attacks is just irrelevant to the entire question.
    – orlp
    Commented Mar 21, 2014 at 18:07
  • Thanks for updating your question to make this clear. Without that last edit, it was not as obvious as you assume it is. Commented Mar 21, 2014 at 19:00

You must log in to answer this question.

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