Почему эти генераторы ключей PHP и Java производят разные результаты?
Я пишу генератор ключей для шифрования script в PHP, и я хочу, чтобы он был совместим с классом, который я написал на Java, чтобы они могли совместно использовать ресурсы.
PHP-код:
public function keyGen($key, $rounds) {
for($i = 0; $i < $rounds; $i++) {
$key = substr(base64_encode(md5($key)), 0, 16);
echo $i . " " . $key . PHP_EOL; // debugging //
}
return $key;
}
Код Java:
public static String keyGen(String key, int rounds) {
try {
for(int i = 0; i < rounds; i++) {
byte[] md5 = MessageDigest.getInstance("MD5").digest(key.getBytes("UTF-8"));
String md5h = ( new BigInteger(1, md5) ).toString(16);
key = Base64.getEncoder().encodeToString(md5h.getBytes()).substring(0, 16);
System.out.println( Integer.toString(i) + " " + key); // debugging //
}
} catch(Exception ex) {
ex.printStackTrace();
return null;
}
return key;
}
Отладочный вывод PHP:
0 MWExZGM5MWM5MDcz
1 NDVkZmMxNWVjNWZi
2 ODY5YzVkODBhNTRh
3 ZGE2OTNiOWMxOWM1
4 OTcxMTY3MzgxMmRk
5 NWNjNDI2N2IzMDlj
6 NGVkYzY0YjVkMWUy
7 MjdhMGU4NjhhNmU3
8 OWY5OGE3ZGZiODZl
9 Y2I1ZjBkNjRmMjkx
10 YTk5NDA1MGI1OWY1
11 YzRmYWE5ZTk0ZDdl
12 NDBiZWZkNmQ5Yjhj
13 MzQyNzcwNGRjMTYw
14 N2U4ZmUxOGMyNWYx
15 MjBjOTZhNGE4ZDQ1
16 MjdmMzkwMzI0NDdj
17 YjM4NDI0YWU0YzUw
18 NDRiNjA1MWUwOGZi
19 MGI1YmIyMDViMGYz
Отладочный вывод Java:
0 MWExZGM5MWM5MDcz
1 NDVkZmMxNWVjNWZi
2 ODY5YzVkODBhNTRh
3 ZGE2OTNiOWMxOWM1
4 OTcxMTY3MzgxMmRk
5 NWNjNDI2N2IzMDlj
6 NGVkYzY0YjVkMWUy
7 MjdhMGU4NjhhNmU3
8 OWY5OGE3ZGZiODZl
9 Y2I1ZjBkNjRmMjkx
10 YTk5NDA1MGI1OWY1
11 YzRmYWE5ZTk0ZDdl
12 NDBiZWZkNmQ5Yjhj
13 MzQyNzcwNGRjMTYw
14 N2U4ZmUxOGMyNWYx
15 MjBjOTZhNGE4ZDQ1
16 MjdmMzkwMzI0NDdj
17 YjM4NDI0YWU0YzUw
18 NDRiNjA1MWUwOGZi
19 YjViYjIwNWIwZjMy
Он работает как ожидается до 19-го цикла. Почему после этого получается другой результат?
Ответы
Ответ 1
В Java преобразование BigDecimal в шестнадцатеричную строку с помощью метода toString(int base)
не выводит начальные нули.
Вы можете обнаружить это, распечатав вывод промежуточного шага (преобразование хэш-кода md5 в шестнадцатеричную строку) - в Java, который дает b5bb205b0f32a7bf2a80fc870cbd2b7
, а в PHP - 0b5bb205b0f32a7bf2a80fc870cbd2b7
. Это только разница одного ведущего нуля, но после применения кодировки base64 они выглядят совсем по-другому.
Более простой способ получить ведущие нули - использовать метод String.format
.
Заменить эту строку:
String md5h = ( new BigInteger(1, md5) ).toString(16);
с этой строкой:
String md5h = String.format("%032x", new BigInteger(1, md5));
и вы получите тот же результат, что и с вашим php-кодом.