views:

227

answers:

6

What Java library should I be using to Hash passwords for storage in a database?

I was hoping to just take the plain text password, add a random salt, then store the salt and the hashed password in the database.

Then when a user wanted to log in, I could just take their submitted password, add the random salt from their account information, hash it and see if it equates to the stored hash password with their account information.

+2  A: 

BCrypt is a very good library, and there is a Java port of it.

Michael Borgwardt
A: 

Use MessageDigest to compute hashes (SHA-256 preferably)

Bozho
How would you hash the password at login without storing salt in database?
ZZ Coder
Using the username as the salt is not a fatal flaw, but it's nowhere near as good as using a salt from a cryptographic RNG. And there is absolutely no problem storing the salt in the database. The salt is not secret.
erickson
Wouldn't the username and e-mail also be stored in the database?
DutrowLLC
@ZZ Coder, @erickson correct, I somehow assumed that it will be one salt for all passwords, which would lead to an easily computable rainbow table.
Bozho
One problem with using the username (or other ID like email) as a salt is that you can't then change the ID without having the user also set a new password.
Software Monkey
+1  A: 

Here you have two links for MD5 hashing and other hash methods:

Javadoc API: http://java.sun.com/j2se/1.4.2/docs/api/java/security/MessageDigest.html

Tutorial: http://www.twmacinta.com/myjava/fast_md5.php

Simon
Just keep in mind that for password hashing, slower is better. You should use thousands of iterations of the hash function as a "key strengthening" technique. Also, salt is imperative.
erickson
I'm with you, erickson :)
Simon
I was under the impression that multiple iterations of a quality hashing algorithm would produce about the same security as one iteration since the length of bytes would still be the same?
DutrowLLC
@erickson It would be better to slow down attackers explicitly.
deamon
Yeah, but hashing the hashe's hash ..., is more secure. Let's say you hash "a" to "b" and "b" to "c". Someone could be able to get somehow (though not uniquely) the value "b" but he will unlikely get the original value "a" as he does not know how many times you hashed your intial value.
Simon
@deamon - "Slow them down explicitly?" What does that mean?
erickson
About key strengthening: Salts exist to make precomputed hashes unusable. But attackers do not have to precompute. Attackers can just hash strings + salt "on the fly" until they find the right one. But if you iterate thousands of times for your hashes they will have to do the same. Your server will not be impacted much by 10k iterations as it doesn't happen that often. Attackers will need 10k times the computing power.
zockman
+1  A: 

Among all the standard hash schemes, LDAP ssha is the most secure one to use,

http://www.openldap.org/faq/data/cache/347.html

I would just follow the algorithms specified there and use MessageDigest to do the hash.

You need to store the salt in your database as you suggested.

ZZ Coder
Because SSHA doesn't iterate the hash function, it is too fast. This allows attackers to try passwords more quickly. Better algorithms like Bcrypt, PBBKDF1, and PBKDF2 use "key strengthening" techniques to slow attackers to the point where a password should expire before they can brute force even an 8-letter password space.
erickson
The problem with all these mechanisms is that you don't get client support. The problem with hashed password is that you can't support password hashed with another algorithms. With ssha, at least all the LDAP clients support it.
ZZ Coder
+3  A: 

You can actually use a facility built in to the Java runtime to do this. The SunJCE in Java 6 supports PBKDF2, which is a good algorithm to use for password hashing.

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));
erickson
You may want to be a bit wary of byte to hex conversions with `BigInteger`: leading zeros are removed. That's ok for quick debug, but I have seen bugs in production code due to that effect.
Thomas Pornin
+1  A: 

You can use the Shiro library's (formerly JSecurity) implementation of what is described by OWASP.

It also looks like the JASYPT library has a similar utility.

laz
Thats actually what I was using. But since we decided not to use Shiro, there was some concern about the inefficiency of having to include the whole Shiro library for just that one package.
DutrowLLC
I don't know of a library made up of just a password hashing utility. You're probably better off rolling your own if dependencies are a concern. The answer by erickson looks pretty good to me. Or just copy the code from that OWASP link I referenced if you'd rather use SHA in a secure manner.
laz