2012-09-06 34 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();