0

次のコードを使用してアプリケーションの MD5 ハッシュを生成し、文字列値をエンコードしてから、この生成されたハッシュを Web サービスを介して .Net コードに送信します。そのコードは MD5 ハッシュを読み取り、文字列の MD5 を生成します。 DBから取得して比較する

public static String getMD5Hash(String val) throws Exception {
        byte[] bytes = val.getBytes();

        MessageDigest m = MessageDigest.getInstance("MD5");
        byte[] digest = m.digest(bytes);
        String hash = new BigInteger(1, digest).toString(16);
        System.out.println(hash.length());
        return hash;
    }

    public static void main(String[] asd) throws Exception{
        for(int i=0;i<10;i++){
            System.out.println(getMD5Hash(i+Math.pow(10, i)+""));//for testing
            System.out.println(getMD5Hash(i+""));//for testing
        }
    }

問題は、BigInteger から変換されたハッシュを取得していて、生成されたハッシュが 0 で始まる場合があるためです。このように、文字列比較は false を返します。たとえば、ハッシュ コードを生成して送信する " 102678D1922799CF9122B3F103975F1" ここで、.Net ハッシュは " 0102678D1922799CF9122B3F103975F1"です。

また、次のようなコードを生成する場合もあります

.Net generates  0012678D1922799CF9122B3F103975F1 and java 12678D1922799CF9122B3F103975F1 

また

0002678D1922799CF9122B3F103975F1 and 2678D1922799CF9122B3F103975F1

先頭がすべて 0 のこのコードを取得するにはどうすればよいですか。前もって感謝します。

4

2 に答える 2

4

MessageDigest文字列をパディングするよりも良い方法はないと思います:

// ...
StringBuilder builder = new StringBuilder();
for (int i = hash.length(); i < 64; i++) {
  builder.append('0');
}
builder.append(hash);
return builder.toString();

...しかし、 Guavaを使用できますStrings.padStart():

// ...
return Strings.padStart(hash, 64, '0');

...または、関数とまったく同じ文字列を返すGuava のハッシュ ライブラリを使用することもできます (チェックしたところです):

public static String getMD5Hash(String val) throws Exception {
  return Hashing.md5().hashBytes(val.getBytes()).toString();
}
于 2012-11-02T05:49:59.880 に答える
3

この質問には、16進文字列を生成するためのより良い方法がいくつかあります。

Java で、先行ゼロを維持しながらバイト配列を 16 進数の文字列に変換するにはどうすればよいですか?

あなたはすでに を使用しているのでBigInteger、これが最善の解決策のようです:

BigInteger bi = new BigInteger(1, digest);
String hash = String.format("%0" + (digest.length << 1) + "X", bi);
于 2012-11-02T18:40:20.753 に答える