I simulate storing password hashes and validate it in login process.
I have a method called hashPassword(String password)
to get a String password and returns it's hash with adding of salt.
I choose salt an static value and in this example, i choose an identical value for password ( hello123
)
public class T1 {
public static void main(String[] args) {
String userDefinedPassword = "hello123";
String hashedPassToStoreInDB = String.valueOf(hashPassword(userDefinedPassword));
System.out.println("what stores in DB: " + hashedPassToStoreInDB);
// store in database
//Password Verify
String inputPassword = "hello123";
String hashedInputPassword = String.valueOf(hashPassword(inputPassword));
System.out.println("Users hashed password: " + hashedInputPassword);
if (hashedPassToStoreInDB.equals(hashedInputPassword)) {
System.out.println("Correct");
} else {
System.out.println("Incorrect");
}
}
private static byte[] hashPassword(String password) {
byte[] salt = new byte[16];
byte[] hash = null;
for (int i = 0; i < 16; i++) {
salt[i] = (byte) i;
}
try {
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128);
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
hash = f.generateSecret(spec).getEncoded();
} catch (NoSuchAlgorithmException nsale) {
nsale.printStackTrace();
} catch (InvalidKeySpecException ikse) {
ikse.printStackTrace();
}
return hash;
}
}
But the result is:
what stores in DB: [B@219c9a58
Users hashed password: [B@305918a5
Incorrect
Why this two value is not identical?
What is wrong with my code?
The problem is here:
String hashedPassToStoreInDB = String.valueOf(hashPassword(userDefinedPassword));
and here:
String hashedInputPassword = String.valueOf(hashPassword(inputPassword));
You're creating a String
from the byte[]
returned from hashPassword
method, but using the wrong method. Since there's no overload for byte[]
in String#valueOf
method, it ends calling String#valueOf(Object obj)
which will use Object#toString
internally, and the string representation of an array by itself is meaningless.
Use new String(byte[] byteArray)
instead.
String hashedPassToStoreInDB = new String(hashPassword(userDefinedPassword));
//...
String hashedInputPassword = new String(hashPassword(inputPassword));
You are generating two different instances of a byte[]
array, whose String
representation follows the one from Object.toString
.
Hence the hashes of your two byte[]
s are different.
Try comparing Arrays.equals(yourSaltedPassword, yourOtherSaltedPassword)
instead.
For instance:
byte[] foo = {1,2};
byte[] bar = {1,2};
System.out.println(foo == bar);
System.out.println(String.valueOf(foo).equals(String.valueOf(bar)));
System.out.println(Arrays.equals(foo, bar));
Output
false
false
true
If you need to store your byte[]
s as String
s, you can represent them equally (for equal byte[]
s) with Arrays.toString(myByteArray)
.
The comparisons between the two equal passwords will then return equal String
s.
You have stumbled on to the fact that java arrays do not override toString.
Bug why use arrays: You can get a basic salt working by just concatenating strings, then using hashCode()
on the result:
int hash = (password + salt).hashCode();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.