2015-08-15 75 views
2

我想比較來自同一文件的MD5哈希。該文件通過來自Android的HTTP POST被髮送爲byte [],在那裏我還計算散列並從.NET服務器接收,在那裏我再次計算散列,然後想要比較它們。Java和C之間的不同MD5#

的問題是,對於同一個文件,我得到不同的散列...

Java代碼

FileInputStream fileInputStream = null; 

byte[] bFile = new byte[(int) file.length()]; 

try { 

    fileInputStream = new FileInputStream(file); 
    fileInputStream.read(bFile); 

} catch (Exception e) { 
    e.printStackTrace(); 
} 

try { 
    MessageDigest md = MessageDigest.getInstance("MD5"); 

    int read = 0; 
    while((read = fileInputStream.read(bFile)) != -1) { 
     md.update(bFile, 0, read); 
    } 
    fileInputStream.close(); 

    byte[] mdBytes = md.digest(); 

    StringBuffer sb = new StringBuffer(); 
    for(int i=0; i < mdBytes.length; ++i) { 
     sb.append(Integer.toString((mdBytes[i] & 0xff) + 0x100, 16).substring(1)); 
    } 

    // generated MD5 is d41d8cd98f00b204e9800998ecf8427e 


} catch (NoSuchAlgorithmException e) { 
    e.printStackTrace(); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 

C#代碼

using (var md5 = MD5.Create()) 
{ 
    using (var stream = File.OpenRead(filePath)) 
    { 
     string hexString = ToHex(md5.ComputeHash(stream), false); 

     // Generated MD5 is d167df114a478809ef71fb7e10c40f8c 
    } 
} 

public string ToHex(byte[] bytes, bool upperCase) 
{ 
    StringBuilder result = new StringBuilder(bytes.Length * 2); 

    for (int i = 0; i < bytes.Length; i++) 
     result.Append(bytes[i].ToString(upperCase ? "X2" : "x2")); 

    return result.ToString(); 
} 

UPDATE

我試着將Java代碼更改爲

StringBuffer sb = new StringBuffer(); 
for(int i=0; i < mdBytes.length; ++i) { 
    sb.append(String.format("%02x", mdBytes[i])); 
} 

結果總是一樣的...

+2

我認爲這個問題依賴於對數值進行加密,而不是獲取MD5。 –

+0

也這麼認爲......但無法弄清楚錯誤在哪裏 –

+0

爲什麼你用不同的方式來獲取HEX字符串?我不知道該代碼中發生了什麼:'sb.append(Integer.toString((mdBytes [i]&0xff)+ 0x100,16).substring(1));' –

回答

3

在你讀取文件流後,你必須尋求回到爲了正確計算散列值而開始流。

+0

Java不允許在彼此之上嵌套流?例如,.Net肯定會這樣做,所以人們只能讀取一次文件流,同時通過散列器進行讀取。它不僅具有性能優勢(文件不必被讀取兩次),並且允許處理不可查找的流(如網絡),但也更靈活且容易出錯。 –

3

首先採取的許多免費提供的工具來計算MD5哈希一個(或多個)減半你的工作,看看是否你的C#或Java代碼是正確的(也許都是錯的,好的:-))。

然後我們會看到。

更新:

在你將數據讀入一個字節數組Java中的情況;之後你使用的是同一個流(已經是EOF),因此永遠不會調用md.update

更新2:

所以,寫

[...] 
MessageDigest md = MessageDigest.getInstance("MD5"); 
md.update(bFile, 0 , bFile.length); 
byte[] mdBytes = md.digest(); 
[...] 

和你的基本上都是精品。順便說一句,有趣的技術將字節數組轉換爲十六進制字符串... :-)你可能想要尋找一個更好的方法,雖然...

+0

我試過從http://www.fileformat.info/tool/hash.htm和哈希從兩個文件(服務器和客戶端)是一樣的...所以絕對算法錯誤 –

+0

哦,有一個誤解。我打算使用外部MD5工具來檢查你的兩個*實現*的結果,並確定至少有一個是否有效。不要在傳輸時檢查文件是否損壞。更具體一點,請檢查代碼註釋中提到的兩個MD5。 – Hille

+0

c#其中一個是正確的 –

相關問題