迭代哈希在 Python 和 Java 中返回不同的值

2024-02-22

我正在尝试将 python (2.7) 脚本移植到 Java。它多次迭代 sha256 哈希,但最终得到不同的结果。我注意到他们第一次返回相同的结果,但从那时起它就不同了。

这是 Python 实现:

import hashlib

def to_hex(s):
  print " ".join(hex(ord(i)) for i in s)

d = hashlib.sha256()

print "Entry:"
r = chr(1)
to_hex(r)

for i in range(2):
  print "Loop", i
  d.update(r)
  r = d.digest()
  to_hex(r)

在 Java 中:

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class LoopTest {

  public static void main(String[] args) {
    MessageDigest d;
    try {
      d = MessageDigest.getInstance("SHA-256");
    } catch (NoSuchAlgorithmException e) {
      System.out.println("NoSuchAlgorithmException");
      return;
    }

    System.out.println("Entry:");
    byte[] r = new byte[] {1};
    System.out.println(toHex(r));

    for(int i = 0; i < 2; i++) {
      System.out.printf("Loop %d\n", i);
      d.update(r);
      r = d.digest();
      System.out.println(toHex(r));
    }
  }

  private static String toHex(byte[] bytes) {
    StringBuilder sb = new StringBuilder(bytes.length);
    for (byte b: bytes) {
       sb.append(String.format("0x%02X ", b));
    }
    return sb.toString();
  }
}

对于 python,输出是:

$ python looptest.py
Entry:
0x1
Loop 0
0x4b 0xf5 0x12 0x2f 0x34 0x45 0x54 0xc5 0x3b 0xde 0x2e 0xbb 0x8c 0xd2 0xb7 0xe3 0xd1 0x60 0xa 0xd6 0x31 0xc3 0x85 0xa5 0xd7 0xcc 0xe2 0x3c 0x77 0x85 0x45 0x9a
Loop 1
0x98 0x1f 0xc8 0xd4 0x71 0xa8 0xb0 0x19 0x32 0xe3 0x84 0xac 0x1c 0xd0 0xa0 0x62 0xc4 0xdb 0x2c 0xe 0x13 0x58 0x61 0x9a 0x83 0xd1 0x67 0xf5 0xe8 0x4e 0x6a 0x17

对于java:

$ java LoopTest
Entry:
0x01
Loop 0
0x4B 0xF5 0x12 0x2F 0x34 0x45 0x54 0xC5 0x3B 0xDE 0x2E 0xBB 0x8C 0xD2 0xB7 0xE3 0xD1 0x60 0x0A 0xD6 0x31 0xC3 0x85 0xA5 0xD7 0xCC 0xE2 0x3C 0x77 0x85 0x45 0x9A
Loop 1
0x9C 0x12 0xCF 0xDC 0x04 0xC7 0x45 0x84 0xD7 0x87 0xAC 0x3D 0x23 0x77 0x21 0x32 0xC1 0x85 0x24 0xBC 0x7A 0xB2 0x8D 0xEC 0x42 0x19 0xB8 0xFC 0x5B 0x42 0x5F 0x70

造成这种差异的原因是什么?

Edit:

感谢@dcsohl 和@Alik 的回答,我现在明白原因了。由于我要将 Python 脚本移植到 Java,所以我必须保持 Python 脚本不变,所以我修改了 Java 程序,如下所示:

byte[] r2 = new byte[]{};
for(int i = 0; i < 2; i++) {
  System.out.printf("Loop %d\n", i);
  d.update(r);
  r2 = d.digest();
  System.out.println(toHex(r2));
  byte[] c = new byte[r.length + r2.length];
  System.arraycopy(r, 0, c, 0, r.length);
  System.arraycopy(r2, 0, c, r.length, r2.length);
  r = c;
}

两种语言运行update() and digest()不同。

python 文档update() says

使用字符串 arg 更新哈希对象。重复调用相当于连接所有参数的单个调用:m.update(a); m.update(b)相当于m.update(a+b).

我使用 shell 测试了这一点sha256sum命令。

echo -n '\0x01\0x4b\0xf5\0x12\0x2f\0x34\0x45\0x54\0xc5\0x3b\0xde\0x2e\0xbb\0x8c\0xd2\0xb7\0xe3\0xd1\0x60\0xa\0xd6\0x31\0xc3\0x85\0xa5\0xd7\0xcc\0xe2\0x3c\0x77\0x85\0x45\0x9a' | sha256sum
981fc8d471a8b01932e384ac1cd0a062c4db2c0e1358619a83d167f5e84e6a17 *-

您从 \0x01 开始,因此这是第一个字节,然后其余字节是 0x01 的哈希值。生成的哈希值与您的 Python 输出相匹配。

现在看看这个 - 我省略了最初的 \0x01 并得到了哈希值 - 它与你的 Java 输出匹配。

> echo -n '\0x4b\0xf5\0x12\0x2f\0x34\0x45\0x54\0xc5\0x3b\0xde\0x2e\0xbb\0x8c\0xd2\0xb7\0xe3\0xd1\0x60\0xa\0xd6\0x31\0xc3\0x85\0xa5\0xd7\0xcc\0xe2\0x3c\0x77\0x85\0x45\0x9a' | sha256sum
9c12cfdc04c74584d787ac3d23772132c18524bc7ab28dec4219b8fc5b425f70 *-

但为什么?最初的 \0x01 不应该包含在内吗?是的,除了 javadocdigest() says:

通过执行填充等最终操作来完成哈希计算。进行此调用后,摘要将被重置。

所以当你打电话时你最初的 \0x01 会被丢弃digest()在 java 中,您只是在消化旧的摘要,而没有最初的 \0x01 条目。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

迭代哈希在 Python 和 Java 中返回不同的值 的相关文章

  • 获取运行时生成的类的字节

    我正在使用一个 Java 框架 该框架使用自定义类加载器在运行时生成一些 代理 类 我想为任何这样的类获取自定义 ClassLoader 从 loadClass 返回的与该类对应的原始字节数组 这可能吗 我知道 如果一个类作为资源存在 那么
  • 按字段名称对命名元组列表进行排序的 Pythonic 方法

    我想对命名元组列表进行排序 而不必记住字段名的索引 我的解决方案看起来相当尴尬 希望有人能有一个更优雅的解决方案 from operator import itemgetter from collections import namedtu
  • PyPI 项目页面中的“Py 版本”是什么意思?这有关系吗?

    我注意到 大多数在 PyPI 上发布的项目在其项目页面中都包含 Py 版本 元数据 但它们的值各不相同 如果包不是通用包或不是纯 python 包 那么它们的值是不同的 这是可以理解的 以便表示它们的目标平台 例如鼻页 https pypi
  • 为什么 Libgdx 的 Table 不接受缩放操作?

    我在 libgdx 库中使用 scene2d 在游戏中创建一些 UI 我使用了一个表格 我想在用户触摸时采取一些缩放操作以使按钮触摸有意义 当我使用任何其他 Actor 类型 例如 Group 并为其提供缩放操作时 它可以工作 但不能工作表
  • Java字符串中的字符数[重复]

    这个问题在这里已经有答案了 可能的重复 Java 使用unicode上划线显示平方根时字符串的长度 https stackoverflow com questions 7704426 java length of string when u
  • Java 通用问题

    下面的代码可以编译 但如果我取消注释行 它不会编译 我很困惑为什么 HashMap 确实扩展了 AbstractMap 并且声明映射的第一行可以正常编译 import java util AbstractMap import java ut
  • 在 (i)python 脚本中从 jupyter 内核获取输出

    我想从单个 ipython 会话中打开多个内核 在这些内核上运行代码 然后收集结果 但我不知道如何收集结果 甚至不知道如何查看 stdout stderr 我怎样才能做这些事情呢 到目前为止我所得到的 我已经使用如下代码管理了前两个步骤 打
  • 对于 pygtk 应用程序来说,什么是好的嵌入式浏览器?

    我计划在我的 pygtk 应用程序中使用嵌入式浏览器 并且我正在 gtkmozembed 和 pywebkitgtk 之间进行辩论 两者之间有什么引人注目的区别吗 还有我不知道的第三种选择吗 应该注意的是 我不会使用它来访问网络上的内容 我
  • 如何在树莓派上更新到最新的 python 3.5.1 版本?

    我昨天拿到了 Raspberry Pi 我已经在尝试用它来编写代码了 我有一个计划在其上运行的程序 但它仅与 Python 版本 3 5 0 或 3 5 1 兼容 并且我在互联网上找到的所有内容似乎都已经过时 与 Python 2 有关 或
  • 在 Java Jersey 2 JAX-RS 中初始化单例

    我是泽西岛 2 22 2 的新手 请耐心等待 我正在创建一个与 LDAP 服务器交互的 REST 服务 用于存储 删除和检索用户数据 该服务通过执行加密 解密充当安全中介 在使用 REST 服务之前必须进行相当多的初始化 并且我只想执行此初
  • 如何将时间间隔划分为不同长度的部分?

    我有一个从 0 到t 我想把这个区间分成一个以2 25 2 25 1 5为周期的累积序列 方法如下 input start 0 stop 19 output sequence 0 2 25 4 5 6 8 25 10 5 12 14 25
  • 尝试修复我的功能

    我正在开发一个函数 我必须返回一个元组 其中第一个参数是最大数字的 str 第二个参数是 int 列表 这是示例以及我为该函数编写的内容 投票 G G N G C G 1 3 0 1 您必须将最大值的位置映射到正确的一方 parties N
  • Hive NVL 不适用于列的日期类型 - NullpointerException

    我正在使用 HDFS 上的 MapR Hive 发行版并面临以下问题 如果表的列类型是 日期 类型 则NVL https cwiki apache org confluence display Hive LanguageManual UDF
  • 在 Java Web 应用程序中获取 DataSource 资源

    我的 context xml 文件中有以下资源标记
  • 具有条件的重复行 pandas dataframe python

    我的数据框有问题 我的 df 是 product power brand product 1 3 x 1500W brand A product 2 2x1000W 1x100W product 3 1x1500W 1x500W brand
  • 在 Django/python 中,如何将内存缓存设置为无限时间?

    cache set key value 9999999 但这并不是无限的时间 def get memcache timeout self timeout Memcached deals with long gt 30 days timeou
  • 使用 JPA 和 Hibernate 时 DISTINCT 如何工作

    DISTINCT 在 JPA 中使用什么列 是否可以更改它 以下是使用 DISTINCT 的 JPA 查询示例 select DISTINCT c from Customer c 这没有多大意义 不同的列是基于哪一列 它是否在实体上指定为注
  • Networkx 中 Louvain 分区的可视化

    请帮助我更改 Louvain 聚类算法结果的可视化 我从网站上获取了代码https github com taynaud python louvain https github com taynaud python louvain我可以重写
  • 在私有 guice 模块中公开 Map

    我在 guice 中有一个 PrivateModule 我想从该模块公开一个 Map public class TestInjectionModule extends PrivateModule expose Map class annoa
  • Pandas 替换特定列上的值

    我知道这两个类似的问题 熊猫替换值 https stackoverflow com questions 27117773 pandas replace values Pandas 替换数据框中的列值 https stackoverflow

随机推荐