2011-04-10 65 views
0

我的servlet加密併發送HashMap及其MD5散列。
然後客戶端接收它們,並將MD5與其從HashMap中找出的MD5進行比較。通過網絡發送的散列映射的完整性

這有時有效,但不是別人,例如,如果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哈希值是不同的。 (唯一不同的是「count」而不是'coun')

該程序發送類似的HashMaps,所有包含的鍵/值只是字符串或整數,這是我第一次看到類似奇怪的東西這個。如何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; 
    } 

解密使用相同類型的inputStreams,作品出來hashmap的md5以相同的方式,然後使用比較:

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

我不明白爲什麼這對發送所有我試過的HashMaps都有效,但現在不能用這個數字鍵。 我測試過比較客戶端和servlet中HashMap內部的各個鍵/值對,它們是相同的,但是當比較整個HashMap中的兩個MD5時,它們不匹配。

此外,我不知道我在流鏈的正確部分使用緩衝流嗎?

+0

你說「兩個MD5哈希值是不同的」,你在說這兩個MD5哈希值,特別是*? – 2011-04-10 19:10:56

回答

0

不能保證兩個Java副本將產生與對象序列化完全相同的字節 - 只是它們會產生語義等同的對象。

您可以通過在鍵和值上運行摘要來做類似這樣的工作,但是您需要決定如何對Object值進行散列。

如果你可以渲染到XML,並將其規範化,那麼你可以從那裏去。

您可以查看各種Web服務標準的安全性,而不是滾動自己的。

建議:將哈希映射覆制到一個具有順序的TreeMap中,並嘗試使用它。

+0

thx,只是假設有一個保證,因爲它一直工作到很多不同的hashmaps,直到現在罰款 - 認爲這是好的,因爲他們只包含整數和字符串...任何想法爲什麼這個特定的hashmap是它停止工作對於?必須推出我自己的,它的任務 – twisted 2011-04-10 19:12:41

+0

不能保證,它是以未定義的順序走地圖。 – bmargulies 2011-04-10 19:15:47

+0

好吧會嘗試treemap,否則我只會在散列表中的東西,而不是序列化的字節...感謝 – twisted 2011-04-10 19:24:48