31

我正在尝试使用 MessageDigest 生成 MD5 和。我有以下代码。

byte[] md5sum = digest.digest();
BigInteger bigInt = new BigInteger(1, md5sum);
output = bigInt.toString(16);

这返回的不是 32 个字符的字符串,而是一个 31 个字符的字符串8611c0b0832bce5a19ceee626a403a7

预期的字符串是08611c0b0832bce5a19ceee626a403a7

输出中缺少前导 0。

我尝试了另一种方法

byte[] md5sum = digest.digest();
output = new String(Hex.encodeHex(md5sum));

并且输出符合预期。

我检查了文档,Integer.toString 根据它进行了转换

使用 Character.forDigit 提供的数字到字符的映射,并在适当的情况下添加减号。

并在 Character.forDigit 方法中

如果 0 <=digit < radix,则 digit 参数有效。

有人能告诉我两种方法有何不同以及为什么删除前导 0 吗?

4

5 回答 5

22

我个人会避免使用BigInteger将二进制数据转换为文本。这并不是它的真正用途,即使它可以用于此目的。有大量代码可用于将 a 转换byte[]为其十六进制表示 - 例如使用Apache Commons Codec或简单的单一方法:

private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray();
public static String toHex(byte[] data) {
    char[] chars = new char[data.length * 2];
    for (int i = 0; i < data.length; i++) {
        chars[i * 2] = HEX_DIGITS[(data[i] >> 4) & 0xf];
        chars[i * 2 + 1] = HEX_DIGITS[data[i] & 0xf];
    }
    return new String(chars);
}
于 2012-04-23T06:33:13.757 回答
12

String.format("%064X", new BigInteger(1, ByteArray);

在哪里

  1. 0 - 零前导符号
  2. 64 - 字符串长度
  3. X - 大写
  4. ByteArray - 要在其上运行此操作的 ByteArray
于 2016-01-12T14:39:24.983 回答
9

它被删除是因为前导零不重要,根据BigInteger. 27和之间没有区别000000000027

如果你想要一个特定的长度,你必须自己强迫它,比如:

output = ("00000000000000000000000000000000"+output).substring(output.length());

(虽然那是笨拙的)。

于 2012-04-23T06:33:46.067 回答
2

使用以下代码替换删除的零:

MessageDigest digest = MessageDigest.getInstance("MD5");
digest.reset();
digest.update(output.getBytes());
byte[] outDigest = digest.digest();
BigInteger outBigInt = new BigInteger(1,outDigest);
output = outBigInt.toString(16);
    while (output.length() < 32){
    output = "0"+output;
    }

循环将根据需要考虑尽可能多的前导零

于 2012-09-26T14:54:25.793 回答
-2
MessageDigest m=MessageDigest.getInstance("MD5");
m.update(PlainText.getBytes(),0,PlainText.length());
String M1=new BigInteger(1,m.digest()).toString(16);      
return M1;
于 2018-02-11T17:33:31.217 回答