Java Encode SHA-1 Byte Array - PullRequest
       28

Java Encode SHA-1 Byte Array

0 голосов
/ 20 июня 2009

У меня есть байтовый массив SHA-1, который я хотел бы использовать в запросе GET. Мне нужно закодировать это. URLEncoder ожидает строку, и если я создаю ее и затем кодирую, она становится поврежденной?

Чтобы уточнить, это своего рода продолжение моего другого вопроса. ( Bitorrent Tracker Request ) Я могу получить значение в виде шестнадцатеричной строки, но трекер не распознает это значение С другой стороны, при кодированной отметке ответа возвращается 200 OK.

Так что мне нужно преобразовать полученное шестнадцатеричное представление:

9a81333c1b16e4a83c10f3052c1590aadf5e2e20

в кодированном виде

%9A%813%3C%1B%16%E4%A8%3C%10%F3%05%2C%15%90%AA%DF%5E.%20

Ответы [ 4 ]

3 голосов
/ 20 июня 2009

Вопрос был отредактирован, пока я отвечал, ниже приводится ДОПОЛНИТЕЛЬНЫЙ код, который должен работать (с моим шестнадцатеричным кодом преобразования):

//Inefficient, but functional, does not test if input is in hex charset, so somewhat unsafe
//NOT tested, but should be functional
public static String encodeURL(String hexString) throws Exception {
  if(hexString==null || hexString.isEmpty()){
     return "";
  }
  if(hexString.length()%2 != 0){
    throw new Exception("String is not hex, length NOT divisible by 2: "+hexString);
  }
  int len = hexString.length();
  char[] output = new char[len+len/2];
  int i=0;
  int j=0;
  while(i<len){
      output[j++]='%';
      output[j++]=hexString.charAt(i++);
      output[j++]=hexString.charAt(i++);
  }
  return new String(output);
}

Вам необходимо преобразовать необработанные байты в шестнадцатеричные символы или в любую кодировку, удобную для URL, которую они используют. Возможны кодировки Base32 или Base64, но наиболее распространенными являются прямые шестнадцатеричные символы. URLEncoder не нужен для этой строки, поскольку он не должен содержать символов, для которых требуется кодировка URL в формате% NN.

Ниже приведено преобразование байтов для хэша (SHA-1, MD5SUM и т. Д.) В шестнадцатеричную строку:

/** Lookup table: character for a half-byte */
    static final char[] CHAR_FOR_BYTE = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
         /** Encode byte data as a hex string... hex chars are UPPERCASE*/
         public static String encode(byte[] data){
             if(data == null || data.length==0){
                 return "";
             }
             char[] store = new char[data.length*2];
             for(int i=0; i<data.length; i++){
                 final int val = (data[i]&0xFF);
                 final int charLoc=i<<1;
                 store[charLoc]=CHAR_FOR_BYTE[val>>>4];
                 store[charLoc+1]=CHAR_FOR_BYTE[val&0x0F];
             }
             return new String(store);
         }

Этот код довольно оптимизирован и быстр, и я использую его для собственной байтовой кодировки SHA-1. Обратите внимание, что вам может потребоваться преобразовать прописные буквы в строчные с помощью метода String.toLowerCase (), в зависимости от того, какую форму принимает сервер.

0 голосов
/ 20 июня 2009

Используйте Apache Commons-Codec для всех ваших потребностей в кодировании / декодировании (кроме ASN.1, который является проблемой в заднице)

0 голосов
/ 20 июня 2009

SHA1 имеет шестнадцатеричный формат [0-9a-f], поэтому не нужно его кодировать URLE.

0 голосов
/ 20 июня 2009

Это зависит от того, что ожидает получатель вашего запроса. Я полагаю, это может быть шестнадцатеричное представление байтов в вашем хэше. Строка, вероятно, не будет лучшей идеей, потому что хэш-массив, скорее всего, будет содержать непечатаемые символьные значения.

Я бы перебрал массив и использовал бы Integer.toHexValue () для преобразования байтов в шестнадцатеричный формат.

...