使用salt存储和验证哈希密码

时间:2015-01-08 15:27:54

标签: java hash

我模拟存储密码哈希并在登录过程中验证它。

我有一个名为hashPassword(String password)的方法来获取String密码并通过添加salt返回它的哈希值。

我选择salt作为静态值,在本例中,我为密码选择了相同的值(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;
}
}

但结果是:

what stores in DB: [B@219c9a58
Users hashed password: [B@305918a5
Incorrect

为什么这两个值不相同?

我的代码出了什么问题?

3 个答案:

答案 0 :(得分:2)

问题在于:

String hashedPassToStoreInDB = String.valueOf(hashPassword(userDefinedPassword));

在这里:

String hashedInputPassword = String.valueOf(hashPassword(inputPassword));

您正在使用String方法返回的byte[]创建hashPassword,但使用了错误的方法。由于byte[]方法中的String#valueOf没有重载,它结束调用String#valueOf(Object obj),它将在内部使用Object#toString,并且数组的字符串表示本身没有意义。

改为使用new String(byte[] byteArray)

String hashedPassToStoreInDB = new String(hashPassword(userDefinedPassword));
//...
String hashedInputPassword = new String(hashPassword(inputPassword));

答案 1 :(得分:0)

您正在生成byte[]数组的两个不同实例,其String表示遵循Object.toString中的byte[]表示。

因此,你的两个Arrays.equals(yourSaltedPassword, yourOtherSaltedPassword)的哈希值不同。

请尝试比较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));

例如:

false
false
true

<强>输出

byte[]

如果您需要将String存储为byte[],则可以使用Arrays.toString(myByteArray)平等地表示它们(对于相等的String s)。

两个相等密码之间的比较将返回相等的{{1}} s。

答案 2 :(得分:0)

你偶然发现java数组不会覆盖toString。

错误为什么要使用数组:只需连接字符串,然后在结果上使用hashCode(),就可以获得基本的盐工作:

int hash = (password + salt).hashCode();