将MD5数组转换为字符串Java

15

我知道有很多类似的主题,但是...能否有人提供一个生成MD5字符串的方法的工作示例。
我目前正在使用MessageDigest,并且我正在执行以下操作来获取一个字符串:

sun.misc.BASE64Encoder().encode(messageDigest.digest())  
我猜应该有更好的方法来实现这个。提前感谢你!

这是哪个BASE64Encoder类? - Jon Skeet
抱歉...这里是import sun.misc.BASE64Encoder; - Andrew
7
一般情况下,我会避免使用sun.*类…参见http://java.sun.com/products/jdk/faq/faq-sun-packages.html。 - Jon Skeet
请查看已接受答案的评论,代码中存在一个错误。 - David Parks
5个回答

16
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] arr = md.digest(bytesOfMessage);
return Base64.getEncoder().encodeToString(arr);

注意:MD5 不再被视为好的哈希算法,请考虑选择 SHA 算法。


18
FYI:MD5是一种哈希算法,而不是密码。因此,它不能对数据进行“加密”。相反,它会对数据进行“哈希处理”。 - Adam Paynter
40
警告 - 这个算法有一个漏洞。它会删除 MD5 哈希值的开头 0。举个例子:使用这个算法对“wwq123456”(不加引号)进行哈希,然后使用一个在线工具,如 http://www.miraclesalad.com/webtools/md5.php 进行相同操作,并注意缺少的 0。正确的哈希值应该是“07e1c0d9533b5168e18a99f4540448af”,但这个算法给出的是“7e1c0d9533b5168e18a99f4540448af”。糟糕了。 - David Parks
以上答案的基本问题是,如果以零开头,则会将其删除,因此我认为它不适合使用!!! - duggu
我开始维护一个已有此实现的网站,遇到了@DavidParks警告我们的那个错误,并因为需要在开头使用0进行比较而浪费了时间和精力。我正在使用密码解决方案,但无法验证某些密码。 - Ernest
2
现在答案已经被编辑成完全不同的实现方式,这些评论变得令人困惑了。 - teppic
显示剩余2条评论

16

我会使用 commons-codec

  • Base64编码 - Base64.encodeBase64(digestBytes)
  • 十六进制字符串 - Hex.encodeHex(digestBytes)

1
DigestUtils是此页面上最佳的解决方案。:) - Alan LaMielle
虽然使用库代码而不是编写自己的算法很棒,但它也有一个缺点,就是整个库必须包含在分发中,这对于仅仅一个方法来说是一种浪费。显然,如果还使用了许多其他类和方法,那么这是理想的,但这可能通常不是情况。 - darrenp
Hex.encodeHex比已接受的答案要快得多。 - RonK

5
// Convert to hex string
StringBuffer sb = new StringBuffer();
for (int i = 0; i < messageDigest.length; i++) {
    if ((0xff & messageDigest[i]) < 0x10) {
        sb.append('0');
    }
    sb.append(Integer.toHexString(0xff & messageDigest[i]));
}
String md5 = sb.toString();

这假设您实际上希望将您的MD5打印为十六进制字符串,而不是BASE64编码。这通常是它的表示方式。

如果有人使用这个解决方案,需要提醒一下。它不允许前导零,这可能会影响哈希检查。因此,0x0E将只被打印为E,而0x00将被削减为单个0。一个基本的解决方法是测试每个结果的长度,并在长度为1时添加前导零。 - Matt C.
@MechIntel 你说得完全正确。我刚刚更新了答案。感谢你提醒! - Grodriguez

2
我看到了下面的解决方案:

我看到了下面的解决方案:

    byte[] digest = md.digest(someDataByteArray);
    StringBuilder hex = new StringBuilder();
    for (byte b : digest) {
        hex.append(String.format("%02x", b));
    }

这个方法得到的结果实际上与在*nix终端中使用md5程序得到的结果相同,而且非常清晰明了! - Marvin

0
import javax.xml.bind.DatatypeConverter;
import java.security.MessageDigest;

...
String input = "westerngun";
MessageDigest digest = MessageDigest.getInstance("MD5"); // not thread-safe, create instance for each thread
byte[] result = digest.digest(input.getBytes()); // get MD5 hash array, could contain negative
String hex = DatatypeConverter.printHexBinary(result).toLowerCase(); // convert byte array to hex string

如果你想要一个数字:
Integer number = Integer.parseInt(hex, 16); // parse hex number to integer. If overflowed, use Long.parseLong()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接