在工作项目中,我们接受用户的个人信息和类似账号密码此类数据时必须对其进行加密,否则可能会导致信息的泄露引发安全性问题。加密的方式有很多种,其中较为常用的加密方式是MD5加密算法和SHA-1加密算法,这两种算法中MD5较为常用。MD5用于确保信息传输完整一致,是一种计算机广泛使用的哈希算法,主流编程语言普遍已有MD5实现。
MD5算法
MD5是一种通过固定的算法将任意位长的数据转化为固定长度128位(16字节)长的加密算法。这种算法容易计算,从原数据得到MD5值是很容易操作的。而且对于极其相似两个的原数据,即使相差只有一位,最后得到的MD5加密结果都是有很大区别的。而且MD5具有很强的抗碰撞性,即使已知原数据和MD5的值想找到一个具有相同的MD5值的伪造数据也很困难。
但是随着MD5算法被破解,通过杂凑算法伪造数据的可能性也是有的。但这并不妨碍我们在电子商务领域对MD5算法的使用,只是当需要传输安全性要求极高的数据时需要采用加密程度更高、安全性更好的加密算法。普通的数据传输及个人信息和类似账号密码传输都可以使用MD5加密算法。
MD5算法加密原理
在进行JAVA实现前,我们有必要先了解MD5算法加密的原理,因为我们的目的并不是专门研究密码领域,所以这里仅简要的表述算法加密的原理,为我们使用java来实现加密做铺垫。
1.填充并处理原数据
MD5加密算法会将任意长度的数据转换为128位字串。在进行加密前的第一步要做的事将数据填充至512位(512位是四个128位)长度的倍数。无论数据是否是512位的倍数,我们都将其进行填充,直到总长度为:N*512+448为止。在数据的后面先添加一个1,再添加若干个0知道符合上述长度为止。在这个结果后面再添上64数据,表示填充之前的数据的长度,如果数据位数太多,则采用低64位。
经过如此处理,我们得到了N*512+448+64位的数据,一共有(N+1)*512个数据。
2.将变量进行初始化并分组
初始的128位值为初试链接变量,由128=32*4分为4组32位的数据。用大端法表示这些数据。第一分组需要将上面四个链接变量复制到另外四个变量中:A到a,B到b,C到c,D到d。从第二分组开始的变量为上一分组的运算结果,即A = a, B = b, C = c, D = d。每一组都是如此操作。
3.MD5加密算法
主循环有四轮操作,每轮循环的算法都几乎相同。第一轮进行16次操作。每次操作对a、b、c和d中的其中三个作一次非线性函数运算,然后将所得结果加上第四个变量,文本的一个子分组和一个常数。再将所得结果向左环移一个不定的数,并加上a、b、c或d中之一。最后用该结果取代a、b、c或d中之一。我们不必过于纠结具体的算法,我们在代码实现时这些算法已经被封装好。
四个非线性函数:
F( X ,Y ,Z ) = ( X & Y ) | ( (~X) & Z )
G( X ,Y ,Z ) = ( X & Z ) | ( Y & (~Z) )
H( X ,Y ,Z ) =X ^ Y ^ Z
I( X ,Y ,Z ) =Y ^ ( X | (~Z) )
4.输出最后加密结果
最后将MD5算法加密后的a、b、c和d的级联作为整个算法的输出值。
java.security.MessageDigest
很多的项目中,我们用整个辅助类或是自己编写的util类来实现MD5的效果。实际上在java中有MD5的这个类,在security包中,名字就是MessageDigest。此 MessageDigest 类为应用程序提供信息摘要算法的功能,如 MD5 或 SHA 算法。
MessageDigest类使用步骤:
- 初始化MessageDigest对象
- 调用update方法传入要进行加密的byte数据
- (可选)调用reset方法重置要传入进行加密的数据
- 调用digest方法对传入的数据进行加密
package MD5;import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;public class mda5 {public static void main(String[] args) {// TODO Auto-generated method stubString strData = "words";String strMD5 = null;try {MessageDigest md5 = MessageDigest.getInstance("MD5");md5.update(strData.getBytes());// md5.reset();if (strData == null || "".equals(strData))strMD5 = null;else {byte[] mdBytes = md5.digest();StringBuffer sb = new StringBuffer();for(int i = 0 ;i<mdBytes.length;i++){int bt = mdBytes[i]&0xff; if (bt < 16){ sb.append(0); } sb.append(Integer.toHexString(bt)); }strMD5 = sb.toString(); }} catch (NoSuchAlgorithmException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
在项目中使用的一个实战例子
在我最近工作的项目中也有用到MD5加密的工具类,简洁易懂,在这里分享一下,可以用来备份拷贝。
package com.framework.util;import java.security.MessageDigest;/*** * @author Quinn**/
public class MD5Util {/*** The MD5 encryption operation is performed on the incoming information.* * @param origin* Enter the information to be encrypted.* @param charsetname* Byte code type.* @return Display MD5 encryption results in lower case letters and numbers.*/public static String MD5Encode(String origin, String charsetname) {String resultString = null;byte[] b = null;try {resultString = new String(origin);MessageDigest md = MessageDigest.getInstance("MD5");if (charsetname == null || "".equals(charsetname))b = md.digest(resultString.getBytes());elseb = md.digest(resultString.getBytes(charsetname));StringBuffer resultSb = new StringBuffer();for (byte bs : b) {int bt = bs & 0xff;if (bt < 16)resultSb.append(0);resultSb.append(Integer.toHexString(bt));}resultString = resultSb.toString().toLowerCase();} catch (Exception exception) {exception.printStackTrace();}return resultString;}/*** The MD5 encryption operation is performed on the incoming information and* return upper case letters and numbers.* * @param origin* Enter the information to be encrypted.* @param charsetname* Byte code type.* @return Display MD5 encryption results in upper case letters and numbers.*/public static String MD5EncodeUpper(String origin, String charsetname) {String resultString = MD5Encode(origin, charsetname);if (resultString != null)resultString = resultString.toUpperCase();return resultString;}}