注意:本节内容主要参考自《Java加密与解密的艺术(第2版)》第6章“验证数据完整性--消息摘要算法”
4.1、SHA
原理:消息摘要长度(可以定量为加密后的字符串的长度)越长,安全性越高
- MD5:128位二进制摘要(32位16进制字符串)(已破解)
- SHA1:160位二进制摘要(40位16进制字符串)(已破解)
- SHA256:256位二进制摘要(64位16进制字符串)(常用,在spring security中也有使用到)
实现方式:
- Commons Codec(“CC”,最推荐,因为封装了JDK的底层代码,并且提供了二进制字节数组向十六进制转化的方法)
- JDK(没有提供二进制字节数组向十六进制转化的方法,想要进行转化,需要借助BC)
- Bouncy Castle(“BC”,不推荐,实现比较复杂)
下边只列出基于CC的工具类代码,至于基于JDK的代码可以参考“《Java加密与解密的艺术(第2版)》”,基于BC的代码可参考“慕课网”
4.1.1、基于CC的SHA加密算法
1 package com.util.sha; 2 3 import java.io.UnsupportedEncodingException; 4 import java.security.NoSuchAlgorithmException; 5 import org.apache.commons.codec.digest.DigestUtils; 6 /** 7 * 基于Commons Codec的SHA算法 8 */ 9 public class SHACC { 10 private static final String ENCODING = "UTF-8"; 11 12 /** 13 * SHA加密,加密后的结果为二进制字节数组 14 */ 15 public static byte[] encode(String data) throws NoSuchAlgorithmException,UnsupportedEncodingException { 16 //return DigestUtils.sha1(data.getBytes(ENCODING));//SHA-1 17 return DigestUtils.sha256(data.getBytes(ENCODING));//SHA-256 18 } 19 20 /** 21 *SHA加密,加密后的结果为二进制字节数组,并且在这里将二进制字节数组转为了16进制字符串 22 */ 23 public static String encodeSHAHex(String data) throws NoSuchAlgorithmException,UnsupportedEncodingException { 24 //return new String(DigestUtils.sha1Hex(data.getBytes(ENCODING))); 25 return new String(DigestUtils.sha256Hex(data.getBytes(ENCODING))); 26 } 27 28 /** 29 * 测试 30 * @param args 31 * @throws UnsupportedEncodingException 32 * @throws NoSuchAlgorithmException 33 */ 34 public static void main(String[] args) throws UnsupportedEncodingException, NoSuchAlgorithmException { 35 36 String data = "找一个好姑娘做老婆是我的梦 想!"; 37 /*************测试encode()**************/ 38 System.out.println("原文-->"+data); 39 byte[] encodedByte = SHACC.encode(data); 40 System.out.println("加密后-->"+encodedByte); 41 byte[] encodedByte2 = SHACC.encode(data); 42 System.out.println("加密后-->"+encodedByte2); 43 for(int i=0;i<encodedByte.length;i++){ 44 System.out.println(encodedByte[i]==encodedByte2[i]); 45 } 46 /*************测试encodeSHAHex()**************/ 47 System.out.println("原文-->"+data); 48 String encodedStr = SHACC.encodeSHAHex(data); 49 System.out.println("加密后-->"+encodedStr); 50 String encodedStr2 = SHACC.encodeSHAHex(data); 51 System.out.println("加密后-->"+encodedStr2); 52 System.out.println(encodedStr.equals(encodedStr2)); 53 } 54 }
在我们需要采用相应的sha算法的时候,只需选用不同的函数即可(具体查询Commons Codec的API即可,链接在第五章末尾)。
jar包的引入参考第二章的第一个例子进行即可,在测试的过程中,自己去试着看看“同一个消息多次进行SHA加密后结果是不是相同”;
在encode()方法的测试中判断两个byte[]是否相等:按索引依次比较两个字节数组中的元素是否相同即可(如果使用main方法去测的话);如果使用Junit,直接使用assertArrayEquals(array1,array2)即可。