2015-01-26 5 views
1

Этот вопрос касается операций, выполняемых с массивами байтов, прежде чем они будут хэшированы в java.Зачем бросать все байт нулей в массив байтов java перед хешированием

Я пытаюсь понять, почему в нескольких библиотеках криптографии srp ведущий нулевой байт (в случае его наличия) отбрасывается до того, как он хешируется.

, например: это от Bouncy Castle

/** 
* Return the passed in value as an unsigned byte array. 
* 
* @param value value to be converted. 
* @return a byte array without a leading zero byte if present in the signed encoding. 
*/ 
public static byte[] asUnsignedByteArray(int length, BigInteger value) 
{ 
    byte[] bytes = value.toByteArray(); 
    if (bytes.length == length) 
    { 
     return bytes; 
    } 

    int start = bytes[0] == 0 ? 1 : 0; 
    int count = bytes.length - start; 

    if (count > length) 
    { 
     throw new IllegalArgumentException("standard length exceeded for value"); 
    } 

    byte[] tmp = new byte[length]; 
    System.arraycopy(bytes, start, tmp, tmp.length - count, count); 
    return tmp; 
} 

или это из венчика SRP:

public static byte[] toUnsignedByteArray(final BigInteger bigInteger) { 

    byte[] bytes = bigInteger.toByteArray(); 
    byte[] result = toUnsignedByteArray(bytes); 

    // remove leading zero if any 
    if (bytes[0] == 0) { 

     byte[] tmp = new byte[bytes.length - 1]; 

     System.arraycopy(bytes, 1, tmp, 0, tmp.length); 

     return tmp; 
    } 
    return bytes; 
} 

Купил примеры в основном падение, что ведущий ноль. Методы из этих библиотек вызывают «toUnsignedByteArray», хотя я не понимаю, почему падение начального нуля приведет к тому, что массив байтов будет неподписанным. То есть он просто отбрасывает нулевой байт, тогда следующий байт может быть отрицательным, т. е. следующий байт становится самым левым байтом (в Big Indian), а самый левый бит в байте - это знаковый бит, который может быть установлен или отменен в зависимости от байта, So если я правильно понимаю структуру байтового массива, эти методы не должны вызываться в «toUnsignedByteArray» в первую очередь. Однако самый важный вопрос заключается в том, почему нам нужно отбросить этот нулевой байт, если все нули

Вот пример тестового вектора из приложения srp rfc 5054 A. Мы вычислим U из A и B. Где нулевой байт B случается все нули в двоичном, т.е. если мы выводим B в виде массива байтов, мы получим следующие значения

public static final B = new BigInteger("BD0C61512C692C0CB6D041FA01BB152D4916A1E77AF46AE105393011BAF38964DC46A0670DD125B95A981652236F99D9B681CBF87837EC996C6DA04453728610D0C6DDB58B318885D7D82C7F8DEB75CE7BD4FBAA37089E6F9C6059F388838E7A00030B331EB76840910440B1B27AAEAEEB4012B7D7665238A8E3FB004B117B58", 16); 

[0, -67, 12, 97, 81, 44, 105 , 44, 12, -74, -48, 65, -6, 1, -69, 21, 45, 73, 22, -95, -25, 122, -12, 106, -31, 5, 57, 48, 17, -70, -13, -119, 100, -36, 70, -96, 103, 13, -47, 37, -71, 90, -104, 22, 82, 35, 111, - 103, - 39, -74, -127, -53, -8, 120, 55, -20, -103, 108, 109, -96, 68, 83, 114, -122, 16, -48, -58, - 35, -75, -117, 49, -120, -123, -41, -40, 44, 127, -115, -21, 117, -50, 123, -44, -5, -86, 55 , 8, -98, 111, -100, 96, 89, -13, -120, -125, -114, 122, 0, 3, 11, 51, 30, -73, 104, 64, -111, 4 , 64, -79, -78, 122, -82, -82, -21, 64, 18, -73, -41, 102, 82, 56, -88, -29, -5, 0, 75, 17, 123, 88]

байт Нулевых печататься в двоичной системе: 00000000

Теперь я понимаю, что по какой-то причине, сбросив эти байты важно (хотя я не уверен), что я имею в виду с теми тестовыми векторов правильно вычислить эти две библиотеки следует правильно запрограммировать? Однако я не понимаю, почему нам нужно отбросить этот нулевой байт. В чем проблема с этим. Если я отброшу этот ведущий бай-и-байт и попытаюсь создать еще один BigInteger из массива байтов без начального нулевого байта, тогда я получу совершенно другое число в этом случае даже отрицательное. Поэтому сброс этого нулевого байта не создает для меня никакой сцены. Любые объяснения приветствуются.

ответ

2

«unsigned» в названии, возможно, немного вводит в заблуждение; это не падение 0 байта, что делает его неподписанным, он просто предполагает, что BigInteger содержит неподписанное число.

0 байт, отбрасываемый в этих случаях, не изменяет значение, точно так же, как 01 или 001 - то же значение, что и 1.

Это будет важно отказаться от нуля по разным причинам:

  1. Не тратить пространство лишних 0 байт.
  2. Обеспечение согласованности представления при сравнении массивов байтов.
  3. (И самое важное в контексте, о котором вы говорите) хэш байтового массива с дополнительным 0 впереди не будет таким же, как хэш массива байтов без дополнительного 0. Хэш-функция doesn ' В конце концов, я знаю, что это число и что 0 в этом случае не имеет смысла. Представьте себе, был ли это файл, с байтами 0:1:2:3 и файлом с байтами 1:2:3. Вы не ожидали бы, что хэш файлов с разной длиной будет одинаковым.

Обратите внимание, что если 0-байты должны быть удалены с начала или конца, это зависит от endianness целочисленного представления.

UPDATE: Разъяснение удаления 0 байт:

В то время как удаление 0 байт от начала или конца любого старого байтового массива бы изменить значение в тех случаях, вы имеете в виду мы «Речь идет о представлении целого числа. Если значение 0-байта имеет значение, например. вы хотите округлить некоторые двоичные данные, было бы нецелесообразно загружать эти двоичные данные в класс BigInteger. Я ссылаюсь на свой оригинальный пример, вы не считаете, что 1 и 01 будут разными номерами (хотя вы считаете, что это разные строки)?

ОБНОВЛЕНИЕ: Осветление на байтов:

Целые могут быть представлены по-разному в памяти. Если вы видели номер 20 (в обычном десятичном разряде), вы знаете, что 2 относится к числу десятков, но это всего лишь соглашение. Мы могли бы написать двадцать назад как 02 и поместить наибольшие единицы в конце номера. Точно так же в компьютере порядок цифр может быть таким, каким мы обычно знакомы с ними, или они могут быть «назад». Учитывая, что 0s, которые не влияют на значение числа, могут быть либо в начале, либо в конце массива байтов, и мы должны знать, когда имеем дело с массивом байтов, который должен быть вокруг байтов "читать".

+0

Я принимаю номера 1 и 2, однако у меня есть вопрос до номера 3. Я не согласен с утверждением, что нулевой байт не изменил значение. Проблема, которую я вижу, заключается в том, что если вы сбросите нулевой байт и выберете из него байтовый массив и попробуйте преобразовать его обратно в BigInteger, тогда вы не получите то же значение, поэтому оно изменит его. Более того, я бы ожидал, что если я возьму хэш из какого-то объекта, т. Е. Целочисленного файла и т. Д., Для тех, кто будет тем же самым объектом, т. Е. Что они были в начале, за исключением того, что действительно существует какое-то соглашение, как вы упомянули об зависимостях континентности – Tito

+0

не могли бы вы подробнее рассказать о контенте, википедия, похоже, не упоминает об этом. – Tito

+0

Я обновил некоторые пояснения по пунктам в ваших 2 комментариях. – softwariness

 Смежные вопросы

  • Нет связанных вопросов^_^