У меня возникли трудности с созданием одного и того же зашифрованного пароля с использованием алгоритма 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
Любая помощь очень ценится, спасибо.