SHA1 Java и Python не совпадают - PullRequest
0 голосов
/ 01 декабря 2018

Мне нужно перевести часть Python на Java, но когда я делаю хэш SHA, у меня не такой результат, как у Python, появляется строка:

$&).6CXzPHw=2N_+isZK2908069825

// Java code

private static byte[] getSHA1(byte[] input) throws NoSuchAlgorithmException {
    MessageDigest msdDigest = MessageDigest.getInstance("SHA-1");
    msdDigest.reset();
    msdDigest.update(input, 0, input.length);
    System.out.println(DatatypeConverter.printHexBinary((msdDigest.digest())));
    return msdDigest.digest();
}

// Python Code

print(sha1(prefix + str(num4).encode('ascii')).digest())

Может быть, разница между типами байтов ??Есть идеи ?Спасибо

Ответы [ 2 ]

0 голосов
/ 01 декабря 2018

Криптографическая архитектура Java Объекты, которые представляют типы алгоритмов, такие как MessageDigest, но также Cipher и Mac, все реализуют схему, которая позволяет выполнять частичные операции с большими объемами данных.Они делают это с помощью методов, обновляющих внутреннего состояния и конечных операций, таких как sign / verify или - для MessageDigest - единственной операции с именем digest с различными перегрузками.

ЭтиОбщим для алгоритмов также является то, что состояние объекта сбрасывается в состояние непосредственно после инициализации, когда вызывается «конечная» операция.Это состояние обычно достигается после вызова метода init.

Алгоритмы хеширования, такие как SHA-1, не требуют явной инициализации, поэтому они возвращаются в состояние непосредственно после создания экземпляра: состояние, в котором они еще не выполнялисьобрабатывать любые данные.Таким образом, алгоритм хеширования можно повторно использовать для хеширования другого значения.Это немного более эффективно , чем создание нового объекта.

Из Руководства разработчика JCA :

После того, как дайджест сообщения былвычисляется, объект дайджеста сообщения автоматически сбрасывается и готов к приему новых данных и вычислению их дайджеста.Все прежнее состояние (т. Е. Данные, предоставленные для вызовов обновления) теряется.

Таким образом, после вызова digest() объект сбрасывается в состояние, в котором он еще не получил никаких данных.Таким образом, второй вызов возвращает хеш поверх пустой строки / байтового массива октетов.


В кавычках из Википедии :

SHA1("")
gives hexadecimal: da39a3ee5e6b4b0d3255bfef95601890afd80709

, что идентичнобайты со знаком [-38, 57, -93, -18, 94, 107, 75, 13, 50, 85, -65, -17, -107, 96, 24, -112, -81, -40, 7, 9]: значение, которое вы указали в комментариях.


Правильный напечатанный хеш действительно

 A0FF4E5EBDA08F0CE15DF6C9FB48FEC734AC8B28

в шестнадцатеричном формате в верхнем регистре или

[160, 255, 78, 94, 189, 160, 143, 12, 225, 93, 246, 201, 251, 72, 254, 199, 52, 172, 139, 40]

как массив байтов без знака в Python.Обратите внимание, что Java использует подписанных байтов вместо , так что это будет равно

[-96, -1, 78, 94, -67, -96, -113, 12, -31, 93, -10, -55, -5, 72, -2, -57, 52, -84, -117, 40]

Для вычисления этого будет достаточно одного вызова MessageDigest#digest(byte[] input): byte[], в вашем случае это будетbyte[] digest = msdDigest.digest(input), после чего вы могли бы сначала распечатать digest и , чтобы позже вернуть переменную, содержащую байтовый массив.


Обратите внимание, что хеши по-прежнему не должны использоваться одновременно в нескольких потокаххоть;только один хэш может быть вычислен за один раз;эти классы не являются потокобезопасными.

0 голосов
/ 01 декабря 2018

На вопрос отвечает Эрвин Болвидт в комментарии :

Удалить оператор print. Вызов digest разрушителен, и вы звонитеэто дважды - неверное значение, возвращаемое из метода

В дополнение к этому:

В совокупности все вышеперечисленное означает, что ваш код должен быть просто:

private static byte[] getSHA1(byte[] input) throws NoSuchAlgorithmException {
    return MessageDigest.getInstance("SHA-1").digest(input);
}

Тест

byte[] input = "$&).6CXzPHw=2N_+isZK2908069825".getBytes("US-ASCII");
System.out.println(Arrays.toString(getSHA1(input)));

Выход

[-96, -1, 78, 94, -67, -96, -113, 12, -31, 93, -10, -55, -5, 72, -2, -57, 52, -84, -117, 40]

То же, что и Выход Python , за исключением того, что он печатается как подписанный, так и беззнаковый байт:

[160, 255, 78, 94, 189, 160, 143, 12, 225, 93, 246, 201, 251, 72, 254, 199, 52, 172, 139, 40]
...