注意:本节内容主要参考自《Java加密与解密的艺术(第2版)》第6章“验证数据完整性--消息摘要算法”
3.1、消息摘要算法:防止消息在传递过程中被篡改。
原理:任何消息经过消息摘要算法后,都会产生唯一的散列值(即“数据指纹”)(同一段消息无论经过多少次相同的消息摘要算法加密,结果都相同),所以如果消息在传送过程中被修改,那么算出来的数据指纹也与原本的消息算出来的不同了,如果没有被修改,则数据指纹是相同的。
特点:单向性(即只有加密,没有解密)
3.2、MD5(算法已被破解,应用于安全程度要求不高的情况下)
实现方式:
- Commons Codec(“CC”,最推荐,因为封装了JDK的底层代码,并且提供了二进制字节数组向十六进制转化的方法)
- JDK(没有提供二进制字节数组向十六进制转化的方法,想要进行转化,需要借助BC)
- Bouncy Castle(“BC”,不推荐,实现比较复杂)
下边只列出基于CC的工具类代码,至于基于JDK的代码可以参考“《Java加密与解密的艺术(第2版)》”,基于BC的代码可参考“慕课网”
3.2.1、基于CC实现的MD5加密算法
pom.xml
1 <!-- https://mvnrepository.com/artifact/commons-codec/commons-codec --> 2 <dependency> 3 <groupId>commons-codec</groupId> 4 <artifactId>commons-codec</artifactId> 5 <version>1.10</version> 6 </dependency>
工具类
1 package com.util.md5; 2 3 import java.io.UnsupportedEncodingException; 4 import java.security.NoSuchAlgorithmException; 5 import org.apache.commons.codec.digest.DigestUtils; 6 /** 7 * 基于Commons Codec的md5算法 8 */ 9 public class Md5CC { 10 private static final String ENCODING = "UTF-8"; 11 12 /** 13 * MD5加密,加密后的结果为二进制字节数组 14 */ 15 public static byte[] encode(String data) throws NoSuchAlgorithmException,UnsupportedEncodingException { 16 return DigestUtils.md5(data.getBytes(ENCODING)); 17 } 18 19 /** 20 *MD5加密,加密后的结果为二进制字节数组,并且在这里将二进制字节数组转为了32位的16进制 21 */ 22 public static String encodeMd5Hex(String data) throws NoSuchAlgorithmException,UnsupportedEncodingException { 23 return new String(DigestUtils.md5Hex(data.getBytes(ENCODING)));//这里直接使用new String(encodedByte,"UTF-8")不行 24 } 25 26 /** 27 * 测试 28 * @param args 29 * @throws UnsupportedEncodingException 30 * @throws NoSuchAlgorithmException 31 */ 32 public static void main(String[] args) throws UnsupportedEncodingException, NoSuchAlgorithmException { 33 34 String data = "找一个好姑娘做老婆是我的梦 想!"; 35 /*************测试encode()**************/ 36 System.out.println("原文-->"+data); 37 byte[] encodedByte = Md5CC.encode(data); 38 System.out.println("加密后-->"+encodedByte); 39 byte[] encodedByte2 = Md5CC.encode(data); 40 System.out.println("加密后-->"+encodedByte2); 41 for(int i=0;i<encodedByte.length;i++){ 42 System.out.println(encodedByte[i]==encodedByte2[i]); 43 } 44 /*************测试encodeMd5Hex()**************/ 45 System.out.println("原文-->"+data); 46 String encodedStr = Md5CC.encodeMd5Hex(data); 47 System.out.println("加密后-->"+encodedStr); 48 String encodedStr2 = Md5CC.encodeMd5Hex(data); 49 System.out.println("加密后-->"+encodedStr2); 50 System.out.println(encodedStr.equals(encodedStr2)); 51 } 52 }
jar包的引入参考第二章的第一个例子进行即可,在测试的过程中,自己去试着看看“同一个消息多次进行MD5加密后结果是不是相同”;
在encode()方法的测试中判断两个byte[]是否相等:按索引依次比较两个字节数组中的元素是否相同即可(如果使用main方法去测的话);如果使用Junit,直接使用assertArrayEquals(array1,array2)即可。