У меня возникли некоторые трудности при создании одного и того же зашифрованного пароля с использованием алгоритма 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
Любая помощь очень ценится, спасибо.
Это BigInteger
это убивает ведущих 0.
Хэши не являются целыми числами, это массив 8-битных байтов. Не пытайтесь конвертировать в BigInteger
,
Либо использовать его как byte[]
или закодировать в виде шестнадцатеричной или Base64 строки. Чтобы соответствовать PHP шестнадцатеричное кодирование hashedPassword
,
PHP возвращает хеш с шестнадцатеричной строкой, потому что raw_output
установлен в FALSE
,
Других решений пока нет …