MD5 计算前导 0 丢失问题

2020-01-20

现象

我们使用 Java 生成 MD5 时常用的写法如下:

1private static String md5(String data) throws NoSuchAlgorithmException {
2    MessageDigest md = MessageDigest.getInstance("MD5");
3    md.update(data.getBytes());
4    return new BigInteger(1, md.digest()).toString(16);
5}

如果计算 a 的 MD5 会发现结果为 cc175b9c0f1b6a831c399e269772661,只有 31 位,正确的值应该是 0cc175b9c0f1b6a831c399e269772661,仔细观察可以发现我们的计算方法把第一位 0 丢失了。

原因

原因出在最后的字符串转换上,MD5 生成字符串是将 byte 数组转成了 BigInteger,再转成 16 进制表示的字符串,其中转成 BigInteger 时会丢掉前导 0。

解决

只要将字符串生成的地方略作修改即可:

1public static String md5(String data) throws NoSuchAlgorithmException {
2    MessageDigest  md = MessageDigest.getInstance("MD5");
3    md.update(data.getBytes());
4    return String.format("%032x", new BigInteger(1, md.digest()));
5}

String.format 的参数如下:

转换符或标志说明
%x整数类型(十六进制)
0数字前面补 0

因此当 string 不满 32 位时,自动在前面补 0。