我需要将一段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())
也许字节类型之间有区别? 有任何想法吗 ? 谢谢
答案 0 :(得分:2)
问题由Erwin Bolwidt在{{3}}中回答:
删除
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]
与digest()
相同,除了打印为有符号字节还是无符号字节:
[160, 255, 78, 94, 189, 160, 143, 12, 225, 93, 246, 201, 251, 72, 254, 199, 52, 172, 139, 40]
答案 1 :(得分:1)
Java加密体系结构表示诸如MessageDigest
之类的算法类型的对象,以及Cipher
和Mac
之类的对象都实现了一种方案,该方案使得可以进行大批量的零碎操作数据的。他们通过具有 update 内部状态和最终操作(例如签名/验证)或-对于MessageDigest
-具有多个重载的称为digest
的单个操作的方法来做到这一点。>
这些算法还具有一个共同点,即在调用“最终”操作时,将对象的状态直接重置初始化后的状态。通常在调用init
方法之后达到此状态。
尽管诸如SHA-1之类的哈希算法不需要显式初始化,所以它们在实例化后立即返回状态:尚未处理任何数据的状态。这样,哈希算法可以重新用于哈希另一个值。与实例化新对象相比,这效率更高。
计算出消息摘要后,将自动重置消息摘要对象,并准备接收新数据并计算其摘要。所有以前的状态(即提供给更新调用的数据)都将丢失。
因此,在调用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
和返回稍后保存字节数组的变量。
请注意,尽管如此,仍不应在多个线程上同时使用哈希。一次只能计算一次哈希;这些类不是线程安全的。