您的位置:首页 > 编程语言 > Java开发

JAVA中的MD5加密,常见问题处理

2016-03-03 16:03 351 查看
平常使用MD5加密时,自己封装处理时,常见有2个问题:

1、转换为字符串时,高位的0被舍去;

2、出现负数时会有多个连续的F;

这是因为MessageDigest返回的结果是无符号数的byte数组,所以一个byte表示2位的十六进制数时,高位可能为0,而且在JAVA中byte默认是按有符号数的来读取的,转换时会出现负数。

public class MD5Utils {

private static final char[] chs =
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

public static String getMD5(String str) {
MessageDigest messageDigest;
try {
messageDigest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new IllegalArgumentException();
}
byte[] bys = messageDigest.digest(str.getBytes());
StringBuilder sb = new StringBuilder(32);
int index;
for (byte b : bys) {
index = b & 0xff;//将负数byte按无符号数读取
sb.append(chs[index >> 4]);//16进制数的高位
sb.append(chs[index % 16]);//16进制数的低位
}
return sb.toString();//返回的结果为32位的16进制数字符串
}
}

其中,因为MessageDigest返回的结果是用无符号数来表示的,而在JAVA中默认是采用最高位来表示正负的,所以使用了位运算的方式来截取该无符号数:

index = b & 0xff;



等价于:

index = b;
if(index < 0 ){
index += 256;
}

 

一个byte可以表示2位的16进制数,采用Integer.toHexString(index)转换时,若小于16会只有1位16进制数。继续使用位运算+查表法来获取16进制数:

sb.append(chs[ index >> 4]);
sb.append(chs[ index % 16]);
等价于:
               if(index < 16){
                   sb.append('0');
               }
               sb.append(Integer.toHexString(index));
因为没有使用Integer的toHexString(index)和toString(int i, int radix)方法,而是自己重新实现了,所以效率有所提高。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: