Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

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.

share|improve this question
    
This post is relevant: lists.webappsec.org/pipermail/websecurity_lists.webappsec.org/… –  paj28 Mar 23 at 11:04

3 Answers 3

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.

share|improve this answer
    
Why was this downvoted? This seems like a perfectly reasonable answer. –  Levi Mar 21 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 Mar 21 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 Mar 21 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. –  martinstoeckli Mar 21 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 Mar 21 at 22:18

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" :)

share|improve this answer
    
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. –  nightcracker Mar 21 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 Mar 21 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 Mar 21 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. –  martinstoeckli Mar 21 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 Mar 21 at 16:17

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
share|improve this answer
    
"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. –  nightcracker Mar 21 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. –  Sandro Gauci Mar 21 at 19:00

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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