十六进制哈希转字节

huangapple go评论68阅读模式
英文:

String hex hash to bytes

问题

我有一个以十六进制形式表示的字符串 hash("e6fb06210fafc02fd7479ddbed2d042cc3a5155e"),我想将其与 crypt.digest() 进行比较。
一种可行的方法是将 crypt.digest() 转换为十六进制,但我想避免多次转换,而是将 hash 从十六进制形式(如上所示)转换为字节数组。

我尝试了以下方法:

byte[] hashBytes = new BigInteger(hash, 16).toByteArray();

但是它与 crypt.digest() 不匹配。当我将 hashBytes 再次转换为十六进制时,我得到的是 "00e6fb06210fafc02fd7479ddbed2d042cc3a5155e"。

前导零似乎是我未能匹配字节数组的原因。它们为什么会出现?如何通过使用 crypt.digest() 和 toByteArray() 来获得相同的结果?

英文:

I have String hash in hex form ("e6fb06210fafc02fd7479ddbed2d042cc3a5155e") and I would like to compare it to crypt.digest().
One way, which works fine, is to convert crypt.digest() to hex, but I would like to avoid multiple conversions and rather convert hash from hex form (above) to byte array.

What I tried was:

byte[] hashBytes = new BigInteger(hash, 16).toByteArray();

but it does not match with crypt.digest(). When I convert hashBytes back to hex I get "00e6fb06210fafc02fd7479ddbed2d042cc3a5155e".

The leading zeros seem to be the reason why I fail to match byte arrays. Why do they occur? How can I get the same result using crypt.digest() and toByteArray?

答案1

得分: 1

答案可以在以下答案中找到,这是一个与之高度相关的问题的帖子:将十六进制转储的字符串表示转换为Java中的字节数组。其中提到:

> 使用 BigInteger 的问题在于必须存在一个**“符号位”。如果领先的字节设置了高位,则结果的字节数组在第1个位置上多了一个额外的0**。但仍然+1。
>
>– Gray Oct 28 '11 at 16:20

由于第一个位具有特殊含义(表示符号,正数为0,负数为1),如果你的数据以高位为1开始,BigInteger 会在数据前面添加一个额外的0。否则,它将被解释为负数,尽管它最初不是负数。

也就是说,像这样的数据:

101110

会变成

0101110

如果发生这种情况,你可以使用Arrays.copyOfRange(data, 1, data.length)来手动撤销这个操作。


然而,与其修复这段代码,我建议使用链接帖子中发布的其他解决方案之一。它们更清晰、更容易阅读和维护。

英文:

The answer can be found in the following answer from a thread about the highly related question Convert a string representation of a hex dump to a byte array using Java?:

> The issue with BigInteger is that there must be a "sign bit". If the leading byte has the high bit set then the resulting byte array has an extra 0 in the 1st position. But still +1.
>
>– Gray Oct 28 '11 at 16:20

Since the first bit has a special meaning (indicating the sign, 0 for positive, 1 for negative), BigInteger will prefix the data with an additional 0 in case your data started with a 1 on the high bit. Otherwise it would be interpreted as negative although it was not negative to begin with.

I.e. data like

101110

is turned into

0101110

You could easily undo this manually by using Arrays.copyOfRange(data, 1, data.length) if it happens.


However, instead of fixing that code, I would suggest using one of the other solutions posted in the linked thread. They are cleaner and easier to read and maintain.

答案2

得分: 1

额外的00的原因是因为e6的最高(符号)位被设置为1。
多余的00字节使其成为BigInteger的无符号值。

    String hash = "e6fb06210fafc02fd7479ddbed2d042cc3a5155e";
    byte[] hashBytes = new BigInteger(hash, 16).toByteArray();
    hashBytes = hashBytes.length > 1 && hashBytes[0] == 0
        ? Arrays.copyOfRange(hashBytes, 1, hashBytes.length) : hashBytes;
    System.out.println(Arrays.toString(hashBytes));

这里的问题是,如果哈希值实际上以00开头怎么办?
然后你需要哈希长度,或者进行宽松比较。

英文:

The reason for the extra 00 is that e6 has it high (sign) bit set.
A redundant byte 00 makes it an unsigned value for BigInteger.

    String hash = "e6fb06210fafc02fd7479ddbed2d042cc3a5155e";
    byte[] hashBytes = new BigInteger(hash, 16).toByteArray();
    hashBytes = hashBytes.length > 1 && hashBytes[0] == 0
        ? Arrays.copyOfRange(hashBytes, 1, hashBytes.length) : hashBytes;
    System.out.println(Arrays.toString(hashBytes));

The question arises, what if the hash actually starts with a 00?
Then you need the hash length, or do a lenient comparison.

huangapple
  • 本文由 发表于 2020年9月10日 03:13:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/63818140.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定