如何使用充气城堡在Java中创建SHA512摘要字符串?

Lee*_*ner 11 java hash bouncycastle sha512

此单元测试失败:

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

下面是我的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;
}
Run Code Online (Sandbox Code Playgroud)

}

测试失败,原因如下:


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

当我将byte []摘要转换为字符串时,我感觉我没有使用正确的编码方案.任何帮助,将不胜感激.

Kev*_*vin 34

您期望的值是十六进制编码的值.您正在根据原始字节创建一个字符串,这将无法正常工作.

您应尽可能使用标准Java Crypto API而不是BouncyCastle特定API.

尝试以下(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));
Run Code Online (Sandbox Code Playgroud)

  • 它们并不完全等同.Arrays.equals方法认为两个空引用相等,而MessageDigest.isEqual方法会抛出NullPointerException. (2认同)

jar*_*bjo 22

只是对Kevin的回答的补充:从Java 5开始,您可以使用String.format("%0128x", new BigInteger(1, digesta))commons-codec来将字节数组格式化为带有前导零的128位十六进制编码数字.