在一些对安全需求比较高的WEB站点中,除了要保证数据的传输有保障之外,数据库的内容也需要做一些处理,像银行之类的系统,要防止外人取得数据,还不能让管理员看到账号和密码.很多时候都是利用MD5算法来保证数据的完整性和安全性,但是MD5算法并不是一个加密算法,它就像人的"指纹"一样,每个人都有指纹,而且指纹都不一样,MD5算法算出的结果,就像数据的指纹一样,任何数据,不论它占用多少空间,它的指纹都能作为这块数据的唯一标识.,SUN公司的JDK文档就描述了如何通过类java.security.MessageDigest
来完成JAVA的MD5算法实现.
我们先来看一看它的继承关系:
此类为抽象类,并且其父类也是抽象类, MessageDigestSpi 是一个Service Provider Interface (服务提供者接口),主要是为其子类提供方法摘要,并由其子类完成.
由于 MessageDigest 是一个抽象类,我们不可以直接实例化它,得用它的静态方法就能得到这个对象的实例:
public static MessageDigest getInstance(String algorithm) throws NoSuchAlgorithmException
它接受一个字符串参数,我们只需传递一个算法的名称即可,就像这样:
MessageDigest md = MessageDigest.getInstance("md5");
它返回实现了指定摘要算法的MessageDigest对象.
接下来,我们只用把数据传递给MessageDigest对象的digest方法就行了:
md.digest(data);
public byte[] digest(byte[] input)
这个方法接受一个byte[],返回这个经MD5算法算过的byte[].这个byte[]可以是任何字符,如果我把"1296105945865".getBytes()作为参数传递进去,
看看它的返回值:
md.digest(rand.getBytes());
//~[-53, -89, 11, -29, -127, 98, 90, 45, -119, -24, -80, -49, -38, 96, -35, 2]
这样的数据在HTTP协议中传输,会使浏览器疯掉,因为它也许根本不知道如何处理诸如:",e123,1;2,;,./;?=2h3jhkjl?;"这样的数据,一般都会把它转为以
16进制(32位)的方式,或者用BASE64转成"明文"再处理.
转成以16进制显示:
public String show(byte[] b){ StringBuilder sb = new StringBuilder(); for(int i = 0;i<b.length;i++){ int high = (b[i] >> 4) & 0xF; //取出高4位 int low = b[i] & 0xF; //取出低4位 sb.append(String.format("%x%x", high,low)); } System.out.println(sb); return sb.toString(); }
在网上进行下载的时候,经常有网站在资源旁边附上md5验证码,就是让你在下载完成后,用md5算法把你下载的东西算一遍,把结果进行比较,如果一致,就表示你下载的资源确实和原版是一样的.假设某银行出示了相关网银驱动的md5码,你就可以在网上下载好驱动后,进行比较,稍有偏差,都可以认为此驱动被注入了木马之类的,因为相同的数据,会产生相同的"指纹".为什么很多人认为MD5算法是一个加密算法?因为很多人在数据库存用户密码的时候,不是存的密码,而是存的用MD5算法算过密码之后的数据.这样一来,就算有人知道某数据库里某用户的密码是什么,他也一样登录不进来,他在输入密码之后,输入的密码会进行MD5算法算过之后,再与数据库里存的密码数据进行比较.这样一来,安全性又提高了.
由于MD5算法算过的结果很多时候不太方便,除了以16进制显示之外,也可以用BASE64算法进行编码.BASE64就是通过其算法对数据处理后,处理得到的结果全部是以"明文"显示,所谓"明文",就是你能在键盘上看到的字符,而且像"."这样的特殊符号也没有,所以,用BASE64算法得到MD5算法结果的"明文"也可以.
SUN公司也提供了一个类用来完成BASE64的算法:sun.misc.BASE64Encoder.由于官方并没有正式发布这个类,所以它的包名为misc,杂项的意思,在JDK1.6文档里面也找不到这个类的相关信息.但是使用起来很简单,很方便:
BASE64Encoder encoder = new BASE64Encoder();
encoder.encode(Bytes[]); //返回String
关于BASE64Encoder的encode()方法,重载了7个,还有encodeBuffer()方法,就不在这里述说了,用法是一样的.另外,数据传输过后,还需要解码,就要用到sun.misc.BASE64Decoder这个类来完成了:
BASE64Decoder decoder = new BASE64Decoder();
decoder.decodeBuffer(String);
依靠BASE64Decoder的decodeBuffer()方法,就能完成数据的解码.这个方法同样重载了几次,使用是一样的.