본문 바로가기

app/java

java의 sha1과 python의 sha1의 암호화 값은 다를 수 있습니다.

프로젝트하는 도중 재미있는 현상을 발견하여 글을 써 봅니다. 


서로 발급된 키로 sha1으로 암호화 하여 통신하는 api를 개발하는 도중 java 와 python의 sha1의 값이 다르게 나오는것을 발견하였습니다. 


아래는 java의 sha1 암호화의 기본 소스 입니다. 



import java.security.MessageDigest;
import java.security.Security;
import java.security.NoSuchAlgorithmException;


public class HelloWorld{
     public static void main(String []args) throws NoSuchAlgorithmException{

         String return_sha1 = makeSHA("81014614b19daf89e35c46ee299ff7ff1c2239e0641874ab");

        System.out.println(return_sha1);
     }

     public static String makeSHA(String inputText) throws NoSuchAlgorithmException{

      String test = inputText;
      MessageDigest md = MessageDigest.getInstance("SHA-1");
      md.update(test.getBytes());
      byte[] digest = md.digest();


      StringBuffer sb = new StringBuffer();
      
      for(byte b : digest){
       sb.append(Integer.toHexString(b & 0xff));
      }

      return sb.toString();
     }
}


그리고 해당 결과 값은 "4728865bb77267f77ddac8d7dbb579f447d27c" 가 나옵니다. 


다음엔 python의 소스 입니다.



import hashlib
m = hashlib.sha1()
str_sha1 = "81014614b19daf89e35c46ee299ff7ff1c2239e0641874ab"
m.update(str_sha1)
print m.hexdigest()

python의 결과 값은 "47028865bb77267f77ddac8d7dbb579f4407d27c" 가 나옵니다. 


java        4728865bb77267f77ddac8d7dbb579f447d27c

python   47028865bb77267f77ddac8d7dbb579f4407d27c


자세히 보시면 java에서 두자리가 나오지 않은것을 확인할수 있습니다.


해당 이슈는 java의 암호화 방식에 있습니다. 

java에서 sha1으로 암호화시 byte->hex로 변환하지만 해당 변환이 암호화된 값이라 다르게 표현됩니다. 

반면 인터프린터 언어(python포함)에서는 string 자체를 sha1으로 변환해주기 때문에 위와 같이 sha1으로 암호화 했어도 다른 값이 나오게 됩니다. 


이런 경우를 대비해서 java에 소스를 추가해 주시면 됩니다. 



import java.security.MessageDigest;
import java.security.Security;
import java.security.NoSuchAlgorithmException;
import javax.xml.bind.DatatypeConverter;
import javax.xml.bind.DatatypeConverter.*;

public class HelloWorld{
     public static void main(String []args) throws NoSuchAlgorithmException{

         String return_sha1 = makeSHA("81014614b19daf89e35c46ee299ff7ff1c2239e0641874ab");
        System.out.println(return_sha1);
     }
     
     public static String makeSHA(String inputText) throws NoSuchAlgorithmException{

      String test = inputText;
      MessageDigest md = MessageDigest.getInstance("SHA-1");
      md.update(test.getBytes());
      byte[] digest = md.digest();
      String result = DatatypeConverter.printHexBinary(digest);

      return result;
     }
}

위의 소스로 변경하면 정상적으로 "47028865BB77267F77DDAC8D7DBB579F4407D27C" 을 출력합니다. 


추가한 소스는 javax의 DatatypeConverter으로 xml의 데이터 변환에 사용되는 함수 입니다. 

해당 함수를 사용하면 기존의 byte->hex 변환 필요 없이 sha1의 데이터를 가져 올수 있습니다. 


- java간의 통신이라면 굳이 수정할 필요는 없습니다.

- 위의 방법을 쓰지 않으면 sha1의 키값에 따라 정상적으로 나올수도 아닐수도 있습니다. (결과값에서 byte->hex 변환시 달라질수 있기 때문입니다.)