【问题标题】:SHA1 Java vs Python are not the sameSHA1 Java 与 Python 不一样
【发布时间】:2018-11-30 22:09:36
【问题描述】:

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

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

【问题讨论】:

  • 你用的是什么代码?你得到什么结果?你期待什么结果?
  • 大卫说的,让我们看看Python和Java的代码,输入和输出。
  • 对不起,我现在把代码放在问题里了
  • prefix 是什么?
  • 删除打印语句。调用摘要是破坏性的,你调用它两次 - 你从方法返回的值不正确

标签: java python cryptography sha1


【解决方案1】:

Erwin Bolwidt 在comment 中回答了这个问题:

删除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 output 相同,除了打印为有符号字节和无符号字节:

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

【讨论】:

    【解决方案2】:

    Java Cryptographic Architecture 表示算法类型的对象,例如MessageDigest,以及CipherMac,都在实现一种方案,可以对大量数据执行零碎操作。他们通过具有更新内部状态和最终操作的方法来做到这一点,例如签名/验证或 - 对于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] 相同:您在 cmets 中输入的值。


    打印的正确哈希确实是

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


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

    【讨论】:

    • 发布此内容是因为我不同意 Erwin Bolwidt 或 Andreas 的措辞。 MessageDigest 对象的(状态)被破坏,它被重置为已知的有效状态。
    猜你喜欢
    • 2012-10-12
    • 2013-06-25
    • 2011-10-26
    • 1970-01-01
    • 2017-08-16
    • 1970-01-01
    • 1970-01-01
    • 2018-11-26
    • 2018-01-03
    相关资源
    最近更新 更多