Android Little Endian MD5 - PullRequest
       10

Android Little Endian MD5

3 голосов
/ 04 марта 2012

Я портирую приложение Windows на Android, и у меня возникла проблема с порядком байтов.Приложение берет серию текстовых полей от пользователя и генерирует пароль на основе MD5.Проблема в том, что когда я создаю байтовый массив для передачи в метод дайджеста MD5, байты в Android-приложении имеют формат с прямым порядком байтов.Таким образом, вывод MD5 не совпадает между двумя платформами.

Я пытался использовать ByteBuffer для преобразования в младший порядок байтов, а затем скопировать это значение обратно в байтовый массив с помощью ByteBuffer.get ().К сожалению, это не работает, так как не поддерживает настройку порядка. Это похоже на известное «недоразумение» при работе с ByteBuffers.Если я сравниваю значение ByteBuffer.getLong () и эквивалент в версии для Windows, значения совпадают, но я не знаю, как вернуть массив из ByteBuffer в правильном порядке.

Редактировать: IНиже я добавил функции java и C #.

Ниже приведена версия java, которая не пытается исправить порядок / порядковый номер:

public static final long md5(final String input) {
    try {
        // Create MD5
        MessageDigest md5 = MessageDigest.getInstance("MD5");

        // Read in string as an array of bytes.
        byte[] originalBytes = input.getBytes("US-ASCII");
        byte[] encodedBytes = md5.digest(originalBytes);

        long output = 0;
        long multiplier = 1;

        // Create 64 bit integer from the MD5 hash of the input
        for (int i = 0; i < encodedBytes.length; i++) {
            output = output + encodedBytes[i] * multiplier;
            multiplier = multiplier * 255;
        }
        return output;

    } 
    catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
     catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return 0;
}

А вот версия C #

private Int64 MD5(string input)
{
  MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();

  byte[] originalBytes = ASCIIEncoding.ASCII.GetBytes(input);
  byte[] encodedBytes = md5.ComputeHash(originalBytes);
  Int64 output = 0;
  Int64 Multiplyer = 1;
  for (int i = 0; i < encodedBytes.Length; i++)
  {
    output = output + encodedBytes[i] * Multiplyer;
    Multiplyer = Multiplyer * 255;
  }
  return output;
}

Ответы [ 2 ]

2 голосов
/ 05 марта 2012

Проблема в том, что эта строка Java:

            output = output + encodedBytes[i] * multiplier;

несколько отличается от этой строки кода C #:

    output = output + encodedBytes[i] * Multiplyer;

В частности, неявное преобразование encodedBytes[i] изbyte до long (Java) или Int64 (C #) немного отличаются.

В Java вы видите byte значение со знаком между -128 и 127, тогда как в C # это значение без знака между 0 и 255.Так, например, если encodedBytes[i] равно B2 (1011 0010), то Java интерпретирует это как -78, а C # интерпретирует это как 178.

Чтобы эмулировать интерпретацию C # в Java, вы можетенапишите что-то вроде этого:

            output = output + ((encodedBytes[i] + 256) % 256) * multiplier;

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

0 голосов
/ 04 марта 2012

Стандарт MD5 требует 128-битных значений, а не 64-битных.Так что, во-первых, подпись private Int64 MD5(string input) не имеет смысла.Вы не должны преобразовывать их в целые числа и пытаться сравнить их.Просто передайте byte[] ссылки и сравните их.

...