SHA1 Java 与 Python 不一样

SHA1 Java vs Python are not the same

我需要将一段 python 翻译成 Java,但是当我进行 SHA 散列时,我没有得到与 Python 相同的结果,有字符串:

$&).6CXzPHw=2N_+isZK2908069825

// Java代码

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代码

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

可能是字节类型不同?? 有任何想法吗 ? 谢谢

Erwin Bolwidt 在 :

中回答了问题

Remove the print statement. Calling digest is destructive and you call it twice - the value that you return from the method is incorrect

除此之外:

综上所述,您的代码应该是:

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]

相同,除了打印为有符号字节和无符号字节:

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

Java 密码体系结构代表算法类型的对象,例如 MessageDigest 还有 CipherMac 都在实现一个方案,使它成为可能对大量数据执行零碎的操作。他们通过使用 更新 内部状态和最终操作(例如签名/验证)或 - 对于 MessageDigest - 具有各种重载的称为 digest 的单个操作来实现此目的.

这些算法还有一个共同点,就是在调用"final"操作时,对象的状态重置直接初始化后的状态。此状态通常在调用 init 方法后达到。

虽然 SHA-1 等哈希算法不需要显式初始化,因此它们 return 在实例化后直接进入状态:它们尚未处理任何数据的状态。这样,哈希算法就可以重新用于哈希另一个值。这比实例化一个新对象稍微高效

来自JCA developers guide

After the message digest has been calculated, the message digest object is automatically reset and ready to receive new data and calculate its digest. All former state (i.e., the data supplied to update calls) is lost.

因此,在您调用 digest() 之后,对象将重置为尚未收到任何数据的状态。因此,第二个调用 return 是一个空八位字节字符串/字节数组的散列。


如此引用from Wikipedia:

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 and return 稍后保存字节数组的变量。


请注意,散列仍不应在多个线程上同时使用;一次只能计算一个散列;这些 类 不是线程安全的。