为了账号安全,请及时绑定邮箱和手机立即绑定

SHA1 Java 与 Python 不一样

SHA1 Java 与 Python 不一样

慕运维8079593 2021-09-02 17:22:30
我需要将一段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 回答

?
慕森卡

TA贡献1806条经验 获得超8个赞

问题由 Erwin Bolwidt 在评论中回答:

删除print声明。调用digest是破坏性的,您调用了两次 - 您从该方法返回的值不正确

在此之上:

  • 没有必要调用reset()一个新的MessageDigest

  • 调用update(input)而不是update(input, 0, input.length)

  • 调用digest(input)而不是update(input)+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]



查看完整回答
反对 回复 2021-09-02
?
宝慕林4294392

TA贡献2021条经验 获得超8个赞

在Java密码体系结构代表的算法类型,如对象MessageDigest,但也Cipher并Mac全部实施方案,使得它可以对大量的数据进行的零碎操作。他们通过更新内部状态和最终操作的方法来做到这一点,例如签名/验证或 - 对于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 并稍后返回保存字节数组的变量。


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



查看完整回答
反对 回复 2021-09-02
  • 2 回答
  • 0 关注
  • 236 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信