【问题标题】:Cannot output correct hash in Java. What is wrong?无法在 Java 中输出正确的哈希。怎么了?
【发布时间】:2016-10-12 01:03:10
【问题描述】:

在我的 Android 应用程序中,我有一个 SHA256 哈希值,我必须使用 RIPEMD160 消息摘要算法进一步对其进行哈希处理。

我可以输出任何字符串的正确 sha256 和ripemd160 哈希,但是当我尝试使用ripemd160 对sha256 哈希进行哈希时,我得到一个不正确的哈希。

根据在线哈希计算器,字符串'test'(全小写)的SHA256值为:

9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08

而字符串'test'的RIPEMD160值为:

5e52fee47e6b070565f74372468cdc699de89107

根据在线计算,用成熟的 sha256 散列得到的值是:

4efc1c36d3349189fb3486d2914f56e05d3e66f8

我的应用程序给我的是:

cebaa98c19807134434d107b0d3e5692a516ea66

这显然是错误的。

这是我的代码:

public static String toRIPEMD160(String in)
{
    byte[] addr = in.getBytes();
    byte[] out = new byte[20];
    RIPEMD160Digest digest = new RIPEMD160Digest();
    byte[] sha256 = sha256(addr);
    digest.update(sha256,0,sha256.length);
    digest.doFinal(out,0);
    return getHexString(out);
}

public static byte[] sha256(byte[] data)
{
    byte[] sha256 = new byte[32];
    try
    {
        sha256 = MessageDigest.getInstance("SHA-256").digest(data);
    }
    catch(NoSuchAlgorithmException e)
    {}

    return sha256;
}

对于ripemd160算法,你需要bouncycastle和java.security.MessageDigest for sha256。

【问题讨论】:

    标签: java android sha


    【解决方案1】:

    您的“在线计算器”结果是使用 SHA-256 对字符串“test”的字节进行散列,将该散列的结果转换为十六进制字符串,然后取对应于该十六进制的 ASCII 字符的字节的结果字符串并再次对其进行哈希处理。这与您的 Java 代码非常不同,后者将来自第一个散列的字节直接传递给第二个散列,而不将它们打印为十六进制并将这些字符转换回其间的字节。值为 254(十进制)的单个字节在 hex 中变为“fe”,转换回字节后变为两字节序列 [0x66, 0x65]。

    【讨论】:

      【解决方案2】:

      您的哈希工作正常。问题是您使用的在线计算器正在处理您的输入:

      9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
      

      作为 字符串 而不是字节数组。换句话说,它将每个字符视为一个字节,而不是将字符对解析为十六进制的字节。如果我将其作为字符串提供给在线计算器,我确实得到了你所得到的:

      4efc1c36d3349189fb3486d2914f56e05d3e66f8
      

      但是,您将输出视为字节数组而不是String,这会给您带来不同的结果。您应该将原始 SHA256 哈希编码为字符串,然后将编码后的字符串传递给哈希函数。我看到你有一个 getHexString 方法,所以我们将使用它。

      public static String toRIPEMD160(String in) {
          try {
              byte[] addr = in.getBytes();
              byte[] out = new byte[20];
              RIPEMD160Digest digest = new RIPEMD160Digest();
      
              // These are the lines that changed
              byte[] rawSha256 = sha256(addr);
              String encodedSha256 = getHexString(rawSha256);
              byte[] strBytes = encodedSha256.getBytes("UTF-8");
              digest.update(strBytes, 0, strBytes.length);
      
              digest.doFinal(out, 0);
              return getHexString(out);
          } catch (UnsupportedEncodingException ex) {
              // Never happens, everything supports UTF-8
              return null;
          }
      }
      

      如果您想知道它是否有效,请将 encodedSha256 的值放入在线哈希计算器中。只要计算器使用 UTF-8 编码将字符串转为字节数组,就会匹配你的输出。

      【讨论】:

      • @Dan 一个错字。已修复。
      【解决方案3】:

      要获得byte[] 摘要的可打印版本,请使用以下代码:

      StringBuffer hexString = new StringBuffer();
      for (int i=0;i<out.length;i++) {
          hexString.append( String.format("%02x", 0xFF & out[i]) );
      }
      

      然后拨打hexString.toString();

      【讨论】:

        猜你喜欢
        • 2015-08-16
        • 2016-08-24
        • 2019-11-10
        • 2021-03-18
        • 1970-01-01
        • 1970-01-01
        • 2015-07-05
        • 2015-06-08
        • 1970-01-01
        相关资源
        最近更新 更多