前言
最近公司做的一个功能有人反馈有问题,仔细看了看代码打断点才发现原来是md5加密的bug后来看了这篇文章才解决,为了更直观我把代码抽离出来方便演示
出现bug的原因
1 2 3 4 5 6 7 8 9 10 11 12 13
| public static void main(String[] args) throws Exception { String password="300655"; String md5 = getMD5(password); System.out.println(getMD5(md5)); } public static String getMD5(String str) throws Exception { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(str.getBytes());
return new BigInteger(1, md.digest()).toString(16); }
|
这种方式应该是常见的写法了,可是问题是计算出md5转化为String类型的时候,如果md5的结果是0开头的,那么你会发现开头的0被抛弃了,那么校验的时候一定会报错,下面我用个例子演示,公司使用md5一般都是两次加密,比如我这里使用300655
这个值进行加密,在线加解密网站上测试的结果如下
这个表示加密两次的结果
而用上面的代码测试出来的结果为
可以看到结果是不一样的
解决方案
使用下面这种方式即可解决
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public static void main(String[] args) throws Exception { String password = "300655"; String md5 = getMD5(password); System.out.println(getMD5(md5)); }
public static String getMD5(String str) throws Exception { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(str.getBytes()); return toHexString(md.digest()); }
private static String toHexString(byte[] bytes) { Formatter formatter = new Formatter(); for (byte b : bytes) { formatter.format("%02x", b); } String res = formatter.toString(); formatter.close(); return res; }
|
原理就是利用formatter
将字节一个个的转为十六进制的形式即可,可以看到这次的结果为
大功告成!( ̄▽ ̄)~*