Cannot output correct hash in Java. What is wrong?

前端 未结 3 1092
忘掉有多难
忘掉有多难 2021-02-10 21:00

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 s

相关标签:
3条回答
  • 2021-02-10 21:10

    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();

    0 讨论(0)
  • 2021-02-10 21:16

    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.

    0 讨论(0)
  • 2021-02-10 21:29

    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.

    0 讨论(0)
提交回复
热议问题