在Java和PHP中使用PBKDF2

时间:2016-03-16 01:11:42

标签: java php encryption pbkdf2

我在使用Java和PHP上的PBKDF2算法生成相同的加密密码时遇到了一些困难。

我正在使用以下Java实现来生成具有16字节大小的随机字节数组的散列。然后我将哈希和盐分别存储在MySQL数据库中,但是当我使用从数据库中检索到的盐在PHP中执行相同的操作时,我得到几乎完全相同的加密,除了哈希具有前导0和我不能为我的生活找出原因。

爪哇:

public String hashPassword(String password, byte[] salt){

 char[] passwordChars = password.toCharArray();

     PBEKeySpec spec = new PBEKeySpec(
         passwordChars,
         salt,
         ITERATIONS,
         KEY_LENGTH
     );
     SecretKeyFactory key = null;
    try {
        key = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }

    byte[] hashedPassword = null;

    try {
        hashedPassword = key.generateSecret(spec).getEncoded();
    } catch (InvalidKeySpecException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
     return String.format("%x", new BigInteger(hashedPassword));

}

我在https://adambard.com/blog/3-wrong-ways-to-store-a-password/

找到了上述代码

PHP:

$query = $database->query('SELECT * FROM USERS');

$password = 'hello';
$iterations = 1000;

foreach($query as $user){
    $hash = hash_pbkdf2("sha1", $password, $user['salt'], $iterations, 40, false);

}
echo $hash;

注意:数据库中只存储了一个用户,我知道上面的代码不是很好,我为了测试目的而快速创建了它。

对于这两种实现,我使用的迭代次数为1000,Java中的密钥长度为160,PHP的密钥长度为40(以补偿将raw-output设置为false)

Java Output - 971f0dddc1bc2e899f2bca178f16ea79bfbbb13
PHP Output - 0971f0dddc1bc2e899f2bca178f16ea79bfbbb13

非常感谢任何帮助,谢谢。

1 个答案:

答案 0 :(得分:4)

BigInteger正在杀死领先的0。

哈希不是整数,它们是一个8位字节的数组。请勿尝试转换为BigInteger

将其用作byte[]或编码为十六进制或Base64字符串。匹配PHP十六进制编码hashedPassword

PHP返回十六进制字符串编码哈希,因为raw_output设置为FALSE