Как работает вызов алгоритма хеширования, особенно использование сдвига битов 0xff? - PullRequest
0 голосов
/ 24 июля 2011

В следующем фрагменте кода, полученном из Core Java Vol 2 (7-е издание), показано, как создать SHA1 и отпечаток MD5 с использованием Java.

Оказывается, что единственная функция, которая работает, - это когда я загружаю открытый текст из текстового файла.

Как MessageDigestFrame.computeDigest () обрабатывает отпечаток пальца и, в частности, использование шаблона сдвига битов (строка 171 - 172)?

public void computeDigest(byte[] b)
{  
  currentAlgorithm.reset();
  currentAlgorithm.update(b);
  byte[] hash = currentAlgorithm.digest();
  String d = "";
  for (int i = 0; i < hash.length; i++)
  {  
     int v = hash[i] & 0xFF;
     if (v < 16) d += "0";
     d += Integer.toString(v, 16).toUpperCase() + " ";
  }
  digest.setText(d);
} 

Ответы [ 3 ]

2 голосов
/ 24 июля 2011

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

С точки зрения кода, эта строка:

int v = hash[i] & 0xFF;

в основном используется для обработки байта как беззнакового. Байты подписаны в Java - признанная ошибка проектирования в языке - но мы хотим распечатать шестнадцатеричное значение, как если бы оно было целым числом без знака. Побитовое И только с младшими 8 битами эффективно преобразует его в целочисленное значение байта, обработанного как беззнаковый.

(Есть лучшие способы преобразовать байтовый массив в шестнадцатеричную строку, но это отдельный вопрос.)

1 голос
/ 24 июля 2011

Это не битовое смещение, это битовая маскировка.hash[i] - это байт.Когда оно расширено до целого числа, вам необходимо маскировать старшие целые биты из-за возможного расширения знака.

byte b = (byte)0xEF;
System.out.println("No masking: " + (int)b);
System.out.println("Masking:    " + (int)(b & 0xFF));
0 голосов
/ 24 июля 2011

Отрезано:

 int v = hash[i] & 0xFF;
 if (v < 16) d += "0";
 d += Integer.toString(v, 16).toUpperCase() + " ";

Сначала вы устанавливаете все, кроме младших 8 битов v, в 0 (потому что 0xFF - 11111111 в двоичном формате). Затем, если результирующее число представляет собой только одну цифру в шестнадцатеричном формате (<16), вы добавляете начальный «0». Наконец преобразуйте результат в шестнадцатеричное и добавьте его в строку. </p>

...