Java는 SHA-1 바이트 어레이를 인코딩합니다
문제
GET 요청에 사용하고 싶은 SHA-1 바이트 배열이 있습니다. 나는 이것을 인코딩해야한다. URLEncoder
문자열을 기대하고 문자열을 만들고 인코딩하면 손상 되나요?
명확히하기 위해, 이것은 내 다른 질문에 대한 후속 조치입니다. (BITORRENT 추적기 요청) 값을 육각 문자열로 얻을 수 있지만 추적기는 인식하지 못합니다. 반면, 인코딩 된 답변 마크는 Return 200 OK를 제공했습니다.
그래서 나는 내가 얻은 16 진 진술을 변환해야합니다.
9a81333c1b16e4a83c10f3052c1590aadf5e2e20
인코딩 된 형태로
%9A%813%3C%1B%16%E4%A8%3C%10%F3%05%2C%15%90%AA%DF%5E.%20
해결책
응답하는 동안 질문이 편집되었으며 다음은 추가 코드이며 (16 진수 변환 코드와 함께) 작동해야합니다.
//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);
}
원시 바이트를 16 진 문자 또는 사용중인 URL 친화적 인 인코딩으로 변환해야합니다. Base32 또는 Base64 인코딩이 가능하지만 직선형 16 진 문자가 가장 일반적입니다. 이 문자열에는 Urlencoder가 필요하지 않습니다. URL이 %NN 형식으로 인코딩 해야하는 문자가 포함되어 있지 않아야하기 때문입니다.
아래는 해시 (SHA-1, MD5SUM 등)의 바이트를 16 진수로 변환합니다.
/** 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 () 메소드를 사용하여 대문자를 소문자로 변환해야 할 수도 있습니다.
다른 팁
이것은 귀하의 요청 수신자가 기대하는 것에 따라 다릅니다. 나는 그것이 당신의 해시에서 바이트를 16 진수하게 표현할 수 있다고 생각합니다. 해시 어레이에는 인쇄 할 수없는 문자 값이 포함될 가능성이 높기 때문에 문자열은 아마도 최선의 아이디어가 아닐 것입니다.
배열을 반복하고 Integer.toHexValue ()를 사용하여 바이트를 16 진로 변환합니다.
SHA1은 16 진 형식 [0-9A-F]이며 URLENCODE를 필요로하지 않아야합니다.
사용 Apache Commons-Codec 모든 인코딩/디코딩 요구에 대해 (ASN.1 제외, 이것은 엉덩이의 고통입니다)