2011-04-10 4 views
0

내 서블릿이 HashMap과 해당 MD5 ​​해시를 암호화하여 전송합니다.
그런 다음 클라이언트는이를 수신하고 MD5를 HashMap에서 작동하는 것과 비교합니다.네트워크를 통해 전송 된 해시 맵의 무결성

이는 HashMap에 가끔 있지만 다른 예입니다 작동하는 경우 :이 있다면, 그러나

작동

HashMap<String, Object> result = new HashMap<String, Object>(); 
    result.put("error", 0); 
    result.put("coun", 0); 

: 그것은 작동하지 않습니다

HashMap<String, Object> result = new HashMap<String, Object>(); 
    result.put("error", 0); 
    result.put("count", 0); 

-은 두 MD5 해시가 다릅니다. (유일한 차이점은 'coun'대신 'count'가됩니다.)

프로그램이 비슷한 HashMaps를 전송합니다. 모두 문자열/정수형 키/값을 포함하고 있습니다. 이것은 처음으로 wierd와 비슷한 것을 보았습니다. 이. HashMap의가/MD5 실제로 전송되는의

세부 사항 -

서버가 수행합니다

//Work out MD5 of the HashMap result (convert it to bytes with objectOutputStream, and MD5 the bytes) 
    MessageDigest messageDigest = MessageDigest.getInstance("MD5"); 
    ByteArrayOutputStream bos = new ByteArrayOutputStream() ; 
    ObjectOutputStream out = new ObjectOutputStream(bos) ; 
    out.writeObject(result); 
    out.close(); 
    byte[] md5 = messageDigest.digest(bos.toByteArray(); 

    //Encrypt the httpURLConnection response stream, and send the HashMap result and the md5 over the stream 
    Cipher symmetricCipher = Cipher.getInstance("DES"); 
    symmetricCipher.init(Cipher.ENCRYPT_MODE, symmetricKey); 
    CipherOutputStream cipherOutput = new CipherOutputStream(response.getOutputStream(), symmetricCipher); 
    BufferedOutputStream bufferedOutput = new BufferedOutputStream(cipherOutput); 
    ObjectOutputStream objectOutput = new ObjectOutputStream(out); 
    objectOutput.writeObject(result); 
    objectOutput.writeObject(md5); 
    objectOutput.flush(); 

는 클라이언트가 수행합니다

//Decrypt the httpURLConnection response stream 
    Cipher symmetricCipher = Cipher.getInstance("DES"); 
    symmetricCipher.init(Cipher.DECRYPT_MODE, symmetricKey); 
    CipherInputStream cipherInput = new CipherInputStream(httpInput, symmetricCipher); 
    BufferedInputStream bufferedInput = new BufferedInputStream(cipherInput);   

    //read HashMap and MD5 
    ObjectInputStream objectInput = new ObjectInputStream(in); 
    HashMap<String, Object> result = (HashMap<String, Object>) objectInput.readObject(); 
    byte[] hash1 = (byte[]) objectInput.readObject(); 

    //workout hash of the Hashmap received. 
    MessageDigest messageDigest = MessageDigest.getInstance("MD5"); 
    ByteArrayOutputStream bos = new ByteArrayOutputStream() ; 
    ObjectOutputStream out = new ObjectOutputStream(bos) ; 
    out.writeObject(result); 
    out.close(); 
    byte[] hash2 = messageDigest.digest(bos.toByteArray(); 

    // Compare two hashes 
    if (!Arrays.equals(hash1, hash2)) { 
     System.out.println("Result received does not match hash, stopping list operation"); 
     return; 
    } 

가에는 InputStream의 동일한 유형을 사용하여 암호를 해독, 밖으로 작동 hashmap의 md5를 같은 방법으로 비교 한 다음 사용하여 비교합니다.

if (!Arrays.equals(hash1, hash2)) { 
      System.out.println("Result received does not match hash, stopping get operation"); 
      return; 
    } 

내가 해봤 던 모든 HashMaps를 보내는 데 이것이 효과가 있었지만 지금은이 카운트 키로는 작동하지 않는 이유를 알지 못합니다. 클라이언트와 서블릿의 HashMap 내부에있는 개별 키/값 쌍을 비교하여 테스트 해봤는데 그 값은 동일하지만 전체 HashMap의 두 MD5를 비교할 때 일치하지 않습니다.

또한 스트림 체인의 올바른 부분에서 버퍼링 된 스트림을 사용하고 있는지 확실하지 않습니다.

+0

"두 개의 MD5 해시가 다릅니다"라고 말하면 두 MD5 해시가 여기서 말하고 있습니까, 구체적으로 *? –

답변

0

Java 사본 두 개가 객체의 직렬화와 정확히 동일한 바이트를 생성한다는 보장은 없으며 의미 론적으로 동일한 객체 만 생성합니다.

키와 값에 대한 다이제스트를 실행하여이 작업을 만들 수 있지만 Object 값을 해시하는 방법을 결정해야합니다.

XML로 렌더링하고이를 표준화 할 수 있다면 거기에서 갈 수 있습니다.

자신의 웹 서비스를 롤링하는 대신 보안을 위해 다양한 웹 서비스 표준을 살펴볼 수 있습니다.

제안 : 해시 맵을 순서가있는 TreeMap으로 복사하고 동일한 트릭을 시도하십시오.

+0

thx, 방금 보증이 있다고 가정했는데, 지금까지는 다른 해시 맵을 많이 사용 했었습니다. 정수와 문자열 만 포함했기 때문에 괜찮 았을 것입니다. 왜이 특정 해시 맵이 작동을 멈추게하는지 알았습니다. 에 대한? 내 자신을 롤백해야한다. 할당을 위해 – twisted

+0

보장되지 않는다.지도가 정의되지 않은 순서로 걷고있다. – bmargulies

+0

ok는 treemap을 시도 할 것이고, 그렇지 않으면 직렬화 된 바이트가 아니라 hashmap에서 MD5를 사용할 것입니다. 고마워요. – twisted

관련 문제