为什么我有时会在Java和PHP中得到不同的SHA256哈希值?

为什么我有时会在Java和PHP中得到不同的SHA256哈希值?,java,php,sha256,Java,Php,Sha256,所以我对PHP中的哈希函数有一个奇怪的小问题。这只是偶尔发生,这让我很困惑。本质上,我有一个Java应用程序和一个PHP页面,它们都计算相同字符串的SHA256。两者之间没有任何问题,因为它们(通常)计算相同的散列。唯一的例外是,每隔一段时间,PHP的输出比Java的输出长一个字符 我用PHP编写了以下代码: $token = $_GET["token"]; $token = hash("sha256", $token."<salt>"); echo "Your token is "

所以我对PHP中的哈希函数有一个奇怪的小问题。这只是偶尔发生,这让我很困惑。本质上,我有一个Java应用程序和一个PHP页面,它们都计算相同字符串的SHA256。两者之间没有任何问题,因为它们(通常)计算相同的散列。唯一的例外是,每隔一段时间,PHP的输出比Java的输出长一个字符

我用PHP编写了以下代码:

$token = $_GET["token"];
$token = hash("sha256", $token."<salt>");
echo "Your token is " . $token;
正如你所看到的,它们几乎一模一样。但由于某些原因,顶部的一个(由PHP计算)还有一个0。我真的没有注意到它的押韵或理由,但它确实让我感到困惑。我试着去想一些事情,比如错误的编码,或者错误的返回值,但是没有一个能真正解释为什么它们除了一个字符外几乎是相同的

在此问题上的任何帮助都将不胜感激

编辑:空间仅位于底部,以突出显示额外0所在的位置。实际的散列没有空间,实际上是一个有效的散列,因为它与Java生成的散列相同


伊迪丝2:很抱歉。我用记事本++检查了长度,由于它与我的普通文本编辑器不同,我将长度误读了1。因此,是的,上面的一个确实是正确的。这意味着这是我Java代码中的一个bug。我将探究Ignacio的答案,然后再与您联系。

最上面的散列是正确的长度;底部的散列是输出的,因为十六进制值在输出时没有填充为零(请注意,它是一个字节的MSn)。因此,Java程序中的一个bug与哈希算法无关

>>> '%04x %02x%02x %x%x' % (0x1201, 0x12, 0x01, 0x12, 0x01)
'1201 1201 121'

实际上,第二个散列的长度似乎不正确(63)。可能是因为它是由两个不同的标记组合而成的,而最后一个标记(应该是16个字符)的初始零被删除了吗?

事实上,我不认为PHP是罪魁祸首。哈希函数生成一个由十六进制字符[a-f0-9]组成的字符串,但空格肯定不是其中之一。我在其中进行了快速编辑。我只是把空间放在那里,这样人们就不必搜索额外的0。它实际上是一个有效的散列。您能提供产生此行为的示例输入吗?“%first one%”。长度=64。嗯?或者你只是想展示一个例子,而不是一个真正的散列,当它出错时?大多数语言只是在现有库周围使用一个包装器。在PHP/Java的情况下不确定,但是您能在Python中尝试一下,看看是否得到与这两种方法类似的结果吗?对不起,我不得不投你的反对票——他已经解释过第二盘的空白是为了让我们能够确定差距在哪里。@Duniyadnd:是的,我解释过了。我的回答解释了这一点。@Duniyadnd不管怎样,第二个哈希不可能是正确的:它只有63个字符。@IgnacioVazquez Abrams猜想我误解了OP所说的内容-认为空格正在替换不同的字符。取消了否决票。谢谢你的澄清。事实证明这是正确的。我们的程序中有一个静态SHA256函数,它使用Java的MessageDigest。不幸的是,我很久以前从一个网站上获取了这段代码,当时它有一个bug。一个快速的按位操作更改,现在一切都好了。谢谢你的帮助。对于误导性的散列,我很抱歉。我应该仔细检查这个长度。可能与PHP的弱类型有关,检测到它是一个数字,并“有益地”删除开头的0。@BrendanLong第二个实际上是由Java生成的。)无法/直接/生成。我发现很难相信Java在十六分之一的错误中得到了sha256,而且没有人对此感到愤怒。同样的情况也适用于“获取转换”。我对伊格纳西奥的答案投了赞成票。
>>> '%04x %02x%02x %x%x' % (0x1201, 0x12, 0x01, 0x12, 0x01)
'1201 1201 121'