2014-08-27 4 views
0

나는 이것에 대해 질문이 있습니다.동일한 값에 대해 클라이언트와 서버에서 서로 다른 sha가 계산되었습니다.

Java로 소켓을 통해 통신하는 두 개의 프로그램, 클라이언트와 서버를 만들었습니다. 이제 서버 소켓의 InputStream에서 객체를받을 때 SHA384를 받아 클라이언트에서 계산 한 SHA384와 동일한 값인지 확인해야합니다. 수신 된 값이 전송 된 값과 같음을 디버그 모드에서 확인했지만이 값의 SHA384를 사용하면 클라이언트와 다른 해시를 얻습니다.

왜? 클라이언트는 안드로이드 응용 프로그램이며 서버 측은 단순한 Java입니다. Strings를 들어, 시스템의 디폴트 캐릭터 세트를 사용 getBytes()에 의존 :

내가 해시

public enum SECURE_HASH_TYPE{MD2, MD5, SHA, SHA256, SHA384, SHA512} 

private static String SecureHashToString(SECURE_HASH_TYPE hash){ 

    String hashString = "SHA-256";        //default value 

    if(hash != null){ 
     switch(hash){ 
      case MD2: 
       hashString = "MD2"; 
       break; 

      case MD5: 
       hashString = "MD5"; 
       break; 

      case SHA: 
       hashString = "SHA"; 
       break; 

      case SHA256: 
       hashString = "SHA-256"; 
       break; 

      case SHA384: 
       hashString = "SHA-384"; 
       break; 

      case SHA512: 
       hashString = "SHA-512"; 
       break; 

      default: 
       hashString = "SHA-512"; 
       break; 
     } 
    } 

    return hashString; 
} 



public static byte[] getByteHashCode(Object obj, SECURE_HASH_TYPE hashing){ 
    if(obj == null) 
     return null; 

    MessageDigest md; 
    byte[] byteData = null; 

    try { 
     md = MessageDigest.getInstance(SecureHashToString(hashing)); 

     md.update(ObjectUtil.toByteArray(obj)); 

     byteData = md.digest(); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } 

    return byteData; 
} 


public static byte[] toByteArray(Object obj){ 
    if(obj == null) 
     return null; 

    if(obj instanceof String) 
     return ((String)obj).getBytes(); 

    ByteArrayOutputStream baos = null; 
    ObjectOutputStream oos = null; 
    byte[] byte_array = null; 

    try{ 
     baos = new ByteArrayOutputStream(); 
     oos = new ObjectOutputStream(baos); 

     oos.writeObject(obj); 
     byte_array = baos.toByteArray(); 

     baos.close(); 
     oos.close(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    return byte_array; 
} 
+0

해시가 다른 경우 텍스트가 다르고 이야기가 끝납니다. 동일한 문자 세트, 인코딩을 사용하고 있는지 확인하고 그 패딩은 동일합니다 ... – ircmaxell

+0

텍스트가 동일합니다. 나는 그것을 검사했다. 동일한 텍스트는 클라이언트 및 서버 측의 BigInteger입니다. – Giulio

+0

* 텍스트 *는 같을 수 있지만 동일한 바이트를 전달하는 바이트입니까? 의미가 100 % 긍정적인가? 다르게 인코딩하지 않습니까? 아니면 하나의 후행 null 바이트, 또는 그런 ...? – ircmaxell

답변

3

에게 사소한 문제를 만들 호출하는 기능입니다. 클라이언트와 서버가 다른 기본 문자 집합을 사용하면 결과가 달라질 수 있습니다.

return ((String) obj).getBytes('UTF-8'); 

을하지만 큰 문제는 아닌 문자열에 대한 바이트 시퀀스를 만들 수 ObjectOutputStream.writeObject()를 사용한다는 것입니다 : 대신 적절한 캐릭터 세트의 이름을 지정 getBytes(String)를 사용해야합니다. 그러한 객체가 몇 가지 관련성이있는 의미에서 동등하더라도, 두 개의 다른 객체에 적용될 때 그 메소드가 byte-for-byte 동일한 바이트 시퀀스를 산출 할 것으로 기대하는 특별한 이유는 없습니다. 일부 클래스의 객체에 대한 결과를 얻을 수도 있지만 인스턴스가 해당 속성을 갖지 않는 클래스를 작성할 수는 있습니다.

아, 그리고 Serializable이 아닌 개체를 전달하면 메서드가 중단됩니다.

당신이 시도하고있는 일반 수준에서 시도하고있는 것을 어떤 방법으로할지 모르겠습니다.

+0

이 문제에 대한 내 자신의 접근 방식은 모델/개체의 JSON 직렬화에 사용되는 주석 된 인터페이스이며 Java 개체 대신 해당 문자열로 작업합니다. 키 정의 순서가 유지되면 (일반적으로 JSON에서는 기본적으로 사용되지 않음) toJson() 문자열을 동일하게 사용할 수 있으므로 해시를 사용해야합니다. 이는 구현 모델을 수정/버전/확장 할 수 있지만 JSON 직렬화 출력과 해시를 사용하고 유지 관리하고 테스트하고 의존 할 수 있다는 것을 의미합니다. 예상되는 키가 항상 존재하며 널 (null) 유형 값을 일관되게 처리해야합니다. – indivisible