消息摘要算法-MAC

1、简述

mac(Message Authentication Code,消息认证码算法)是含有密钥散列函数算法,兼容了MD和SHA算法的特性,并在此基础上加上了密钥。因此MAC算法也经常被称作 HMAC算法。注意,经过mac算法得到的摘要值也可以使用十六进制编码表示,其摘要值得长度与实现算法的摘要值长度相同。例如 HmacSHA算法得到的摘要长度就是SHA1算法得到的摘要长度,都是160位二进制数,换算成十六进制的编码为40位。

2、模型分析

甲乙双方进行数据交换可以采取如下流程:

(1)、 甲方向乙方公布摘要算法(就是指定要使用的摘要算法名)

(2)、甲乙双方按照约定构造密钥,双方拥有相同的密钥(一般是一方构造密钥后通知另外一方,此过程不需要通过程序实现,就是双方约定个字符串,但是这个字符串可不是随便设定的,也是通过相关算法获取的)

(3)、甲方使用密钥对消息做摘要处理,然后将(2)生成的密钥和生成的摘要消息一同发送给乙方

(4)、乙方收到消息后,使用甲方已经公布的摘要算法+约定好的密钥 对收到的消息进行摘要处理。然后比对自己的摘要消息和甲方发过来的摘要消息。甄别消息是否是甲方发送过来的。

3、实现

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * sun 自带的
 */
public class MACCoder1 {

	/**
	 * 初始化HmacMD5的密钥 
	 * @return byte[] 密钥
	 */
	public static byte[] initHmacMD5Key(){
		try {
			//1、初始化 KeyGenerator
			KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacMD5");
			//2、产生密钥
			SecretKey secretKey = keyGenerator.generateKey();
			//3、获取密钥
			byte[] b = secretKey.getEncoded();
			return b;
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/** 
     * HmacMD5消息摘要 
     * @param data 待做摘要处理的数据 
     * @param key 密钥 
     * @return byte[] 消息摘要 
     * */ 
	public static byte[] encodeHmacMD5(byte[] data, byte[] key){		
		try {
			//还原密钥,因为密钥是以byte形式为消息传递算法所拥有  
			SecretKey secretKey = new SecretKeySpec(key, "HmacMD5");
			//实例化 mac
			Mac mac = Mac.getInstance(secretKey.getAlgorithm());
			//初始化Mac 密钥 
	        mac.init(secretKey);  
	        //执行消息摘要处理  
	        return mac.doFinal(data); 
		} catch (NoSuchAlgorithmException e){
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		}  
		return null;
	}
	
	public static void main(String[] args) throws Exception {
		String source = "mac 测试";
		byte[] key = initHmacMD5Key();
		byte[] ss = encodeHmacMD5(source.getBytes("utf-8"),key);
		System.out.println("md5 生成的 key:" + key);
		System.out.println("md5 加密后的消息:" + bytes2HexString(ss));
		
		System.out.println("-------------------------------------");
		key = initHmacSHA256Key();
		ss = encodeHmacSHA256(source.getBytes("utf-8"), key);
		System.out.println("SHA256 生成的 key:" + key);
		System.out.println("SHA256 加密后的消息:" + bytes2HexString(ss));
		
		/***Console 结果
		 *  md5 生成的 key:[B@73995d80
			md5 加密后的消息:02B0744A0BDAAD671324BE6BB411A31C
			-------------------------------------
			SHA256 生成的 key:[B@33bfc93a
			SHA256 加密后的消息:41AC24A928A9CFF77670FC8020DCA73ED7352364DA939162B0DFCCE6A4ECCB89
		 */
	}
	
	/**
     *把字节数组转换为16进制的形式 
     * @param b
     * @return
     */
     public static String bytes2HexString(byte[] b) {
        String ret = "";
        for (int i = 0; i < b.length; i++) {
             String hex = Integer.toHexString(b[ i ] & 0xFF);
             if (hex.length() == 1) {
                hex = '0' + hex;
             }
             ret += hex.toUpperCase();
        }
        return ret;
    }
     
     /**
 	 * 初始化HmacSHA256的密钥 
 	 * @return byte[] 密钥
 	 */
 	public static byte[] initHmacSHA256Key(){
 		try {
 			//1、初始化 KeyGenerator
 			KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacSHA256");
 			//2、产生密钥
 			SecretKey secretKey = keyGenerator.generateKey();
 			//3、获取密钥
 			byte[] b = secretKey.getEncoded();
 			return b;
 		} catch (NoSuchAlgorithmException e) {
 			e.printStackTrace();
 		}
 		return null;
 	} 
 	
 	/** 
     * HmacSHA256消息摘要 
     * @param data 待做摘要处理的数据 
     * @param key 密钥 
     * @return byte[] 消息摘要 
     * */ 
	public static byte[] encodeHmacSHA256(byte[] data, byte[] key){		
		try {
			//还原密钥,因为密钥是以byte形式为消息传递算法所拥有  
			SecretKey secretKey = new SecretKeySpec(key, "HmacSHA256");
			//实例化 mac
			Mac mac = Mac.getInstance(secretKey.getAlgorithm());
			//初始化Mac 密钥 
	        mac.init(secretKey);  
	        //执行消息摘要处理  
	        return mac.doFinal(data); 
		} catch (NoSuchAlgorithmException e){
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		}  
		return null;
	}
}

4、小结

(1)、sun支持了5中算法,但是不支持转成16进制,但是可以用commons codec或者bouncycastle的16进制转换协助进行转换

(2)、bouncycastle支持补充了三种算法,并支持16进制转换 

转载于:https://my.oschina.net/u/1387400/blog/1504564

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值