2

我无法让 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);
}
4

4 回答 4

4

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;
}
于 2011-10-04T12:15:52.343 回答
1

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

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

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

这些中的每一个都可以使用Apache Commons Codec轻松实现。

没有任何问题MessageDigest,但我相信您对异常的工作原理以及如何以不同于文本数据的方式处理二进制数据的理解存在缺陷。

于 2011-10-04T12:16:13.153 回答
1

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);
}
于 2011-10-04T12:19:41.540 回答
0
// 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();
            }
于 2021-05-22T06:08:24.550 回答