4

私のAndroidアプリには、SHA256ハッシュがあり、RIPEMD160メッセージダイジェストアルゴリズムでさらにハッシュする必要があります。

任意の文字列の正しいsha256およびripemd160ハッシュを出力できますが、sha256ハッシュをripemd160でハッシュしようとすると、正しくないハッシュが取得されます。

オンラインハッシュ計算機によると、文字列'test'(すべて小文字)のSHA256値は次のとおりです。

9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08

また、文字列'test'のRIPEMD160値は次のとおりです。

5e52fee47e6b070565f74372468cdc699de89107

オンライン計算に従って、結果の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アルゴリズムの場合、sha256にはbouncycastleとjava.security.MessageDigestが必要です。

4

3 に答える 3

8

「オンライン計算機」の結果は、文字列「test」のバイトをSHA-256でハッシュし、そのハッシュの結果を16進文字列に変換してから、その16進文字列のASCII文字に対応するバイトを取得してハッシュした結果です。それらをもう一度。これは、最初のハッシュから出力されたバイトを16進数として出力したり、それらの文字をその間のバイトに戻したりせずに、2番目のハッシュに直接渡すJavaコードとは大きく異なります。値254(10進数)の1バイトは16進数で "fe"になり、バイトに変換して戻すと2バイトシーケンス[0x66、0x65]になります。

于 2012-09-06T15:42:07.010 に答える
4

ハッシュは正常に機能しています。問題は、使用しているオンライン計算機が入力を処理していることです。

9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08

バイトの配列ではなく文字列として。つまり、文字ペアを16進数のバイトとして解析するのではなく、各文字を1バイトとして処理します。これをオンライン計算機に文字列として与えると、実際にあなたが得たものを正確に得ることができます。

4efc1c36d3349189fb3486d2914f56e05d3e66f8

ただし、出力をaではなくバイトの配列として扱っているため、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エンコーディングを使用して文字列をバイト配列に変換する限り、出力と一致します。

于 2012-09-06T16:13:20.000 に答える
1

印刷可能なバージョンのbyte[]ダイジェストを取得するには、次のコードを使用します。

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

その後、電話しますhexString.toString();

于 2012-09-06T16:07:47.100 に答える