Сравнение байтовых массивов - PullRequest
0 голосов
/ 08 декабря 2010

Я пытаюсь сравнить 2-байтовые массивы.

Массив байтов 1 - это массив с последними 3 байтами хэша sha1:

  private static byte[] sha1SsidGetBytes(byte[] sha1)
  {
    return new byte[] {sha1[17], sha1[18], sha1[19]};
  }

Массив байтов 2 - это массив, который язаполнить 3 байтами из шестнадцатеричной строки:

  private static byte[] ssidGetBytes(String ssid)
  {
    BigInteger ssidBigInt = new BigInteger(ssid, 16);

    return ssidBigInt.toByteArray();
  }

Как такое сравнение:

  if (Arrays.equals(ssidBytes, sha1SsidGetBytes(snSha1)))
  {
  }

работает в большинстве случаев, но иногда нет.Порядок байтов?

например, для "6451E6" (шестнадцатеричная строка) он работает нормально, для "ABED74" - нет ...

Ответы [ 3 ]

3 голосов
/ 08 декабря 2010

Проблема довольно очевидна, если вы попробуете это:

BigInteger b1 = new BigInteger("6451E6", 16);
BigInteger b2 = new BigInteger("ABED74", 16);

System.out.println(b1.toByteArray().length);
System.out.println(b2.toByteArray().length);

В частности, ABED74 создает BigInteger, байтовый массив которого имеет длину 4 байта - поэтому, конечно, он не будет равен ни одному из трехбайтовых массивов.

Простое решение - изменить оператор возврата в ssidGetBytes с

return ssidBigInt.toByteArray();

до

byte[] ba = ssidBigInt.toByteArray();
return new byte[] { ba[ba.length - 3], ba[ba.length - 2], ba[ba.length - 1] };
1 голос
/ 08 декабря 2010

Из javadoc (выделено мной):

http://download.oracle.com/javase/1.5.0/docs/api/java/math/BigInteger.html#toByteArray%28%29

Возвращает байтовый массив, содержащий представление дополнения до двух этого BigInteger.Массив байтов будет иметь порядок байтов с прямым порядком байтов: самый старший байт находится в нулевом элементе.Массив будет содержать минимальное количество байтов, необходимое для представления этого BigInteger, включая, по крайней мере, один знаковый бит (ceil ((this.bitLength () + 1) / 8)).(Это представление совместимо с конструктором (byte []) .)

В конструкторе ByteInteger (String, radix) выполняется множество вычислений, которыми вы являетесьusing, который не гарантирует, что созданный BigInteger создаст байтовый массив (через метод toByteArray ()), сравнимый с результатом кодирования String getBytes ().

Вывод toByteArray () предназначен для использования (главным образом) в качестве входных данных для конструктора (byte []) BigInteger.Он не дает никаких гарантий для использования кроме тех.

Посмотрите на это так: выходные данные toByteArray () являются байтовым представлением объекта BigInteger и всего, что в нем , включая внутренние атрибуты, такие как величина.Эти атрибуты не существуют во входной строке, но вычисляются во время создания объекта BitInteger.

Это будет несовместимо с байтовым представлением входной строки , которая содержит только начальную цифрузначение для создания BigInteger.

1 голос
/ 08 декабря 2010

Ваш подход к разбору шестнадцатеричной строки через BigInteger, по сути, ошибочен. Например, new BigInteger("ABED74").toByteArray() возвращает массив 4 байтов, а не три. В то время как вы могли бы взломать это, вы принципиально не пытаетесь сделать что-либо с использованием значений BigInteger ... вы просто пытаетесь разобрать hex.

Я предлагаю вам использовать библиотеку Apache Codec для анализа:

byte[] array = (byte[]) new Hex().decode(text);

(API для Apache Codec оставляет желать лучшего, но работает.)

...