三年六班的李子明同学,你妈拿了两本计算机基础在二号树上等你

MessageDigest.getInstance("md5")

初始化,用

MessageDigest.digest(byte[] input)

方法执行MD5加密,返回的结果也是个byte数组。

 

然后把数组中每一个字节转换成两位的十六进制字符串,如果结果只有一位的话在前面添零补位。

结果就是一个30位长度的MD5字符串了。

 1 /** 对数据作MD5加密。 */
 2 public static String hashUp(String src) {
 3     String hash = null;
 4 
 5     try {
 6         byte[] md5 = MessageDigest.getInstance("md5").digest(src.getBytes());
 7 
 8         StringBuilder builder = new StringBuilder();
 9         for (byte b : md5) {
10             String hex = Integer.toHexString(0xff & b);
11             if (hex.length() == 1) {
12                 builder.append('0');
13             }
14 
15             builder.append(hex);
16         }
17         hash = builder.toString();
18     } catch (NoSuchAlgorithmException e) {
19         e.printStackTrace();
20     }
21 
22     return hash;
23 }

 

但是!重点是!

为什么要用0xff来与一下b呢?

因为不这样处理的话b是正数还不要紧,是负数的话结果就不对了。

 

首先假设MD5结果中某一位是26,byte类型长8位,二进制形式是:

0001 1010

因为toHexString方法需要的参数是int类型,所以要把b强转成int,变成了32位,于是前24位填零补位,二进制形式是:

0000 0000 0000 0000 0000 0000 0001 1010

把参数转成十六进制,结果是:

0000001A

前面的0全部省略,结果是1A,没有问题。

 

但是这某一位变成了-26会怎么样呢?

负数在计算机中用正数的补码形式存储,于是把26的二进制值每一位取反再加一,结果是:

1110 0110

于是再把它强转为32位,也就是26的补码。这一转不要紧,结果成了:

1111 1111 1111 1111 1111 1111 1110 0110

蔚为大观。

这个时候再四位一转,把它转成十六进制,结果就是:

FFFFFFE6

符号变了一下,结果变得妈都不认识了。

 

虽然结果好像没什么问题,但是前面的一堆F可不打算直接拿来用。

于是干脆一了百了,把int值的前24位都扔了不要,用0xff,也就是:

0000 0000 0000 0000 0000 0000 1111 1111

与上它:

1111 1111 1111 1111 1111 1111 1110 0110

前24位当场就没了,真是太惨了:

0000 0000 0000 0000 0000 0000 1110 0110

这时候再转成十六进制,结果是E6,虽然跟开始的值不一样,

……

…………

但是反正也没人在乎……

posted @ 2015-05-20 16:31  Chihane  阅读(511)  评论(0编辑  收藏  举报