关于MD5加密中转换byte为十六进制的问题

关于MD5加密中转换byte为十六进制的问题

问题陈述

先看看MD5加密的代码

StringBuilder builder = new StringBuilder();
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(myContentString.getBytes());
byte[] bytes = md.digest();
for(byte b : bytes)
    builder.append(Integer.toString((b & 0xff) + 0x100).subString(1));
String result = builder.toString();

为啥倒数第二句要这样写呢?

问题解答

在Java中,byte转化为int时是按照带符号扩展进行转换的。举个例子,如有一个byte为1111_1111,那么当它转化为int时,剩余的24位与byte的最高位也就是符号位相同,那么此时int就会成为32个1组成的整数。显然这并不是我们想要的,因为我们需要的是0xff而非0xffffffff。

那为啥&一下就可以了呢?

为了处理被扩展的24位。首先在Java中,0xff、123这样的非小数的字面量默认为int类型,byte与这样的字面量相运算,根据向上转换原则,结果自动转化为int类型。第二,&的特性就是对应位相同同为1,不同为0,这样就能达到将byte转化为int时的前24个填充位置为0的效果,也就是达到了筛出最后八位的效果。这样在将其转化为十六进制字符串时就无需考虑前24位的问题。

加上0x100的原因?

为了前导零。我们需要将byte转化为2位的十六进制数,但是如果byte的高4位为0那么输出的话就仅仅有一位。如byte为0000_1111时,不加0x100那么上面的代码就会将byte转化为f,而非0f。当加上0x100时,还以此为例子,那么结果就是0x10f,在通过取子串的方式,从index = 1的地方开始取(index从零开始),这样就可以把0f取出来了。

其他解决方案有木有

可以利用字符串格式化操作,直接将倒数第二句写成

builder.append(String.format("%02x",b));

“%02x”表示把b格式化为2位的十六进制,不够补上前导零。

你可能感兴趣的:(MD5)