2012-09-06 20 views
3

在我的Android應用程序中,我有一個SHA256散列,我必須進一步散列RIPEMD160消息摘要算法。無法在Java中輸出正確的散列。哪裏不對?

我可以輸出正確的SHA256和任何字符串的RIPEMD160哈希值,但是當我試圖用哈希我RIPEMD160得到一個哈希這是不正確的SHA256哈希值。

據網上散列運算,字符串 '測試'(全部小寫)的SHA256值:

9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 

和字符串 '測試' 的RIPEMD160值:

5e52fee47e6b070565f74372468cdc699de89107 

從根據網上Calcs(計算)散列所得散列SHA256與RIPEMD160的值是:

4efc1c36d3349189fb3486d2914f56e05d3e66f8 

和我的應用程序給我的是:

cebaa98c19807134434d107b0d3e5692a516ea66 

這顯然是錯誤的。

這裏是我的代碼:

public static String toRIPEMD160(String in) 
{ 
    byte[] addr = in.getBytes(); 
    byte[] out = new byte[20]; 
    RIPEMD160Digest digest = new RIPEMD160Digest(); 
    byte[] sha256 = sha256(addr); 
    digest.update(sha256,0,sha256.length); 
    digest.doFinal(out,0); 
    return getHexString(out); 
} 

public static byte[] sha256(byte[] data) 
{ 
    byte[] sha256 = new byte[32]; 
    try 
    { 
     sha256 = MessageDigest.getInstance("SHA-256").digest(data); 
    } 
    catch(NoSuchAlgorithmException e) 
    {} 

    return sha256; 
} 

對於RIPEMD160算法,你需要BouncyCastle的和java.security.MessageDigest中的SHA256。

回答

2

你的哈希工作正常。問題是,您使用的在線計算器的治療您的輸入:

9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 

而不是字節數組。換句話說,它將每個字符視爲一個字節,而不是將字符對解析爲十六進制的字節。如果我把這個作爲一個字符串網上計算器,我確實得到正是你得到了什麼:

4efc1c36d3349189fb3486d2914f56e05d3e66f8 

但是,你正在處理的輸出字節而不是一個String數組而這給你不同的結果。您應該將原始SHA256哈希編碼爲字符串,然後將編碼後的字符串傳遞給哈希函數。我看到你有一個getHexString方法,所以我們只是使用它。

public static String toRIPEMD160(String in) { 
    try { 
     byte[] addr = in.getBytes(); 
     byte[] out = new byte[20]; 
     RIPEMD160Digest digest = new RIPEMD160Digest(); 

     // These are the lines that changed 
     byte[] rawSha256 = sha256(addr); 
     String encodedSha256 = getHexString(rawSha256); 
     byte[] strBytes = encodedSha256.getBytes("UTF-8"); 
     digest.update(strBytes, 0, strBytes.length); 

     digest.doFinal(out, 0); 
     return getHexString(out); 
    } catch (UnsupportedEncodingException ex) { 
     // Never happens, everything supports UTF-8 
     return null; 
    } 
} 

如果你想知道它的工作,採取的encodedSha256值並將它放入一個在線散列運算單元。只要計算器使用UTF-8編碼將字符串轉換爲字節數組,它將匹配您的輸出。

+0

在這段代碼中,什麼是'base64Sha256'? – Dan

+1

@丹A錯字。它已被修復。 – Brian

7

你的「網上計算器」的結果是散列字符串「測試」與SHA-256的字節,轉換散列的結果爲十六進制的字符串,然後採取相應的是,ASCII字符的字節的結果十六進制字符串,並再次哈希那些。這與Java代碼非常不同,後者將第一個散列的字節直接傳遞給第二個散列,而不將它們打印爲十六進制,並將這些字符重新轉換爲中間的字節。值爲254(十進制)的單字節在十六進制中變爲「fe」,當轉換回字節時,變爲兩字節序列[0x66,0x65]。

1

要獲得byte[]打印版本消化使用此代碼:

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

,然後調用hexString.toString();