MD5 хэш-код в C # и Kotlin (Java) - PullRequest
       26

MD5 хэш-код в C # и Kotlin (Java)

0 голосов
/ 21 октября 2019

Я борюсь с разницей в потреблении результатов MD5 в Kotlin (Java) и C #. Я нашел эту статью, которая предлагает решение:

Как вы можете генерировать один и тот же хэш-код MD5 в C # и Java?

Но я хотел бы понять логику этого,Я сделал пару тестов. C #:

var data = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes("123456"));
var s = Encoding.UTF8.GetString(data, 0, data.Length);

Создает следующую последовательность байтов (переменную данных):

 225, 10, 220, 57, 73, 186, 89, 171, 190, 86, 224, 87, 242, 15, 136, 62

Если я использую Kotlin (Java):

val md = MessageDigest.getInstance("MD5")
val data = md.digest("123456".toByteArray())

val s = String(data)

val ls2 = data.map { x-> x.toUByte() }

Таким образом, в Java есть байтысо знаком и c # unsigned (ls2 - содержит те же байты без знака, что и в примере c #). Хорошо. Я хотел бы получить строковое значение - я преобразовал оба байтовых массива в строку, и я получил разные строки (переменная s). Что мне не хватает?

Спасибо.

1 Ответ

5 голосов
/ 21 октября 2019

В C # вы пытаетесь использовать кодировку UTF-8, чтобы превратить ваши байты в строку. Однако это очень плохая идея - есть много последовательностей байтов, которые недопустимы в строке в кодировке UTF-8, и дополнительные последовательности, которые приведут к непечатным символам. Если кодировщик встречает последовательность байтов, которые не образуют действительный символ в кодировке UTF-8 (и это будет происходить, потому что вы ничего не делаете, чтобы гарантировать, что ваша последовательность байтов является допустимой строкой в ​​кодировке UTF-8)), он вставит заменяющий символ.

В Kotlin вы используете new String(byte[]), который использует кодировку вашей системы. У вас здесь аналогичная проблема: хотя большинство байтов приводят к действительному символу, некоторые из этих символов будут непечатными.

Таким образом, вы используете две разные кодировки для C # и Kotlin (следовательно, разные результаты), но вы также делаете что-то, что, вероятно, даст вам непечатаемые символы или может заменить последовательности байтов заменяющим символом (поэтому различные хэши MD5 будут выглядеть одинаково).

(Обратите внимание, что «непечатаемые символы» могут просто не отображаться, но они могут делать странные вещи, например, изменять направление текста на этой странице или начинать объединять символы вокруг них!)

Вам было бы лучшепревращение ваших байтов в строку base64 или последовательность шестнадцатеричных символов. Оба из них гарантируют, что каждая возможная последовательность байтов превращается в печатные символы способом, который согласован для разных языков.

Для C # используйте Convert.ToBase64String(data), чтобы получить base64-кодированную строку, и BitConverter.ToString(data).Replace("-","") для получения строки в шестнадцатеричном коде (хотя для этого существует множество способов ).

Для Kotlin используйте Base64.getEncoder().encodeToString(data), чтобы получить base64-закодированная строка и data.joinToString("") { "%02x".format(it) }, чтобы получить шестнадцатеричную строку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...