0

I'm trying to determine the best way to implement password validation in Java. The password is stored as text in an SQL database.

Should I:

  1. Query for password based on user name and validate it within Java app? (SELECT password FROM users WHERE username = 'foo')

  2. Query for row based on user name + password input? (SELECT true FROM users WHERE username='foo' and password='bar')

  3. Something else entirely...

If the answer is #1, what is the correct way to get the password hash into Java? I know that passwords should be stored as a char[] instead of a String to avoid leaving a copy in memory, but is it ok to retrieve it from the result set using ResultSet.getString("password")? Wouldn't that create a String constant and be a security risk (even if hashed)? The other option I see would be to store/convert the password to an array within SQL and then use ResultSet.getArray() to retrieve it, but that seems a little excessive unless absolutely necessary.

Edit:

Ok, maybe I made a mistake by using the word TEXT in the same post as PASSWORD, but I was referring to the data type, not saying that I'm saving the passwords in plain-text. In fact, I clearly asked "what is the correct way to get the password hash into Java". Please stick to the question that I asked if you want to be helpful.

Michael Payne
  • 534
  • 5
  • 13
  • 7
    Step 1: ***DON'T STORE PLAIN-TEXT PASSWORDS...ANYWHERE!*** Instead, store them hashed in the database. Then continue as normal. – cdeszaq Feb 07 '12 at 20:50
  • 2
    You are already violating the cardinal rule of passwords by storing them as plaintext. Why worry about storing them in memory on your server? – BNL Feb 07 '12 at 20:50
  • 4
    And salt them before hashing them. – JB Nizet Feb 07 '12 at 20:56
  • I clearly asked "what is the correct way to get the password HASH into Java". Please read before flaming. – Michael Payne Feb 08 '12 at 22:18

3 Answers3

0

Hash your passwords. Than you can compare hashes.

SELECT username FROM user WHERE username=username and password_hash=password_hash;

How can I hash a password in Java?

byte[] salt = new byte[16];
random.nextBytes(salt);
KeySpec spec = new PBEKeySpec("password".toCharArray(), salt, 2048, 160);
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] hash = f.generateSecret(spec).getEncoded();
System.out.println("salt: " + new BigInteger(1, salt).toString(16));
System.out.println("hash: " + new BigInteger(1, hash).toString(16));
Community
  • 1
  • 1
baklarz2048
  • 10,699
  • 2
  • 31
  • 37
  • The select will not work with proper salting. You need to have the same salt that was used when setting the password. – Has QUIT--Anony-Mousse Feb 07 '12 at 21:07
  • I'm already hashing and salting the passwords. Just because a password is hashed doesn't mean you'd want it sitting around in your query logs or resident in memory. I'm trying to find out which is the lesser of the two evils. – Michael Payne Feb 08 '12 at 22:34
  • Bad idea to add the password column in the WHERE clause in the SQL aswell.. RDMS are designed to return data as quickly as possible this is a open window for [timing attacks](https://en.wikipedia.org/wiki/Timing_attack) – Raymond Nijland Aug 25 '19 at 15:26
0

Both your methods are bad, since password is transmitting in plain text outside an application, probably by network. But the second method is slightly better since some transmitting passwords will be sometimes wrong.

Use some sort of hashing. Hash password then store it into database. Hash entered password too and compare hashes. Hashing is irreversible data transformation. Use MessageDigest class http://docs.oracle.com/javase/6/docs/api/java/security/MessageDigest.html to create hashes in Java. Use one your database knows.

Suzan Cioc
  • 29,281
  • 63
  • 213
  • 385
  • I didn't say I was transmitting anything in plain text. I don't think that being within the application is a reliable safety net either, since there must be some risk if the password components in Java return a char[] data type instead of String for security. – Michael Payne Feb 08 '12 at 22:37
0

Option 3: completely different.

Step 1: SELECT passwordHASH from users WHERE username=? (note the placeholder to avoid SQL injection attacks - check your API on how to use placeholders)

Step 2: extract salt from the password hash.

Step 3: use the salt to compute the hash from the plain text received from the user

Step 4: compare existing passwordHash with the newly computed passwordHash.

Seriously: read up on salted password hashes. This is the only proper way of storing passwords. And the best is, it already exists. Don't even try to reinvent this wheel, unless you are a cryptography genius (and then you should know better).

Don't leave away the hash. It prevents two users from having the same hash when they just happen to choose the same password. Plus, it largely avoids dictionary attacks such as rainbow tables.

Has QUIT--Anony-Mousse
  • 76,138
  • 12
  • 138
  • 194
  • I clearly asked "what is the correct way to get the password **hash** into Java". I know how to store it, I'm asking how to retrieve it securely... – Michael Payne Feb 08 '12 at 22:23
  • 1
    If it is a good hash, you do not need to care much for retrieving it securely. It is supposed to be pretty much useless to anyone who happens to see it (plus, when they get inbetween of your code and your database, they probably can also intercept the plaintext you got from the client before hashing). – Has QUIT--Anony-Mousse Feb 09 '12 at 07:54