SHA1 Java与Python不一样

时间:2018-11-30 22:09:36

标签: java python cryptography sha1

我需要将一段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())

也许字节类型之间有区别? 有任何想法吗 ? 谢谢

2 个答案:

答案 0 :(得分:2)

问题由Erwin Bolwidt在{{​​3}}中回答:

  

删除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]

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之类的算法类型的对象,以及CipherMac之类的对象都实现了一种方案,该方案使得可以进行大批量的零碎操作数据的。他们通过具有 update 内部状态和最终操作(例如签名/验证)或-对于MessageDigest-具有多个重载的称为digest的单个操作的方法来做到这一点。

这些算法还具有一个共同点,即在调用“最终”操作时,将对象的状态直接重置初始化后的状态。通常在调用init方法之后达到此状态。

尽管诸如SHA-1之类的哈希算法不需要显式初始化,所以它们在实例化后立即返回状态:尚未处理任何数据的状态。这样,哈希算法可以重新用于哈希另一个值。与实例化新对象相比,这效率更高

来自JCA developers guide

  

计算出消息摘要后,将自动重置消息摘要对象,并准备接收新数据并计算其摘要。所有以前的状态(即提供给更新调用的数据)都将丢失。

因此,在调用digest()之后,该对象将重置为尚未接收到任何数据的状态。因此,第二个调用将返回一个空八位位组字符串/字节数组的哈希值。


引用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 返回稍后保存字节数组的变量。


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