【问题标题】:String hex hash to bytes字符串十六进制哈希到字节
【发布时间】:2020-12-28 06:28:42
【问题描述】:

我有十六进制形式的字符串 hash(“e6fb06210fafc02fd7479ddbed2d042cc3a5155e”),我想将它与 crypt.digest() 进行比较。 一种效果很好的方法是将 crypt.digest() 转换为十六进制,但我想避免多次转换,而是将哈希从十六进制形式(上图)转换为字节数组。

我尝试的是:

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

但它与 crypt.digest() 不匹配。当我将 hashBytes 转换回十六进制时,我得到“00e6fb06210fafc02fd7479ddbed2d042cc3a5155e”。

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

【问题讨论】:

标签: java arrays hash


【解决方案1】:

额外 00 的原因是 e6 设置了高(符号)位。 冗余字节 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 开头怎么办? 然后你需要哈希长度,或者做一个宽松的比较。

【讨论】:

    【解决方案2】:

    答案可以在following answer 中从一个关于高度相关问题Convert a string representation of a hex dump to a byte array using Java? 的线程中找到:

    BigInteger 的问题是必须有一个“符号位”。如果前导字节设置了高位,则生成的字节数组在第一个位置有一个 extra 0。但仍然 +1。

    – 格雷 2011 年 10 月 28 日 16:20

    由于第一位具有特殊含义(表示符号,0 表示正数,1 表示负数),BigInteger 将在数据前面加上一个额外的0,以防您的数据以1 开头高位。否则它会被解释为否定的,虽然它一开始不是否定的。

    即像这样的数据

    101110
    

    变成了

    0101110
    

    如果发生这种情况,您可以使用Arrays.copyOfRange(data, 1, data.length) 手动轻松撤消此操作。


    但是,我建议使用链接线程中发布的其他解决方案之一,而不是修复该代码。它们更干净,更易于阅读和维护。

    【讨论】:

      猜你喜欢
      • 2011-05-18
      • 2023-03-19
      • 2011-03-02
      • 2014-05-26
      • 2015-01-17
      • 2012-01-24
      • 1970-01-01
      • 2010-10-04
      • 2013-08-09
      相关资源
      最近更新 更多