[t]消息摘要的概念:[/t]
唯一对应一个消息或文本的固定长度的值,由一个单向Hash加密函数对消息进行作用而产生。
消息摘要的分类:
(1)MD(Message Digest):消息摘要算法
(2)SHA(Secure Hash Algorithm):安全散列算法
(3)MAC(Message Authentication Code):消息认证码算法
应用:
验证数据完整性(防止在传输途中被篡改)

[t]MD 算法的编程使用[/t]
MD 算法的基本概念
为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护
2. MD 算法的种类
MD 系列算法(JDK)
| 算法 | 数据长度 | 摘要长度 | 
| MD2 | 任意 | 128 | 
| MD5 | 任意 | 128 | 
MD 算法编程使用:
[cc lang="java"]
// 初始化 MessageDigest
MessageDigest md5 = MessageDigest.getInstance("MD5");
// 更新
md5.update(data);
// 生成摘要
byte[] result= md5.digest();
[/cc]
[t]SHA 算法的编程使用[/t]
1. SHA 算法的基本概念
安全哈希算法,主要适用于数字签名标准里面定义的数字签名算法
2. SHA 算法的种类
SHA 系列算法(JDK)
| 算法 | 数据长度 | 摘要长度 | 
| SHA-1 | 任意 | 160 | 
| SHA-256 | 256 | |
| SHA-384 | 384 | |
| SHA-512 | 512 | 
SHA 系列算法编程使用:
/[cc lang="java"]
/ 初始化MessageDigest
MessageDigest sha = MessageDigest.getInstance("SHA");
// 更新
sha.update(data);
// 生成摘要
byte[] result= sha.digest();
[/cc]
 
[t]HMAC 算法的编程使用[/t]
引言:单一MD或SHA算法缺点?
摘要值容易被篡改!

HMAC 算法的基本概念
结合了MD5和SHA算法的优势,同时用密钥对摘要加密,是一种更为安全的消息摘要算法。

HMAC 算法的种类
HMAC 系列算法(JDK)
| 算法 | 数据长度 | 摘要长度 | 
| HmacMD5 | 任意 | 128 | 
| HmacSHA1 | 160 | |
| HmacSHA256 | 256 | |
| HmacSHA384 | 384 | |
| HmacSHA512 | 512 | 
如何生成密钥

2. 构建密钥
[cc lang="java"]
// 初始化 KeyGenerator
KeyGenerator keyGen = KeyGenerator.getInstance("HmacMD5");
// 产生密钥
SecretKey secretKey = keyGen.generateKey();
// 得到密钥字节数组
byte[] key = secretKey.getEncoded();
[/cc]
3. 执行消息摘要
[cc lang="java"]
// 从字节数组还原密钥
SecretKey secretKey = new SecretKeySpec(key, "HmacMD5");
// 实例化 Mac
Mac mac = Mac.getInstance("HmacMD5");
// 用密钥初始化 Mac
mac.init(secretKey);
// 执行消息摘要
byte[] result = mac.doFinal(data);
[/cc]
总结:
1. 散列函数特征:
(1)输入任意长度数据,输出固定长度散列值,计算很容易,过程不可逆
(2)对于某数据,其散列值固定
(3)两个数据不同,则对应的散列值也不同
(4)两个散列值不同,则对应的原始输入数据也不同
java代码实现
MessageDigestUtil.java
[cc lang="java"]
package cn.bcoder;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.security.DigestInputStream;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class MessageDigestUtil {
	public static String encryptMD5(byte[] data) throws NoSuchAlgorithmException{
		MessageDigest md5 = MessageDigest.getInstance("MD5");
		md5.update(data);
		byte[] resultBytes = md5.digest();
		String resultString = BytesToHex.fromBytesToHex(resultBytes);
		return resultString;
	}
	public static String getMD5OfFile(String path) throws Exception{
		FileInputStream fis = new FileInputStream(new File(path));
		DigestInputStream dis = new DigestInputStream(fis, MessageDigest.getInstance("MD5"));
		// 流输入
		byte[] buffer = new byte[1024];
		int read = dis.read(buffer, 0, 1024);
		while (read != -1){
			read = dis.read(buffer, 0, 1024);
		}
		MessageDigest md = dis.getMessageDigest();
		byte[] resultBytes = md.digest();
		String resultString = BytesToHex.fromBytesToHex(resultBytes);
		return resultString;
	}
	public static String encryptSHA(byte[] data) throws NoSuchAlgorithmException{
		MessageDigest sha = MessageDigest.getInstance("SHA-512");
		sha.update(data);
		byte[] resultBytes = sha.digest();
		String resultString = BytesToHex.fromBytesToHex(resultBytes);
		return resultString;
	}
	public static byte[] initHmacKey() throws Exception{
		KeyGenerator keyGen = KeyGenerator.getInstance("HmacSHA512");
		SecretKey secretKey = keyGen.generateKey();
		return secretKey.getEncoded();
	}
	public static String encryptHmac(byte[] data, byte[] key) throws NoSuchAlgorithmException, InvalidKeyException{
		SecretKey secretKey = new SecretKeySpec(key, "HmacSHA512");
		Mac mac = Mac.getInstance("HmacSHA512");
		mac.init(secretKey);
		byte[] resultBytes = mac.doFinal(data);
		String resultString = BytesToHex.fromBytesToHex(resultBytes);
		return resultString;
	}
}
[/cc]
Main.java
[cc lang="java"]
import java.io.IOException;
package cn.bcoder;
public class Main {
	//待加密的明文
	public static final String DATA = "bcoder.clbug.com";
	public static final String PATH = "mysql-installer-web-community-5.6.22.0.msi";
public static void main(String[] args) throws Exception {
		/* Test MD5 */
		String md5Result = MessageDigestUtil.encryptMD5(DATA.getBytes());
		System.out.println(DATA + ">>>MD5>>>" + md5Result);
		/* Test MD5 of File */
		String fileMD5Result = MessageDigestUtil.getMD5OfFile(PATH);
		System.out.println("File MD5 : " + fileMD5Result);
		/* Test SHA */
		String shaResult = MessageDigestUtil.encryptSHA(DATA.getBytes());
		System.out.println(DATA + ">>>SHA>>>" + shaResult);
		/* Test HMAC */
		byte[] hmacKey = MessageDigestUtil.initHmacKey();
		System.out.println("HMAC KEY: " + BytesToHex.fromBytesToHex(hmacKey));
		String hmacResult = MessageDigestUtil.encryptHmac(DATA.getBytes(), hmacKey);
		System.out.println(DATA + ">>>HMAC>>>" + hmacResult);	
}
}
[/cc]

