1

Users log in to my BlackBerry app with a username and password provided at registration. My app connects to a Java Web Service that does all the logic.

  • How do I go about storing the password and username in a safe manner on my server? Everybody says salting and hashing, but I have no idea how to do this since I've never worked with it. How can I do this in Java?

  • How do I manage sending the password securely from the app to the server?

Michael Donohue
  • 11,776
  • 5
  • 31
  • 44
8vius
  • 5,786
  • 14
  • 74
  • 136

3 Answers3

2

To store the credentials, one possibility is to use PBKDF2. A Java implementation (that I have not used) is available here. Run the password with the salt value through that and store the resulting hash data. The salt value is typically a newly generated random value (one for each password). This helps prevent dictionary attacks via rainbow tables (pre-computed tables of hashed passwords). Using java.security.SecureRandom is a possibility for generating those.

The client application should probably connect to the server using SSL/TLS. That will provide the encryption to protect the credentials when passed from client to your server application.

Edit Based on our conversation in the comments, it sounds as if the goal is not to use SSL. Assuming that is true and no other end-to-end communications encryption is planned, then it seems to imply that the security of the communications is not a high priority. If that is true, then maybe the described scheme for authenticating is sufficient for the application. Nonetheless, it seems worth pointing out the potential issues so you can consider them.

  • The proposed scheme (I think) is to send from the client to the server this value: Hash(Hash(password,origsalt),randomsalt). What this really means is that the password is effectively Hash(password,origsalt). If the attacker can get that information, then they can login as that user because they take that value and hash it with the new salt value to authenticate. In other words, if the database of hashed passwords is compromised, then the attacker can easily gain access. That somewhat defeats the purpose of salting and hashing the passwords in the first place.
  • Without SSL (or some other end-to-end encryption), there is the possibility of a man-in-the-middle attack. They can either listen in or even impersonate one end of the conversation.
Mark Wilkins
  • 40,729
  • 5
  • 57
  • 110
  • How would you go about generating the salts? And also the SSL/TLS is a good suggestion, but in no moment (other than registration) will the password go from client to server. I was planning on doing the following to keep the credentials secure: 1) User registers salt is created, appended to password and hashed. Password is discarded, salt is saved as well. 2) When logging the user sends his username, with this the salt is retrieved and a second random discardable salt is made and sent to the client. On the client the pass and original salt is appended, hashed and converted (continues) – 8vius Feb 11 '11 at 16:03
  • to string, which is then appended the randomly generated second salt, and hashed again and sent to the server, which will do the same process and compare. That way I only send the salt and username over the net – 8vius Feb 11 '11 at 16:04
  • That sounds as if it does allow the server to verify the credentials and does succeed in avoiding sending the password. Depending on the security level you are aiming for, that might be sufficient. One potential drawback, though, is that it would allow an attacker to "easily" grab the necessary information to discover the password (via brute force) in his own time. The attacker could get both salt values and the final hash from those and the password. If you use a large number of PBKDF2 iterations, the attack would be expensive ... but it is a potential opening. – Mark Wilkins Feb 11 '11 at 16:14
  • Yes he can know the salt, username, response and second salt, but since the second salt is random and discarded after verification it's quite harder for him to gain access by knowing this. – 8vius Feb 11 '11 at 16:38
  • @8vius: It is harder, but the attacker only needs one set of those values and can then work completely independently to test passwords using those two salt values (and known resulting hash). And, incidentally, it opens up a second attack. If the hash value you are storing is shorter than the password itself, then all that really needs to be tested is hash values since the authentication is purely the result of Hash(originalhash,newsalt). So really all the attacker needs to break in is the stored hash values (the password is no longer relevant). – Mark Wilkins Feb 11 '11 at 16:56
  • A KDF is a function which transform a piece of secret data (here, a "password", i.e. the kind of data which fits in a human brain and can be typed with human fingers) into a sequence of bits adequate for algorithms which need a symmetric key (e.g. symmetric encryption). A KDF is not meant for anything else, in particular password storage. More info here: http://security.stackexchange.com/questions/2051/is-pbkdf1-based-system-cryptology-passwordderivebytes-better-than-a-typical-h/2056#2056 – makerofthings7 Feb 11 '11 at 18:59
  • Also another thing I forgot to take into account while discussing, whatever cryptography is done on the client side has to very light weight, we are talking about a BB device here. And @Mark your concern is valid about the comms security i'll look into that, what i don't see is the flaw in the exchange i'm proposing the attacker would have to de-hash that information in order for it to be useful to him, and in that case I would say pretty much everything is vulnerable. And the attacker would have to de-hash Hash(Hash(pass,salt),randomsalt) that's a lot of work. What would yo propose? – 8vius Feb 11 '11 at 19:16
  • And @makerofthings7 if not the KDF lib that @Mark gave, how would I go about doing this in Java? both client and server – 8vius Feb 11 '11 at 19:18
  • I'm probably not explaining my concern very well. The attacker has available salt and randomsalt. If they guess the password (a universal problem), they can get in. However, if they guess `hash(pass,salt)` (or steal it from the server presumably hard), they can also get in. For the sake of the argument, assume that only 4 bytes of the hashes are stored for the password. hash(pass,salt)=0x12345678. Since the attacker has randomsalt, they only have to guess 0x12345678 (via brute force) to produce hash(hash(pass,salt),randomsalt). – Mark Wilkins Feb 11 '11 at 19:34
  • I see, but that's the thing randomsalt is a one time use thing, used only for one transaction, the next time the attacker would want to use what he knows already he'd still need that to generate the response. Still, all systems have some sort of vulnerability, nothing is impervious. Right now I'm realizing a flaw in all this and not because of the method, like I said before, it's a BB device and what we're discussing here is pretty heavy processing as far as I can see, the device won't be able to do it I believe. – 8vius Feb 11 '11 at 20:04
  • Maybe I'm missing something, but the fact that the randomsalt is a one-time value doesn't matter. If the attacker can find out hash(pass,salt) from a previous session, then that value does not change. If that value is X, then he can connect because he can still compute hash(X,randomsalt) where randomsalt is the new salt value that the server sent. In any case, I found it to be an interesting question. +1 – Mark Wilkins Feb 11 '11 at 20:12
  • Thanks for the help @Mark, I might have to simplify my approach and just do this process server side without the extra salt since it won't be necessary, and focus on the secure connection. I found some apache commons lib that I can use to salt and hash org.apache.commons.codec and org.apache.commons.lang have classes that can be used for this i'll post the solution but i'll mark your answer as the solution – 8vius Feb 11 '11 at 20:53
  • @8vius, please note this answer is wrong. While there is some good information here, PBKDF is *not* intended for use to store passwords. Take a look at some of the information here: http://security.stackexchange.com/q/2051/33 – AviD Feb 13 '11 at 09:24
  • @AviD: Please read [RFC 2898](http://www.ietf.org/rfc/rfc2898.txt). It is the RFC for PBKDF2. A direct quote: "Another application is password checking, where the output of the key derivation function is stored (along with the salt and iteration count) for the purposes of subsequent verification of a password." – Mark Wilkins Feb 13 '11 at 12:37
  • @AviD: I've thought about this more and am a bit puzzled. What mechanism do you recommend for storing authentication data? In [this post](http://security.stackexchange.com/questions/211/password-hashing), you ask that basic question question and the top voted answer (and the one you selected as the actual answer) describes exactly what PBKDF2 does (aside from the pepper value which could be added to it). – Mark Wilkins Feb 14 '11 at 16:18
  • @Mark, what PBKDF does is generate an encryption key. That is it's purpose, and it's defintion. In http://security.stackexchange.com/q/2051/33 @Thomas Pornin (who btw, is a professional cryptographer) explains it very well. That's not to say you *can't* used it as password storage, just that you *shouldn't*. – AviD Feb 14 '11 at 19:06
  • @AviD: Thanks for the information. I have never seen any other documentation or reference that says one should NOT use PBKDF2 for password verification purposes. And since the RFC itself says it is a valid use (not to mention many other references saying it is valid), my inclination is to side with the majority in this situation. Take a look at [this post](http://stackoverflow.com/questions/2860943/suggestions-for-library-to-hash-passwords-in-java). The answer is to use PBKDF2 for password hashing. Pornin responds to it and does not disagree with the answer. – Mark Wilkins Feb 14 '11 at 19:28
  • @Mark, when it comes to subtle and esoteric details, like cryptography, the majority opinion holds no weight, and is often very wrong. Lord knows I've been there... – AviD Feb 15 '11 at 06:49
  • From @Thomas' comments on the other question: "... It is conceivably possible to make a KDF which also has security characteristics good enough for password storage (assuming you are using a proper, fixed output size) but this is not automatic. PBKDF2 has been published as a KDF and has been analyzed as such. Whether it can be subverted into a password storage mechanism remains to be proven." And anyway, there are better solutions out there, so why bother with something that is not a sure thing? – AviD Feb 15 '11 at 06:50
  • @AviD: Thanks for the interesting conversation and viewpoints. – Mark Wilkins Feb 15 '11 at 15:21
2

Seems like your question has a few parts...

The most secure way to store the password in the database is to use a hash with a Salt + Pepper seed as described here. If you want to find a good way of implementing that specific technique in Java, try opening a new question.

I can see why it would make sense to encrypt a username/password hash prior to sending to the server, since SSL proxies can be a man-in-the-middle for that operation.

As a solution try creating a token in JSON or XML format that has the following properties:

  • Username.ToUpper() // Dont want this to be case sensitive
  • ExpiryDate (Say now plus 5 minutes)
  • Nonce (a random number that is saved on the backend to prevent replay attacks)
  • SHA 256 signature

Use the locally entered username and password to create a SHA256 signature, as it will be a constant. Use this signature to sign the JSON or XML you send to the server with each request.

In other words you're using a symmetric key based on the username and password, without sending it across the wire. Of course you may want to salt and pepper the generation of that symmetric key for more security.

That's all I got for a high level design, since I'm not intimately familiar with Java. Do share your links/code when you do find the answers.

Community
  • 1
  • 1
makerofthings7
  • 60,103
  • 53
  • 215
  • 448
  • +1 Very complete answer @maker, thank you very much. But my performance problem still remains with it being a BB app, i'll have downgrade it a little in light of this and make something simpler, regretfully. – 8vius Feb 11 '11 at 22:17
0

So here's what I ended up doing:

package Utils;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.RandomStringUtils;
/**
 *
 * @author octavius
 */
public class SalterHasher {

    private String salt;
    private String pepper = "******************";
    private String hash;
    private String password;

    public SalterHasher(String password, String username)
    {
        this.password = password;
        salt = RandomStringUtils.random(40, username);
        hash = DigestUtils.md5Hex(password + salt + pepper);
    }


    public String getHash(){
        return hash;
    }
    /**
     * @return the salt
     */
    public String getSalt() {
        return salt;
    }

    public String makeHash(String salt){

        return DigestUtils.md5Hex(password + salt + pepper);
    }



}

A very simple class that generates a salt and the hash for me and has a pepper included for added security, the makeHash() function I use for verification when the user logs in. In view of what I previously mentioned in the comments above I didn't end up using the verification process I proposed and chose to simply add the pepper to my server side code since hashing I believe would prove to be heavy on the BlackBerry device. Thanks again to those who helped me. Good discussions were had :)

8vius
  • 5,786
  • 14
  • 74
  • 136