Использование PBKDF2 в Java и PHP

У меня возникли трудности с созданием одного и того же зашифрованного пароля с использованием алгоритма PBKDF2 на Java и PHP.

Я использую следующую реализацию 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, длину ключа 160 в Java и длину ключа 40 в PHP (чтобы компенсировать установку raw-output в false)

Java Output - 971f0dddc1bc2e899f2bca178f16ea79bfbbb13
PHP Output - 0971f0dddc1bc2e899f2bca178f16ea79bfbbb13

Любая помощь очень ценится, спасибо.

1 ответ

Решение

Это BigInteger это убивает ведущих 0.

Хэши не являются целыми числами, это массив 8-битных байтов. Не пытайтесь конвертировать в BigInteger,

Либо использовать его как byte[] или закодировать в виде шестнадцатеричной или Base64 строки. Чтобы соответствовать PHP шестнадцатеричное кодирование hashedPassword,

PHP возвращает шестнадцатеричный хеш, закодированный строкой, потому что raw_output установлен в FALSE,

Другие вопросы по тегам