Как я могу создать строку дайджеста SHA512 в Java, используя надувной замок? - PullRequest
11 голосов
/ 05 февраля 2010

Этот модульный тест не пройден:

    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;</p>

<p>import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA512Digest;
import org.bouncycastle.crypto.io.DigestInputStream;
import org.bouncycastle.jce.provider.BouncyCastleProvider;</p>

<p>public class MessageDigest {
    private Digest messageDigest;</p>

<pre><code>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á

У меня такое ощущение, что я не использую правильную схему кодирования, когда преобразую свой байт [] в дайджест. Любая помощь будет оценена.

Ответы [ 4 ]

34 голосов
/ 05 февраля 2010

Ожидаемое значение является шестнадцатеричным значением. Вы создаете строку на основе необработанных байтов, которая не будет работать.

Вы должны по возможности использовать стандартный Java Crypto API вместо специфических API BouncyCastle.

Попробуйте следующее (библиотека 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));
22 голосов
/ 05 февраля 2010

Просто дополнение к ответу Кевина: Начиная с Java 5, вы можете использовать String.format("%0128x", new BigInteger(1, digesta)) вместо commons-codec для форматирования массива байтов в виде 128-значного шестнадцатеричного кода с начальными нулями.

3 голосов
/ 05 февраля 2010

Да, вам нужно превратить ваш байтовый массив в шестнадцатеричную строку. :-) Изучите кодек Apache Commons , особенно класс Hex .

2 голосов
/ 06 февраля 2014

Начиная с BouncyCastle 1.49, есть класс toHexString в классе Hex. Например:

Hex.toHexString(digest);

вернет вам хэш-дайджест в виде Java String в шестнадцатеричном формате.

Для справки см. BouncyCastle javadoc или grepcode .

...