java - Verify username and a salted password -
i have application usues jdbc jquery , mysql lists table quotes , user can add quotes.
i have loggin page check input of username , compare exits in database. , works fine
public boolean findbyusername(string username) throws sqlexception { resultset rs = null; connection conn = null; preparedstatement pstmt = null; try { conn = database.getconnection(); conn.setautocommit(false); string query = "select * user username = ?"; pstmt = conn.preparestatement(query); pstmt.setstring(1, username); rs = pstmt.executequery(); if (rs.next()) { return true; } } catch (exception e) { e.printstacktrace(); throw new runtimeexception(e); } { conn.close(); } return false; } but when want compare password problem salt password pbkdf2 generates random characters 1000:485b5808b4786d6aa6e5360ad157945ee927d85e49e96312:60d76b0ef1b742cfa462d84eb7fd7c37eb361717179c0a45. when want compare passwordinput in database use method.
public boolean findbypassword(string password) throws sqlexception, nosuchalgorithmexception, invalidkeyspecexception { resultset rs = null; connection conn = null; preparedstatement pstmt = null; passwordhash p = new passwordhash(); string hash = p.createhash(password); try { conn = database.getconnection(); conn.setautocommit(false); string query = "select * user passwd = ?"; system.out.println("password: " +password); system.out.println("hashpassword " +hash); pstmt = conn.preparestatement(query); pstmt.setstring(1, hash); rs = pstmt.executequery(); if (rs.next()) { if(p.validatepassword(password, hash)){ return true; } } } catch (exception e) { e.printstacktrace(); throw new runtimeexception(e); } { conn.close(); } return false; } i uses class hash password
public class passwordhash { public final string pbkdf2_algorithm = "pbkdf2withhmacsha1"; // following constants may changed without breaking existing hashes. public final int salt_byte_size = 24; public final int hash_byte_size = 24; public final int pbkdf2_iterations = 1000; public final int iteration_index = 0; public final int salt_index = 1; public final int pbkdf2_index = 2; /** * returns salted pbkdf2 hash of password. * * @param password * password hash * @return salted pbkdf2 hash of password */ public string createhash(string password) throws nosuchalgorithmexception, invalidkeyspecexception { return createhash(password.tochararray()); } /** * returns salted pbkdf2 hash of password. * * @param password * password hash * @return salted pbkdf2 hash of password */ public string createhash(char[] password) throws nosuchalgorithmexception, invalidkeyspecexception { // generate random salt securerandom random = new securerandom(); byte[] salt = new byte[salt_byte_size]; random.nextbytes(salt); // hash password byte[] hash = pbkdf2(password, salt, pbkdf2_iterations, hash_byte_size); // format iterations:salt:hash return pbkdf2_iterations + ":" + tohex(salt) + ":" + tohex(hash); } /** * validates password using hash. * * @param password * password check * @param correcthash * hash of valid password * @return true if password correct, false if not */ public boolean validatepassword(string password, string correcthash) throws nosuchalgorithmexception, invalidkeyspecexception { return validatepassword(password.tochararray(), correcthash); } /** * validates password using hash. * * @param password * password check * @param correcthash * hash of valid password * @return true if password correct, false if not */ public boolean validatepassword(char[] password, string correcthash) throws nosuchalgorithmexception, invalidkeyspecexception { // decode hash parameters string[] params = correcthash.split(":"); int iterations = integer.parseint(params[iteration_index]); byte[] salt = fromhex(params[salt_index]); byte[] hash = fromhex(params[pbkdf2_index]); // compute hash of provided password, using same salt, // iteration count, , hash length byte[] testhash = pbkdf2(password, salt, iterations, hash.length); // compare hashes in constant time. password correct if // both hashes match. return slowequals(hash, testhash); } /** * compares 2 byte arrays in length-constant time. comparison method * used password hashes cannot extracted on-line * system using timing attack , attacked off-line. * * @param * first byte array * @param b * second byte array * @return true if both byte arrays same, false if not */ private boolean slowequals(byte[] a, byte[] b) { int diff = a.length ^ b.length; (int = 0; < a.length && < b.length; i++) diff |= a[i] ^ b[i]; return diff == 0; } /** * computes pbkdf2 hash of password. * * @param password * password hash. * @param salt * salt * @param iterations * iteration count (slowness factor) * @param bytes * length of hash compute in bytes * @return pbdkf2 hash of password */ private byte[] pbkdf2(char[] password, byte[] salt, int iterations, int bytes) throws nosuchalgorithmexception, invalidkeyspecexception { pbekeyspec spec = new pbekeyspec(password, salt, iterations, bytes * 8); secretkeyfactory skf = secretkeyfactory.getinstance(pbkdf2_algorithm); return skf.generatesecret(spec).getencoded(); } /** * converts string of hexadecimal characters byte array. * * @param hex * hex string * @return hex string decoded byte array */ private byte[] fromhex(string hex) { byte[] binary = new byte[hex.length() / 2]; (int = 0; < binary.length; i++) { binary[i] = (byte) integer.parseint( hex.substring(2 * i, 2 * + 2), 16); } return binary; } /** * converts byte array hexadecimal string. * * @param array * byte array convert * @return length*2 character string encoding byte array */ private string tohex(byte[] array) { biginteger bi = new biginteger(1, array); string hex = bi.tostring(16); int paddinglength = (array.length * 2) - hex.length(); if (paddinglength > 0) return string.format("%0" + paddinglength + "d", 0) + hex; else return hex; } /** * tests basic functionality of passwordhash class * * @param args * ignored */ } i call metod here
@post @path("/login") @produces(mediatype.text_plain) public string loginuser(string username, string password) throws nosuchalgorithmexception, invalidkeyspecexception, sqlexception { gson gson = new gson(); user theuser = gson.fromjson(username, user.class); if (!u.findbyusername(theuser.getusername()) && u.findbypassword(theuser.getpasswd())) { return theuser.getusername(); } return null; } how compare passwordinput exits in database ?
you query database in findbyusername method using select * user username = ?. result of query should return password hash well. take password hash query, , call validatepassword.
forget findbypassword method. won't work. besides being wrong. (it return true if of users stored in database had password provided)
some hints on storing passwords in sql (or database, or rather storage):
- always store password hashed strong hash. (you that, should repeated anytime talking storing passwords)
- always salt hashes. (you well, same above)
- and please make sure salts random.
- always query by username or whatever unique identificator is.
- have unique key on identificator.
- never use column contain duplicates find user record.
- that means never query password (or hash), well.
- never use password in query. never in cleartext.
- better, try avoiding hashes in selects.
- use multiround algorithms. care.
- do not implement algorithm yourself, unless know doing.
- keep number of rounds reasonable. hashing password 100ms may dosed easily.
- do not things
for(int i=0;i<rounds;i++) md5(previous_hash). may, , will, compromise hash.
- never implement hashes yourself. (unless of course know doing)
- do not combine hashes.
md5(sha256(sha512(password)))might seem idea @ first, trust me, not.
- always store password hashed. use strong hash. salt hash random salt.
(if has tip on missing hint, i'll happy add ...)
Comments
Post a Comment