【问题标题】:Java MessageDigest doesn't workJava MessageDigest 不起作用
【发布时间】:2011-10-04 12:12:30
【问题描述】:

我无法让 MessageDigest 工作,程序给了我两个错误: UnsupportedEncodingException, NoSuchAlgorithmException

 byte[] bytesOfchat_key = "lol".getBytes("UTF-8");
 MessageDigest md = MessageDigest.getInstance("MD5");
 byte[] Digest = md.digest(bytesOfchat_key);

如果我抛出错误,它会给我 ワ￟ᄡ9ᅦヌnp>0xd￉z 作为响应(16 个字符)

PS:我曾经打印过Digest

for (byte b : Digest) {
    System.out.print((char)b);
}

【问题讨论】:

    标签: java md5 digest


    【解决方案1】:

    md5 返回十六进制数字,因此您可以使用将其解码为字符串

    String plaintext = "lol";
    MessageDigest m = MessageDigest.getInstance("MD5");
    m.reset();
    m.update(plaintext.getBytes());
    byte[] digest = m.digest();
    //Decoding
    BigInteger bigInt = new BigInteger(1,digest);
    String hashtext = bigInt.toString(16);
    while(hashtext.length() < 32 ){
      hashtext = "0"+hashtext;
    }
    

    【讨论】:

      【解决方案2】:

      程序不会你这些错误 - 你调用的方法可以抛出这些异常,所以你需要为它们捕获块,或者声明你的方法也会抛出它们。

      摘要的结果是二进制数据,而不是文本。您应该将其逐字节转换为这样的文本 - 如果您需要将其作为字符串,有两种常见的解决方案:

      • 将每个字节编码为一对十六进制数字
      • 对完整字节数组使用 Base64 编码

      这些都可以通过Apache Commons Codec 轻松实现。

      MessageDigest 没有任何问题,但我相信您对异常的工作原理以及如何区别对待二进制数据与文本数据的理解存在缺陷。

      【讨论】:

        【解决方案3】:

        MessageDigest 生成的字节不一定代表可打印的字符。您应该显示每个字节的数值,或将字节数组转换为 Base64 字符串以具有可打印的内容。

        请参阅apache commons-codec 以获取 Base64 的实现。

        您必须处理的两个异常永远不应该发生,因为 UTF-8 保证被任何 JVM 支持,并且 JVM 也原生支持 MD5 算法。因此,您应该将代码包装在这样的 try catch 块中:

        try {
            byte[] bytesOfchat_key = "lol".getBytes("UTF-8");
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] Digest = md.digest(bytesOfchat_key);
        }
        catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("something impossible just happened", e);
        }
        catch (UnsupportedEncodingException e) {
            throw new RuntimeException("something impossible just happened", e);
        }
        

        【讨论】:

          【解决方案4】:
          // I had the issue that the hash from API was not generating right.
          // Using eclipse it was working correctly but when running the same API as the service runnable jar was causing wrong value to produce.
          
          // it was caused by java as Java take Lower case and upper case letters as different Ascii values and window take them as same, so you need to simply add lower and upper case letters in your bytes to hex convertion.
          // I hope this helps everyone.
                
           private static String makeHash(String key_to_hash) {
                      try {
                          MessageDigest md = MessageDigest.getInstance("SHA1");
                          md.reset();
                          md.update(key_to_hash.getBytes(Charset.forName("UTF-8")));
                          return bytesToHex(md.digest());
                      } catch (Exception ex) {
                          ex.printStackTrace();
                      }
                      return null;
                  }
              
                  
              
          private static String bytesToHex(byte[] b) {
                          char hexDigit[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                                  'a', 'b', 'c', 'd', 'e', 'f','A', 'B', 'C', 'D', 'E', 'F' };
                          StringBuffer buf = new StringBuffer();
                          for (int j = 0; j < b.length; j++) {
                              buf.append(hexDigit[(b[j] >> 4) & 0x0f]);
                              buf.append(hexDigit[b[j] & 0x0f]);
                          }
                          return buf.toString();
                      }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-05-07
            • 1970-01-01
            • 2022-11-06
            • 2013-06-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多