web-dev-qa-db-ja.com

弾む城を使用してJavaでSHA512ダイジェスト文字列を作成するにはどうすればよいですか?

この単体テストは失敗しています:

    public void testDigest() throws NoSuchAlgorithmException {
    String hashExpected = "150a14ed5bea6cc731cf86c41566ac427a8db48ef1b9fd626664b3bfbb99071fa4c922f33dde38719b8c8354e2b7ab9d77e0e67fc12843920a712e73d558e197";
    MessageDigest md = new MessageDigest();
    String hashActual = new String(md.digest("hi"));
    Assert.assertEquals(hashExpected, hashActual);
}

以下は、MessageDigestクラスの実装です。


import Java.io.IOException;
import Java.io.InputStream;
import Java.security.NoSuchAlgorithmException;
import Java.security.Security;


import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.digests.SHA512Digest; import org.bouncycastle.crypto.io.DigestInputStream; import org.bouncycastle.jce.provider.BouncyCastleProvider;


public class MessageDigest { private Digest messageDigest;

public MessageDigest() throws NoSuchAlgorithmException {
    Security.addProvider(new BouncyCastleProvider());
    messageDigest = new SHA512Digest();
}

public byte[] digest(String message) {
    byte[] retValue = new byte[messageDigest.getDigestSize()];
    messageDigest.update(message.getBytes(), 0, message.length());
    messageDigest.doFinal(retValue, 0);
    return retValue;
}
</ code>

}

テストは次の理由で失敗します。


junit.framework.ComparisonFailure: expected:<150a14ed5bea6cc731cf86c41566ac427a8db48ef1b9fd626664b3bfbb99071fa4c922f33dde38719b8c8354e2b7ab9d77e0e67fc12843920a712e73d558e197> but was:<
í[êlÇ1φÄf¬Bz�´Žñ¹ýbfd³¿»™¤É"ó=Þ8q›ŒƒTâ·«�wàæÁ(C’
q.sÕXá

Byte []ダイジェストを文字列に変換するときに、正しいエンコードスキームを使用していないように感じます。どんな助けでもいただければ幸いです。

11
Lee Warner

期待する値は、16進エンコードされた値です。生のバイトに基づいて文字列を作成していますが、これは機能しません。

BouncyCastle固有のAPIの代わりに、可能な限り標準のJava CryptoAPIを使用する必要があります。

次のことを試してください(Hexライブラリは commons-codec から来ています):

Security.addProvider(new BouncyCastleProvider());

String data = "hello world";

MessageDigest mda = MessageDigest.getInstance("SHA-512", "BC");
byte [] digesta = mda.digest(data.getBytes());

MessageDigest mdb = MessageDigest.getInstance("SHA-512", "BC");
byte [] digestb = mdb.digest(data.getBytes());

System.out.println(MessageDigest.isEqual(digesta, digestb));

System.out.println(Hex.encodeHex(digesta));
34
Kevin

Kevinの答えへの単なる追加:Java 5なので、commons-codecの代わりにString.format("%0128x", new BigInteger(1, digesta))を使用して、バイト配列を先行ゼロ付きの128桁の16進数でエンコードされた数値としてフォーマットできます。 。

22
jarnbjo

はい、バイト配列を16進文字列に変換する必要があります。 :-) Apache Commons Codec 、特に Hex クラスを調べてください。

3

BouncyCastle 1.49以降、toHexStringクラスには少数のHexメソッドがあります。例えば:

Hex.toHexString(digest);

ハッシュダイジェストをJava Stringとして16進形式で返します。

参考までに、 BouncyCastle javadoc または grepcode を参照してください。

2
Diego