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.

Edit: Updated to put more emphasis on the goal - peace of mind for the user, and not beefing up the security.

After reading through a few discussions here about client side hashing of passwords, I'm still wondering whether it might be OK to use it in a particular situation.

Specifically I would like to have the client - a Java program - hash their password using something like PBKDF2, using as salt a combination of their email address and a constant application-specific chunk of bytes. The idea being that the hash is reproducible for authentication, yet hopefully not vulnerable to reverse-engineering attacks (to discover the literal password) other than brute force if the server data is compromised.

Goal:

The client side hashing is for the peace of mind for the user that their literal password is never being received by the server, even if there is the assurance of hashing it in storage anyway. Another side benefit (or maybe a liability?) is that the hashing cost of an iterated PBKDF2 or similar rests with the client.

The environment characteristics are:

  1. All client-server communication is encrypted.
  2. Replayed messages are not permitted. ie. the hash sent from the client cannot effectively be used as a password by an eavesdropper.
  3. Temp-banning and blacklisting IPs is possible for multiple unsuccessful sign in attempts within a short time frame. This may be per user account, or system wide.

Concerns:

  1. "Avoid devising homebaked authentication schemes."
  2. The salt is deterministic for each user, even if the hashes produced will be specific to this application because of the (identical) extra bytes thrown into the salt. Is this bad?
  3. Authentications on the server end will happen without any significant delay, without the hashing cost. Does this increase vulnerability to distributed brute force authentication attack?
  4. Rogue clients can supply a weak hash for their own accounts. Actually, not too worried about this.
  5. Should the server rehash the client hashes before storing?

Thoughts?

share|improve this question
3  
I think I'm a bit confused about the threat model. What is the threat against which this defends. Is the password stored on the server? If not, then the token passed from the client to the server is the password. If it isn't, then how do you prevent replay attacks. I see things I like in here, but I can't evaluate the scheme without understanding the threat model. –  Mark C. Wallace Oct 23 '12 at 10:33
1  
Sorry I really should have emphasised the third.. now fourth paragraph more, which outlines the goal of this versus a more conventional scheme: peace of mind for the user in the server not receiving their literal password. The server not having to perform an expensive PBKDF2 hash performed over n iterations is a bonus (although as a poster has pointed out it could also add defence against DOS). However I'm not trying to cater for a specific threat model other than the usual. –  Foy Stip Oct 23 '12 at 23:24
add comment

6 Answers

up vote 15 down vote accepted

Hashing on the client side doesn't solve the main problem password hashing is intended to solve - what happens if an attacker gains access to the hashed passwords database. Since the (hashed) passwords sent by the clients are stored as-is in the database, such an attacker can impersonate all users by sending the server the hashed passwords from the database as-is.

On the other hand, hashing on the client side is nice in that it ensures the user that the server has no knowledge of the password - which is useful if the user uses the same password for multiple services (as most users do).

A possible solution for this is hashing both on the client side and on the server side. You can still offload the heavy PBKDF2 operation to the client and do a single hash operation (on the client side PBKDF2 hashed password) on the server side. The PBKDF2 in the client will prevent dictionary attacks and the single hash operation on the server side will prevent using the hashed passwords from a stolen database as is.

share|improve this answer
    
You're right, there's the compelling reason to re-hash on the server: if an attacker gets a copy of the database without necessarily having write access, if I understand you correctly. Based on other's responses so far I'm still wary of the viability of this whole scheme but for the moment it seems like the combo of a heavy hash on the client and a final re-hash on the server is sounding promising. Thanks for the response. –  Foy Stip Oct 23 '12 at 23:25
add comment

There are few time when client-side hashing is worthwhile. One such circumstance is when the hash process is computationally intensive, which can be the case with PBKDF2.

Addressing your concerns:

  1. Also avoid unvalidated suggestions about cryptography you find on the internet. (Disclaimer: I am not Bruce Schneier.)
  2. Deterministic salts aren't a problem--the only real requirement of the salt is that it is unique for each user. The salt's real purpose is to prevent a brute force on one password from turning into a brute force on all passwords in the case of a compromised database. Even if you were to store a random salt in your database right beside the hashed password you would still reach this goal, provided each users' is different.
  3. As I mentioned above, PBKDF2 is nice because you can arbitrarily decide the computational difficulty of the hash. You could select a c such that a single hash on modern hardware takes seconds--effectively eliminating risk of an API level brute force attack. (Of course, your client's might not enjoy such a long delay at login.)
  4. An users can choose simple passwords--they are only hurting themselves. If you wanted eliminate this risk, you would have the server generate the hash the first time, provided ithe password is going over an encrypted channel.
  5. Yes, and you will need to uniquely salt these as well. In the event of a database compromise, you want to ensure that the attacker doesn't get information that allows him/her to directly authenticate as any user on your system. One caveat here is that you do not want your server-side hashing to be computationally intensive the way your client-side hash is. If your server-side hash takes too much effort, you open yourself to a CPU-exhausting Denial of Service attack vector--an attacker simply spams empty password authentication attempts over Tor, passwords which your server has to try hashing before it knows they are fraudulent, eventually leaving you with an overwhelmed server..
share|improve this answer
4  
+ 1 for my new disclaimer (IANBS) –  Mark C. Wallace Oct 23 '12 at 14:57
    
Thanks for the input on all of those points. Re: point 2, yes this was/is my understanding.. that it would be OK, as long as the salts are always different. For this scheme the salt will be different for different emails, and also different for the same emails across different applications/databases. –  Foy Stip Oct 23 '12 at 23:30
    
Yes as you and others have pointed out, re-hashing on the server will definitely be necessary, though it will be done more cheaply as you say. Hmm.. Tor requests from the same user or from different machines behind the same NAT router will appear to originate from different IPs, won't they? –  Foy Stip Oct 23 '12 at 23:30
    
Yes, there are simple tools out there that allow multiple requests from a single machine to be routed through multiple Tor exit nodes. –  Motoma Oct 25 '12 at 10:52
add comment

If you hash the password on the client side, whatever the result is IS the password, so you're not gaining any real security. Any hack or information leak that would have revealed the plaintext password will instead reveal the hashed password, which is the real password.

This shouldn't be confused with zero-knowlege authentiction schemes, where an exchange of messages proves that the client knows the real password, without actually transmitting it.

share|improve this answer
    
If you mean the case of the server's DB being compromised, as David Wachtfogel pointed out, then yes you're right that the hash could just be retransmitted as a password. It needs to be re-hashed on the server. The gain is not beefed up security, but peace of mind for the user in the server not receiving a literal password. If on the other hand you mean man-in-the-middle attacks then the underlying encryption scheme protects against replay of anything, be it literal or hashed passwords. –  Foy Stip Oct 23 '12 at 23:27
add comment

A Google employee is working on something similar called TLS-OBC. This RFC draft allows the client to hash the password and bind it to a TLS session.

Specifically you may be interested in this website http://www.browserauth.net/origin-bound-certificates

and this link on Strong User Authentication http://www.browserauth.net/strong-user-authentication

share|improve this answer
    
Thanks for the links, it looks interesting. Can you provide a link to some info about the client-side password hashing aspect of it? –  Foy Stip Oct 23 '12 at 23:31
add comment

It seems like you're trying to invent your own cryptographic protocol. From the description of your approach, it does not seem like you have the background to do this in a secure manner. I highly recommend using existing protocols instead of creating your own.

First, it's not clear what threat model you think you're circumventing. You cite something called a "reverse-engineering attack" which has no real definition or meaning.

Second, your understanding of a salt's purpose and best practices for its generation appear to be lacking. Salts are not required to be kept secret. You can (and should) generate a unique salt from a CSPRNG for each new authentication token, and not from something like an email address (which might change). Fixed application-specific salts are sometimes called "peppers", and I am unaware of any cryptographic literature which supports or encourages their use.

Third, PBKDF2 is okay, but seriously just use BCrypt. BCrypt was designed for this and is in widespread use. Good BCrypt implementations will handle salt generation and work factor calibration / autodetection for you. You will have to implement these things yourself to use PBKDF2, and you will almost inevitably make mistakes.

Fourth, there is an existing approach to what you appear to be trying to do. Zero-knowledge authentication can be performed with SRP. The user's password is never transmitted over the wire, and a man in the middle cannot sniff anything useful with which to authenticate themselves. However, it is apparently difficult to implement correctly and there are not many existing libraries to do so, which should give you an indication of how difficult the problem actually is.

Long story short: Don't invent your own crypto. Use solutions and protocols that are widely implemented and have withstood the test of time.

share|improve this answer
    
Yes I'm very wary of doing things outside of established protocols but if a client side hash of the password (versus sending it in literal form, albeit still encrypted and nonced) is a no-no I'd like help to understand why it's bad. I've edited the question to put more emphasis on the goal: peace of mind for the user in not having their literal password received by the server. –  Foy Stip Oct 23 '12 at 23:31
    
In the case of a changed email, the user would have to supply their password at that time so that it could be re-hashed but otherwise that should be fine. The salt will be different for different emails, and different from that used in other applications because of the fixed extra salt thrown in (specific to this app) for each hash. Also, BCrypt is definitely a possibility that I will consider. Thanks for your thoughts. –  Foy Stip Oct 23 '12 at 23:32
    
The very first reason it's a no-no is that you will get it wrong. I don't mean any offense by this, but there are simply too many places to make a critical mistake for you to have any reasonable expectation of success. Whatever security might be gained from not sending the password over the wire will be obliterated the second you compare the digest to the stored value using the database, or your language's built-in string comparison function. Or when you make a mistake on one of a dozen other operations. –  Stephen Touset Oct 24 '12 at 0:08
1  
Another reason is that having read access to the database is now enough for an attacker to impersonate any user. Security is about defense in depth — layering security so that an attacker exploiting a failure in one level of security is still stymied by deeper layers. Converting a large security failure into an absolutely critical one is the exact opposite of that goal. –  Stephen Touset Oct 24 '12 at 0:21
1  
They are, according to Stanford researchers. The correct solution is to use a constant-time comparison algorithm. Lockouts after failed attempts also help mitigate the issue, but it's best to simply fix the root problem — policy about lockouts might change in the future. The point wasn't about the one attack, though, but that this stuff is hard, and there are an uncountable number of ways to mess it up. Work with high-level constructs (e.g., "authenticate user") instead of low-level ones ("AES" or "PBKDF2") whenever possible. –  Stephen Touset Oct 24 '12 at 21:38
show 8 more comments

Hashing on the client can be a good idea in some circumstances and for some reasons, but I would not make "user's peace of mind" one of them. I am all for users to be in an harmonious frame of mind and at one with the Universe, but I find dubious the idea of promoting a way to induce users to reuse the same password on several sites.

A good case for client-side hashing is the way some "password safes" work: they compute a site-specific password by hashing the user's "master password" together with the site name. This gives most of the usability of always using the same password everywhere, while not actually giving your master password to dozens of distinct site. But this works only as long as the password derivation algorithm is generic and not changing; this seems to be much better addressed by a Web browser extension than by an applet coming from the sites themselves (all the sites would have to cooperate so as to use applets which use the same password derivation algorithm, with site-specific data).

Another good case for client-side password hashing is when a slow hash is used (so as to make password cracking harder for an attacker who could grab a copy of the database of hashed passwords); it is tempting to try to offload the cost into the client, since, when the client wants to connect, it is mostly idle and actively interested in connecting. However, slow hashing is an arms race between attacker and defender. Using Java will induce a slowdown (by a typical factor of 3), and some client systems can be quite feeble (e.g. cheap smartphones or ten-years-old computers). This is like picking up a sword instead of an assault rifle before entering a battle where the opponent will bring a tank).

But if what you want, as a user, is to protect your password against sloppy storage procedures by a site, then the right way to do it is to choose a different password for each site. (Personally, I keep a file of passwords, and all my passwords are generated randomly.)

share|improve this answer
    
Thanks for taking the time to share your expert insights (I've read a lot of your other posts) on this question, and sorry for taking so long to respond - I don't hop on here very often. After weighing up the considerations I did end up implementing the client-side hashing, as much giving in to the temptation to offload the cost of a slow hash to the client (as you say) as having the server avoid handling raw passwords. As I wondered in the OP though and also as someone pointed out, a server-side rehash is necessary anyway, albeit a more lightweight one than PBKDF2. –  Foy Stip Jul 24 '13 at 6:27
add comment

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.