Cannot output correct hash in Java. What is wrong?

本秂侑毒 提交于 2019-12-21 02:45:25

问题


In my Android app I have a SHA256 hash which I must further hash with the RIPEMD160 message digest algorithm.

I can output the correct sha256 and ripemd160 hash of any string, but when I try to hash the sha256 hash with ripemd160 I get a hash which is incorrect.

According to online hash calculators, the SHA256 value of the string 'test'(all lowercase) is:

9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08

And the RIPEMD160 value of the string 'test' is:

5e52fee47e6b070565f74372468cdc699de89107

The value from hashing the resulting sha256 hash with ripemd160 according to online calcs is:

4efc1c36d3349189fb3486d2914f56e05d3e66f8

And the one my app gives me is:

cebaa98c19807134434d107b0d3e5692a516ea66

which is obviously wrong.

Here is my code:

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;
}

For the ripemd160 algorithm, you need bouncycastle and java.security.MessageDigest for sha256.


回答1:


Your hash is working fine. The problem is that the online calculators that you're using are treating your input:

9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08

as a string instead of an array of bytes. In other words, it's treating each character as a byte instead of parsing character pairs as bytes in hexadecimal. If I give this as a string to online calculators, I indeed get exactly what you got:

4efc1c36d3349189fb3486d2914f56e05d3e66f8

However, you're treating the output as an array of bytes instead of a String and that's giving you different results. You should encode your raw SHA256 hash as a string, then pass the encoded string to the hash function. I see you have a getHexString method, so we'll just use that.

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;
    }
}

If you want to know it's working, take the value of encodedSha256 and put that into an online hash calculator. As long as the calculator uses UTF-8 encoding to turn the string into a byte array, it will match your output.




回答2:


Your "online calculator" result is the result of hashing the bytes of the string "test" with SHA-256, converting the result of that hash to a hex string, then taking the bytes corresponding to the ASCII characters of that hex string and hashing those a second time. This is very different from your Java code, which passes the bytes that come out of the first hash directly to the second one, without printing them as hex and turning those characters back into bytes in between. The single byte with value 254 (decimal) becomes "fe" in hex, which becomes the two-byte sequence [0x66, 0x65] when converted back to bytes.




回答3:


To get printable version of byte[] digest use this code:

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

and then call hexString.toString();



来源:https://stackoverflow.com/questions/12303567/cannot-output-correct-hash-in-java-what-is-wrong

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!