2012-12-18 53 views
4

我有計算字符串SHA-256哈希的代碼,並且注意到我從Android和Oracle Java 7獲得了不同的哈希以獲得相同的字符串。我的散列碼轉換成Stringbyte[]使用Android和Oracle進行字符串字符編碼Java

byte[] data = stringData.getBytes("UTF-16"); 

使用UTF-16編碼,我從甲骨文的Java和Android的Java不同的結果。這是我散列字符串:

// Test Code: 
String toHash = "testdata"; 
System.out.println("Hash: " +DataHash.getHashString(toHash)); 

並獲得論文哈希使用UTF-16:

Hash: a1112a0363a59097a701e38398e1fdfef3049358aee81b77ecaad2924a426bc5 [Oracle Java 7] 
Hash: 811b723aee07c7a52456fc57a5683e73649075a373d341f7257bf73575111ba3 [Android 2.2] 

然而,UTF-8,我得到了相同的散列兩者的JRE:

Hash: 810ff2fb242a5dee4220f2cb0e6a519891fb67f2f828a6cab4ef8894633b1f50 [Oracle Java 7] 
Hash: 810ff2fb242a5dee4220f2cb0e6a519891fb67f2f828a6cab4ef8894633b1f50 [Android 2.2] 

是否存在某種類型的endian-ness問題,這會導致不同平臺上的不同結果?我應該如何真正準備一個字符串以獨立於平臺的方式進行散列?

編輯: 哎呀,答案是相當明顯的,一旦你讀了關於UTF-16多一點。有兩種版本的UTF-16(大端和小端)。你只需要指定getBytes()應該使用哪個版本,並且散列值是相同的。挑一個:

  • UTF-16LE
  • UTF-16BE

回答

1

按照documentation of Orcale Java

解碼時,UTF-16字符集解釋一個字節順序標記到 指示流但默認爲大端的字節順序如果 沒有字節順序標記編碼時,它使用大端字節 命令並寫入一個大端字節順序標記。

這意味着普通UTF-16應該始終以Oracle Java中的Big Endian編碼。

然後從Android Java documentation

Charset   Encoder writes 
UTF-16BE   BE, no BOM 
UTF-16LE   LE, no BOM 
UTF-16    BE, with BE BOM 

所以在任何一個錯誤,或者文檔。兩者都必須是Big Endian,並寫入BOM,所以應該沒有任何區別。

一般而言,您應該更喜歡UTF-16BE/LE而不是UTF-16,但在這種情況下,它似乎是一個錯誤。

+0

啊,有趣。它看起來像Android(2。2至少)正在進行小端轉換: Oracle Java 7: 「UTF-16:[-2,-1,0,116,0,101,0,115,0,116,0,100 ,0,97,0,116,0,97]' Android Java 2.2: 'UTF-16:[-1,-2,116,0,101,0,115,0,116,0,100 ,0,97,0,116,0,97,0]' –

+0

@TajMorton'-1,-2,116,0..'是Little Endian,帶有LE BOM。這是從Android?無論如何,它顯然與Android文檔相矛盾。 – Esailija

+0

對不起,我的格式化已被破壞,並在我準備好之前意外發布。 Oracle Java 7爲'[-2,-1,0,116]'提供了「UTF-16」,而Android 2.2提供了'[-2,-1,116,0]'。所以是的,它看起來像是用LE BOM生產LE。 –

0

顯示你的哈希代碼,但它可能是做錯了什麼。哈希結果是byte[],所以不需要首先將字符串轉換爲byte[]。要將二進制散列值轉換爲String,請使用Base64或十六進制編碼。