【问题标题】:Can't seem to generate hex-encoded string from SHA256 digest in Java似乎无法从 Java 中的 SHA256 摘要生成十六进制编码字符串
【发布时间】:2011-04-20 00:52:30
【问题描述】:

似乎无法弄清楚我在哪里出错了:

 private static String generateHashFromFile(String filePath) {
  try {
   final int BUFSZ = 32768;
   MessageDigest sha = MessageDigest.getInstance("SHA-256");
   FileInputStream in = new FileInputStream(filePath);
   BufferedInputStream is = new BufferedInputStream(in, BUFSZ);
   byte[] buffer = new byte[BUFSZ];
   int num = -1;
   while((num = is.read(buffer)) != -1) {
    sha.update(buffer, 0, num);
   }
   is.close();
   byte[] hash = sha.digest();
   return byteArrayToHex(hash);
  } catch (NoSuchAlgorithmException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (FileNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  return null;
 }

 private static String byteArrayToHex(byte[] barray)
 {
     char[] c = new char[barray.length * 2];
     byte b;
     for (int i = 0; i < barray.length; ++i)
     {
         b = ((byte)(barray[i] >> 4));
         c[i * 2] = (char)(b > 9 ? b + 0x37 : b + 0x30);
         b = ((byte)(barray[i] & 0xF));
         c[i * 2 + 1] = (char)(b > 9 ? b + 0x37 : b + 0x30);
     }
     return new String(c);
 }

我得到如下字符串:

")469.76F5941+31E25)6,9,C26)978)4*917180A4C(B7C,E,D+6,7133C705167"

显然不是十六进制!

问题:

  1. 哈希生成代码是否正确?
  2. 十六进制编码方式正确吗?
  3. 我在编码方面遗漏了什么吗?

【问题讨论】:

    标签: java encoding hash hex sha256


    【解决方案1】:

    byte 值已签名,并且您正在使用带符号的右移。这将导致在计算高阶 nybble 时 b 的负值。

    例如,考虑一下您的代码对 byte 值 -112 (0x90) 的作用。右移时,首先提升为int 值,0xFFFFFF90。然后右移 4 位,保留符号,变为 0xFFFFFFF9。然后将其转换回一个字节,该字节简单地丢弃高位 24 位,并将 0xF9(十进制-7)分配给bb 不大于 9,因此结果字符为 (-7 + 48),或 ')'。

    改为这样做:

    int hi = (barray[i] & 0xF0) >>> 4, lo = barray[i] & 0xF;
    

    使用byte 作为局部变量在 32 位或 64 位机器上没有任何好处。事实上,转换为byte 是一种浪费的指令。

    【讨论】:

      【解决方案2】:

      您的哈希生成和十六进制编码代码都有效。我会仔细查看您正在阅读的文件的内容。

      你也可以这样写你的十六进制编码方法:

      public static String byteArrayToHex(byte[] barray) {
       StringBuffer sb = new StringBuffer();
       for (int i = 0; i < barray.length; i++) {
           String hex = Integer.toHexString(0xff & barray[i]);
           if (hex.length() == 1) sb.append('0');
           sb.append(hex);
       }
       return sb.toString();
      }
      

      【讨论】:

        【解决方案3】:

        您的哈希生成代码是正确的。要将byte[] barray 转换为十六进制字符串,您可以这样做:

        String c = new String();
        for(short i = 0; i < barray.length; i++) {
            c += Integer.toString((barray[i] & 255) + 256, 16).substring(1).toUpperCase();
        }
        

        【讨论】:

          猜你喜欢
          • 2012-02-15
          • 1970-01-01
          • 1970-01-01
          • 2014-03-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-10
          相关资源
          最近更新 更多