无法在Java中输出正确的哈希值。 哪里不对?

在我的Android应用程序中,我有一个SHA256哈希值,我必须使用RIPEMD160消息摘要算法进一步哈希。

我可以输出任何字符串的正确sha256和ripemd160哈希,但是当我尝试使用ripemd160散列sha256哈希时,我得到一个不正确的哈希值。

根据在线哈希计算器,字符串’test’(全部小写)的SHA256值为:

9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 

字符串’test’的RIPEMD160值为:

 5e52fee47e6b070565f74372468cdc699de89107 

根据在线计算,使用ripemd160散列生成的sha256哈希的值为:

 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算法,sha256需要bouncycastle和java.security.MessageDigest。

你的哈希工作正常。 问题是你正在使用的在线计算器正在处理你的输入:

 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 

作为字符串而不是字节数组。 换句话说,它将每个字符视为一个字节,而不是将字符对解析为hex的字节。 如果我把它作为一个字符串给在线计算器,我确实得到你所得到的:

 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 ,可以使用encodedSha256的值并将其放入在线哈希计算器中。 只要计算器使用UTF-8编码将字符串转换为字节数组,它就会匹配您的输出。

您的“在线计算器”结果是使用SHA-256对字符串“test”的字节进行散列,将该散列的结果转换为hex字符串,然后获取与该hex字符串的ASCII字符对应的字节并进行散列的结果那是第二次。 这与您的Java代码非常不同,后者将第一个哈希中的字节直接传递给第二个哈希,而不将它们打印为hex,并将这些字符转换回其间的字节。 值为254(十进制)的单字节变为hex的“fe”,当转换回字节时,变为双字节序列[0x66,0x65]。

要获取byte[]摘要的可打印版本,请使用以下代码:

 StringBuffer hexString = new StringBuffer(); for (int i=0;i 

然后调用hexString.toString();