Хеширование Java MD5 не соответствует хешированию C# MD5

Я очень мало знаю о шифровании/хешировании.

Мне нужно хешировать ключ шифрования. Пример на Java выглядит так...

String encryptionKey = "test";

    MessageDigest messageDigest = MessageDigest.getInstance("MD5");
    messageDigest.update(encryptionKey.getBytes("UTF-8"), 0, encryptionKey.length());
    byte[] encryptionKeyBytes = messageDigest.digest();

Теперь поправьте меня, если я ошибаюсь, но приведенный выше код хэширует строку с помощью алгоритма MD5.

И мне нужен тот же результат, когда я хеширую одну и ту же строку на С#.

Мой текущий код С# выглядит так...

string encryptionKey = "test";

        var md5 = MD5.Create();
        var keyBytes = Encoding.UTF8.GetBytes(encryptionKey);
        byte[] encryptionKeyBytes = md5.ComputeHash(keyBytes);

Но результаты конечного байта не совпадают.

Ява получает...

[0] 9   
[1] -113    
[2] 107 
[3] -51 
[4] 70  
[5] 33  
[6] -45 
[7] 115 
[8] -54 
[9] -34 
[10]    78  
[11]    -125    
[12]    38  
[13]    39  
[14]    -76 
[15]    -10 

С# получает...

    [0] 9   byte
    [1] 143 byte
    [2] 107 byte
    [3] 205 byte
    [4] 70  byte
    [5] 33  byte
    [6] 211 byte
    [7] 115 byte
    [8] 202 byte
    [9] 222 byte
    [10]    78  byte
    [11]    131 byte
    [12]    38  byte
    [13]    39  byte
    [14]    180 byte
    [15]    246 byte

Мне нужен мой код C#, чтобы получить тот же результат, что и код Java (а не наоборот), есть идеи?

Спасибо.


person Theo    schedule 14.06.2012    source источник
comment
Байты Java подписаны. Байты С# не являются. Обратите внимание, что только в тех местах, где байт Java отрицательный, это неправильно.   -  person vcsjones    schedule 14.06.2012
comment
помимо равного результата, у вас есть довольно серьезная ошибка в коде Java: encryptionKey.getBytes("UTF-8"), 0, encryptionKey.length() Я предоставляю вам понять, в чем ошибка. Последнее сравнение прямого строкового представления (toString) всегда плохая идея   -  person bestsss    schedule 14.06.2012
comment
@bestsss Я использую точку останова для проверки значений. Я думаю, что значения точек останова создаются из представления toString (могут быть неправильными). Как бы вы сравнили значения байтов?   -  person Theo    schedule 14.06.2012
comment
шестнадцатеричный код без знака обычно является нормой для представления byte[], так как вы можете легко увидеть оба полубайта. Кстати, вы узнали, где ошибка?   -  person bestsss    schedule 14.06.2012
comment
@bestsss Он использует массив byte[] для данных, а длина исходит из строки (вместо byte[]). Это то, что вы указывали? Если нет, то я не знаю. Этот java-код представляет собой демо-версию шифрования/дешифрования, отправленную мне. С#, который я должен написать, чтобы получить тот же результат.   -  person Theo    schedule 15.06.2012
comment
да, байт [] utf8 может иметь большую длину, чем исходная строка.   -  person bestsss    schedule 15.06.2012


Ответы (1)


На самом деле результаты одинаковы. Как и другие целочисленные типы, байтовое значение может интерпретироваться как со знаком или без знака. Например, 10001111 будет соответствовать 143 (ваше второе значение C#), если интерпретируется как беззнаковое. Однако, если он интерпретируется как подписанный (с использованием дополнения до двух), его значение будет -113 (ваше второе значение Java).

Таким образом, несоответствие, по-видимому, вызвано тем, что ваши значения отформатированы как подписанные в Java, но не подписанные в C#. Если вы хотите получить подписанные байты на С#, вы можете использовать:

sbyte[] encryptionKeyBytesSigned = 
    encryptionKeyBytes.Select(b => (sbyte)b).ToArray();

Однако будьте осторожны, это не просто проблема форматирования, которая возникает только при отображении ваших значений. При сохранении в файл оба результата должны быть идентичными.

person Douglas    schedule 14.06.2012
comment
Спасибо за ваш ответ... Это последнее утверждение кажется противоречащим, если я его правильно читаю. Если вы сохраняете оба в файл, и они идентичны, то это просто проблема форматирования, которая возникает при отображении значений. Вы можете уточнить? Я возьму это хэшированное значение (в byte[]) и использую его в качестве ключа шифрования. Так что, если это просто проблема с отображением, я думаю, что все будет в порядке без преобразования. Я не думаю, что функция шифрования примет sbyte[] вместо byte[]. - person Theo; 14.06.2012
comment
Н/м. Ты просто предупредил меня, чтобы я проверил и удостоверился. Я понял. - person Theo; 14.06.2012
comment
@Theo: Да, я предполагаю, что это проблема форматирования, и при сохранении в файл результирующие файлы должны быть идентичными даже без преобразования значений C # в байты со знаком. Однако, если честно, я не очень хорошо знаком с Java (могу поручиться только за ваш код на C#), поэтому я бы провел небольшое тестирование, чтобы убедиться. - person Douglas; 14.06.2012
comment
Вы были правы насчет проблемы с форматированием. При записи в файл оба показывают одни и те же символы тарабарщины. Спасибо за помощь. - person Theo; 14.06.2012