Подтвердить что ты не робот

Почему эти генераторы ключей 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-го цикла. Почему после этого получается другой результат?

4b9b3361

Ответ 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-кодом.