Какой SHA-256 правильный?Дайджест Java SHA-256 или инструмент командной строки Linux - PullRequest
24 голосов
/ 11 июня 2010

Когда я вычисляю в Java SHA-256 строки следующим методом

public static void main(String[] args) throws NoSuchAlgorithmException {

    MessageDigest md = MessageDigest.getInstance("SHA-256");

    byte[] hash = md.digest("password".getBytes());

    StringBuffer sb = new StringBuffer();
    for(byte b : hash) {
        sb.append(Integer.toHexString(b & 0xff));
    }

    System.out.println(sb.toString());
}

, я получаю:

5e884898da2847151d0e56f8dc6292773603dd6aabbdd62a11ef721d1542d8

в командной строке я делаю следующее (мне нужно-n, чтобы не добавлять новую строку):

echo -n "password" | sha256sum

и получить

5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8

, если мы сравним их более близко, я найду 2 тонкие различия

5e884898da2847151d0e56f8dc6292773603dd6aabbdd62a11ef721d1542d8
5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8

или:

5e884898da28   47151d0e56f8dc6292773603d   d6aabbdd62a11ef721d1542d8
5e884898da28 0 47151d0e56f8dc6292773603d 0 d6aabbdd62a11ef721d1542d8

Какая из 2 верна здесь?

Результат: И то и другое, но я ошибался ...

исправленоэто с помощью:

    StringBuffer sb = new StringBuffer();
    for(byte b : hash) {
        sb.append(String.format("%02x", b));
    }

Спасибо!

Ответы [ 7 ]

28 голосов
/ 11 июня 2010

Я сделаю разумное предположение: оба выводят один и тот же дайджест, но в вашем Java-коде, который выводит результат byte[] в виде шестнадцатеричной строки, вы выводите небольшие байтовые значения (меньше 16) без начального 0. Таким образом, байт со значением «0x0d» записывается как «d», а не «0d».

10 голосов
/ 11 июня 2010

Виновником является toHexString. Кажется, он выводит 6 для значения 6, тогда как sha256sum единица выводит 06. Документы Java для Integer.toHexString() состояния:

Это значение преобразуется в строку цифр ASCII в шестнадцатеричном формате (основание 16) без лишних начальных 0.

Другие нули в строке не затрагиваются, так как они являются второй половиной байтов (например, 30).

Один из способов исправить это было бы изменить:

for(byte b : hash) {
    sb.append(Integer.toHexString(b & 0xff));
}

до:

for(byte b : hash) {
    if (b < 16) sb.append("0");
    sb.append(Integer.toHexString(b & 0xff));
}
7 голосов
/ 11 июня 2010

Они оба правы - виноват ваш Java-код, потому что он не печатает ведущий 0 для шестнадцатеричного значения меньше 0x10.

4 голосов
/ 15 октября 2011

Вам все еще нужен "echo -n", чтобы предотвратить трейлинг \ n

2 голосов
/ 11 июня 2010

Сгенерированный sha256sum кажется правильным. Кажется, ваша реализация отбрасывает эти два нуля.

1 голос
/ 16 ноября 2011

При использовании идеи @paxdiablo возникла проблема с большим числом, поскольку оно выглядит как отрицательное, поэтому

Вместо:

for(byte b : hash) {
    sb.append(Integer.toHexString(b & 0xff));
}

вы можете сделать:

for(byte b : hash) {
    if (b > 0 && b < 16) {
        sb.append("0");
    }
    sb.append(Integer.toHexString(b & 0xff));
}

И прочитайте @ Шон Оуэн ответ.

0 голосов
/ 18 апреля 2013

Вы также можете получить правильный результат, используя это:

MessageDigest md = MessageDigest.getInstance("SHA-256");

byte[] hash = md.digest("password".getBytes());

BigInteger bI = new BigInteger(1, hash);

System.out.println(bI.toString(16));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...