JAVA加解密8-消息摘要算法-MAC算法系列

一、简述
mac(Message Authentication Code,消息认证码算法)是含有密钥散列函数算法,兼容了MD和SHA算法的特性,并在此基础上加上了密钥。因此MAC算法也经常被称作HMAC算法。关于hmac算法的详情可以参看RFC 2104(http://www.ietf.org/rfc/rfc2104.txt),这里包含了HmacMD5算法的C语言实现。
这里需要说明的是经过mac算法得到的摘要值也可以使用十六进制编码表示,其摘要值得长度与实现算法的摘要值长度相同。例如 HmacSHA算法得到的摘要长度就是SHA1算法得到的摘要长度,都是160位二进制数,换算成十六进制的编码为40位。

二、模型分析
甲乙双方进行数据交换可以采取如下流程完成
1、甲方向乙方公布摘要算法(就是指定要使用的摘要算法名)
2、甲乙双方按照约定构造密钥,双方拥有相同的密钥(一般是一方构造密钥后通知另外一方,此过程不需要通过程序实现,就是双方约定个字符串,但是这个字符串可不是随便设定的,也是通过相关算法获取的)
3、甲方使用密钥对消息做摘要处理,然后将消息和生成的摘要消息一同发送给乙方
4、乙方收到消息后,使用甲方已经公布的摘要算法+约定好的密钥 对收到的消息进行摘要处理。然后比对自己的摘要消息和甲方发过来的摘要消息。甄别消息是否是甲方发送过来的

三、MAC系列算法支持表

算法 摘要长度 备注
HmacMD5 128 JAVA6实现
HmacSHA1 160 JAVA6实现
HmacSHA256 256 JAVA6实现
HmacSHA384 384 JAVA6实现
HmacSHA512 512 JAVA6实现
HmacMD2 128 BouncyCastle实现
HmacMD4 128 BouncyCastle实现
HmacSHA224 224 BouncyCastle实现

四、sun以及bouncycastle的hmac算法实现

package com.ca.test;
import java.security.Security;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;
/**
 * MAC消息摘要组件
 * @author kongqz
 * */
public class MACCoder {
///////////////////////////HmacMD5///////////////////////////////
    /**
     * 初始化HmacMD5的密钥
     * @return byte[] 密钥
     * 
     * */
    public static byte[] initHmacMD5Key() throws Exception{
        //初始化KeyGenerator
        KeyGenerator keyGenerator=KeyGenerator.getInstance("HmacMD5");
        //产生密钥
        SecretKey secretKey=keyGenerator.generateKey();
        //获取密钥
        return secretKey.getEncoded();
    }
    /**
     * HmacMD5消息摘要
     * @param data 待做摘要处理的数据
     * @param key 密钥
     * @return  byte[] 消息摘要
     * */
    public static byte[] encodeHmacMD5(byte[] data,byte[] key) throws Exception{
        //还原密钥,因为密钥是以byte形式为消息传递算法所拥有
        SecretKey secretKey=new SecretKeySpec(key,"HmacMD5");
        //实例化Mac
        Mac mac=Mac.getInstance(secretKey.getAlgorithm());
        //初始化Mac
        mac.init(secretKey);
        //执行消息摘要处理
        return mac.doFinal(data);
    }
    
///////////////////////////////HmacSHA1//////////////////////////////////
    /**
     * 初始化HmacSHA1的密钥
     * @return byte[] 密钥
     * 
     * */
    public static byte[] initHmacSHAKey() throws Exception{
        //初始化KeyGenerator
        KeyGenerator keyGenerator=KeyGenerator.getInstance("HmacSHA1");
        //产生密钥
        SecretKey secretKey=keyGenerator.generateKey();
        //获取密钥
        return secretKey.getEncoded();
    }
    /**
     * HmacSHA1消息摘要
     * @param data 待做摘要处理的数据
     * @param key 密钥
     * @return  byte[] 消息摘要
     * */
    public static byte[] encodeHmacSHA(byte[] data,byte[] key) throws Exception{
        //还原密钥,因为密钥是以byte形式为消息传递算法所拥有
        SecretKey secretKey=new SecretKeySpec(key,"HmacSHA1");
        //实例化Mac
        Mac mac=Mac.getInstance(secretKey.getAlgorithm());
        //初始化Mac
        mac.init(secretKey);
        //执行消息摘要处理
        return mac.doFinal(data);
    }
    
///////////////////////////////HmacSHA256//////////////////////////////////
    /**
     * 初始化HmacSHA256的密钥
     * @return byte[] 密钥
     * 
     * */
    public static byte[] initHmacSHA256Key() throws Exception{
        //初始化KeyGenerator
        KeyGenerator keyGenerator=KeyGenerator.getInstance("HmacSHA256");
        //产生密钥
        SecretKey secretKey=keyGenerator.generateKey();
        //获取密钥
        return secretKey.getEncoded();
    }
    /**
     * HmacSHA256消息摘要
     * @param data 待做摘要处理的数据
     * @param key 密钥
     * @return  byte[] 消息摘要
     * */
    public static byte[] encodeHmacSHA256(byte[] data,byte[] key) throws Exception{
        //还原密钥,因为密钥是以byte形式为消息传递算法所拥有
        SecretKey secretKey=new SecretKeySpec(key,"HmacSHA256");
        //实例化Mac
        Mac mac=Mac.getInstance(secretKey.getAlgorithm());
        //初始化Mac
        mac.init(secretKey);
        //执行消息摘要处理
        return mac.doFinal(data);
    }
    
///////////////////////////////HmacSHA384//////////////////////////////////
    /**
     * 初始化HmacSHA384的密钥
     * @return byte[] 密钥
     * 
     * */
    public static byte[] initHmacSHA384Key() throws Exception{
        //初始化KeyGenerator
        KeyGenerator keyGenerator=KeyGenerator.getInstance("HmacSHA384");
        //产生密钥
        SecretKey secretKey=keyGenerator.generateKey();
        //获取密钥
        return secretKey.getEncoded();
    }
    /**
     * HmacSHA384消息摘要
     * @param data 待做摘要处理的数据
     * @param key 密钥
     * @return  byte[] 消息摘要
     * */
    public static byte[] encodeHmacSHA384(byte[] data,byte[] key) throws Exception{
        //还原密钥,因为密钥是以byte形式为消息传递算法所拥有
        SecretKey secretKey=new SecretKeySpec(key,"HmacSHA384");
        //实例化Mac
        Mac mac=Mac.getInstance(secretKey.getAlgorithm());
        //初始化Mac
        mac.init(secretKey);
        //执行消息摘要处理
        return mac.doFinal(data);
    }
    
///////////////////////////////HmacSHA512//////////////////////////////////
    /**
     * 初始化HmacSHA512的密钥
     * @return byte[] 密钥
     * 
     * */
    public static byte[] initHmacSHA512Key() throws Exception{
        //初始化KeyGenerator
        KeyGenerator keyGenerator=KeyGenerator.getInstance("HmacSHA512");
        //产生密钥
        SecretKey secretKey=keyGenerator.generateKey();
        //获取密钥
        return secretKey.getEncoded();
    }
    /**
     * HmacSHA512消息摘要
     * @param data 待做摘要处理的数据
     * @param key 密钥
     * @return  byte[] 消息摘要
     * */
    public static byte[] encodeHmacSHA512(byte[] data,byte[] key) throws Exception{
        //还原密钥,因为密钥是以byte形式为消息传递算法所拥有
        SecretKey secretKey=new SecretKeySpec(key,"HmacSHA512");
        //实例化Mac
        Mac mac=Mac.getInstance(secretKey.getAlgorithm());
        //初始化Mac
        mac.init(secretKey);
        //执行消息摘要处理
        return mac.doFinal(data);
    }
///////////////////////////////HmacMD2-BouncyCastle才支持的实现//////////////////////////////////
    /**
     * 初始化HmacMD2的密钥
     * @return byte[] 密钥
     * */
    public static byte[] initHmacMD2Key() throws Exception{
        
        //加入BouncyCastleProvider的支持
        Security.addProvider(new BouncyCastleProvider());
        //初始化KeyGenerator
        KeyGenerator keyGenerator=KeyGenerator.getInstance("HmacMD2");
        //产生密钥
        SecretKey secretKey=keyGenerator.generateKey();
        //获取密钥
        return secretKey.getEncoded();
    }
    /**
     * HmacMD2消息摘要
     * @param data 待做摘要处理的数据
     * @param key 密钥
     * @return  byte[] 消息摘要
     * */
    public static byte[] encodeHmacMD2(byte[] data,byte[] key) throws Exception{
        //加入BouncyCastleProvider的支持
        Security.addProvider(new BouncyCastleProvider());
        //还原密钥,因为密钥是以byte形式为消息传递算法所拥有
        SecretKey secretKey=new SecretKeySpec(key,"HmacMD2");
        //实例化Mac
        Mac mac=Mac.getInstance(secretKey.getAlgorithm());
        //初始化Mac
        mac.init(secretKey);
        //执行消息摘要处理
        return mac.doFinal(data);
    }
    /**
     * HmacMD2Hex消息摘要
     * @param data 待做消息摘要处理的数据
     * @param String 密钥
     * @return byte[] 消息摘要
     * */
    public static String encodeHmacMD2Hex(byte[] data,byte[] key) throws Exception{
        //执行消息摘要处理
        byte[] b=encodeHmacMD2(data,key);
        //做十六进制转换
        return new String(Hex.encode(b));
    }
    
///////////////////////////////HmacMD4-BouncyCastle才支持的实现//////////////////////////////////
    /**
     * 初始化HmacMD2的密钥
     * @return byte[] 密钥
     * */
    public static byte[] initHmacMD4Key() throws Exception{
        
        //加入BouncyCastleProvider的支持
        Security.addProvider(new BouncyCastleProvider());
        //初始化KeyGenerator
        KeyGenerator keyGenerator=KeyGenerator.getInstance("HmacMD4");
        //产生密钥
        SecretKey secretKey=keyGenerator.generateKey();
        //获取密钥
        return secretKey.getEncoded();
    }
    /**
     * HmacMD4消息摘要
     * @param data 待做摘要处理的数据
     * @param key 密钥
     * @return  byte[] 消息摘要
     * */
    public static byte[] encodeHmacMD4(byte[] data,byte[] key) throws Exception{
        //加入BouncyCastleProvider的支持
        Security.addProvider(new BouncyCastleProvider());
        //还原密钥,因为密钥是以byte形式为消息传递算法所拥有
        SecretKey secretKey=new SecretKeySpec(key,"HmacMD4");
        //实例化Mac
        Mac mac=Mac.getInstance(secretKey.getAlgorithm());
        //初始化Mac
        mac.init(secretKey);
        //执行消息摘要处理
        return mac.doFinal(data);
    }
    /**
     * HmacMD4Hex消息摘要
     * @param data 待做消息摘要处理的数据
     * @param String 密钥
     * @return byte[] 消息摘要
     * */
    public static String encodeHmacMD4Hex(byte[] data,byte[] key) throws Exception{
        //执行消息摘要处理
        byte[] b=encodeHmacMD4(data,key);
        //做十六进制转换
        return new String(Hex.encode(b));
    }
///////////////////////////////HmacSHA224-BouncyCastle才支持的实现//////////////////////////////////
    /**
     * 初始化HmacSHA224的密钥
     * @return byte[] 密钥
     * */
    public static byte[] initHmacSHA224Key() throws Exception{
        
        //加入BouncyCastleProvider的支持
        Security.addProvider(new BouncyCastleProvider());
        //初始化KeyGenerator
        KeyGenerator keyGenerator=KeyGenerator.getInstance("HmacSHA224");
        //产生密钥
        SecretKey secretKey=keyGenerator.generateKey();
        //获取密钥
        return secretKey.getEncoded();
    }
    /**
     * HmacSHA224消息摘要
     * @param data 待做摘要处理的数据
     * @param key 密钥
     * @return  byte[] 消息摘要
     * */
    public static byte[] encodeHmacSHA224(byte[] data,byte[] key) throws Exception{
        //加入BouncyCastleProvider的支持
        Security.addProvider(new BouncyCastleProvider());
        //还原密钥,因为密钥是以byte形式为消息传递算法所拥有
        SecretKey secretKey=new SecretKeySpec(key,"HmacSHA224");
        //实例化Mac
        Mac mac=Mac.getInstance(secretKey.getAlgorithm());
        //初始化Mac
        mac.init(secretKey);
        //执行消息摘要处理
        return mac.doFinal(data);
    }
    /**
     * HmacSHA224Hex消息摘要
     * @param data 待做消息摘要处理的数据
     * @param String 密钥
     * @return byte[] 消息摘要
     * */
    public static String encodeHmacSHA224Hex(byte[] data,byte[] key) throws Exception{
        //执行消息摘要处理
        byte[] b=encodeHmacSHA224(data,key);
        //做十六进制转换
        return new String(Hex.encode(b));
    }
    /**
     * 进行相关的摘要算法的处理展示
     * @throws Exception 
     * **/
    public static void main(String[] args) throws Exception {
        String str="HmacMD5消息摘要";
        //初始化密钥
        byte[] key1=MACCoder.initHmacMD5Key();
        //获取摘要信息
        byte[] data1=MACCoder.encodeHmacMD5(str.getBytes(), key1);
        
        System.out.println("原文:"+str);
        System.out.println();
        System.out.println("HmacMD5的密钥:"+key1.toString());
        System.out.println("HmacMD5算法摘要:"+data1.toString());
        System.out.println();
        
        //初始化密钥
        byte[] key2=MACCoder.initHmacSHA256Key();
        //获取摘要信息
        byte[] data2=MACCoder.encodeHmacSHA256(str.getBytes(), key2);
        System.out.println("HmacSHA256的密钥:"+key2.toString());
        System.out.println("HmacSHA256算法摘要:"+data2.toString());
        System.out.println();
        
        
        //初始化密钥
        byte[] key3=MACCoder.initHmacSHAKey();
        //获取摘要信息
        byte[] data3=MACCoder.encodeHmacSHA(str.getBytes(), key3);
        System.out.println("HmacSHA1的密钥:"+key3.toString());
        System.out.println("HmacSHA1算法摘要:"+data3.toString());
        System.out.println();
        
        
        //初始化密钥
        byte[] key4=MACCoder.initHmacSHA384Key();
        //获取摘要信息
        byte[] data4=MACCoder.encodeHmacSHA384(str.getBytes(), key4);
        System.out.println("HmacSHA384的密钥:"+key4.toString());
        System.out.println("HmacSHA384算法摘要:"+data4.toString());
        System.out.println();
        
        
        //初始化密钥
        byte[] key5=MACCoder.initHmacSHA512Key();
        //获取摘要信息
        byte[] data5=MACCoder.encodeHmacSHA512(str.getBytes(), key5);
        System.out.println("HmacSHA512的密钥:"+key5.toString());
        System.out.println("HmacSHA512算法摘要:"+data5.toString());
        System.out.println();
        
        System.out.println("================以下的算法支持是bouncycastle支持的算法,sun java6不支持=======================");
        //初始化密钥
        byte[] key6=MACCoder.initHmacMD2Key();
        //获取摘要信息
        byte[] data6=MACCoder.encodeHmacMD2(str.getBytes(), key6);
        String datahex6=MACCoder.encodeHmacMD2Hex(str.getBytes(), key6);
        System.out.println("Bouncycastle HmacMD2的密钥:"+key6.toString());
        System.out.println("Bouncycastle HmacMD2算法摘要:"+data6.toString());
        System.out.println("Bouncycastle HmacMD2Hex算法摘要:"+datahex6.toString());
        System.out.println();
        
        //初始化密钥
        byte[] key7=MACCoder.initHmacMD4Key();
        //获取摘要信息
        byte[] data7=MACCoder.encodeHmacMD4(str.getBytes(), key7);
        String datahex7=MACCoder.encodeHmacMD4Hex(str.getBytes(), key7);
        System.out.println("Bouncycastle HmacMD4的密钥:"+key7.toString());
        System.out.println("Bouncycastle HmacMD4算法摘要:"+data7.toString());
        System.out.println("Bouncycastle HmacMD4Hex算法摘要:"+datahex7.toString());
        System.out.println();
        
        //初始化密钥
        byte[] key8=MACCoder.initHmacSHA224Key();
        //获取摘要信息
        byte[] data8=MACCoder.encodeHmacSHA224(str.getBytes(), key8);
        String datahex8=MACCoder.encodeHmacSHA224Hex(str.getBytes(), key8);
        System.out.println("Bouncycastle HmacSHA224的密钥:"+key8.toString());
        System.out.println("Bouncycastle HmacSHA224算法摘要:"+data8.toString());
        System.out.println("Bouncycastle HmacSHA224算法摘要:"+datahex8.toString());
        System.out.println();
    }
}
控制台输出结果如下:
原文:HmacMD5消息摘要
HmacMD5的密钥:[B@136228
HmacMD5算法摘要:[B@913750
HmacSHA256的密钥:[B@bfbdb0
HmacSHA256算法摘要:[B@3e86d0
HmacSHA1的密钥:[B@253498
HmacSHA1算法摘要:[B@9fef6f
HmacSHA384的密钥:[B@f38798
HmacSHA384算法摘要:[B@4b222f
HmacSHA512的密钥:[B@b0f13d
HmacSHA512算法摘要:[B@ae000d
================以下的算法支持是bouncycastle支持的算法,sun java6不支持=======================
Bouncycastle HmacMD2的密钥:[B@4741d6
Bouncycastle HmacMD2算法摘要:[B@337d0f
Bouncycastle HmacMD2Hex算法摘要:0fbabb3bb1a2be81fbc823013f6920fe
Bouncycastle HmacMD4的密钥:[B@1e0bc08
Bouncycastle HmacMD4算法摘要:[B@158b649
Bouncycastle HmacMD4Hex算法摘要:a3fa5935ca554f83c8987efd2bcfe605
Bouncycastle HmacSHA224的密钥:[B@8a0d5d
Bouncycastle HmacSHA224算法摘要:[B@173831b
Bouncycastle HmacSHA224算法摘要:542d47250e5ff9f8bb3a7607799b1685a8accd65580410ea1d4dd578
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,265评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,078评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,852评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,408评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,445评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,772评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,921评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,688评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,130评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,467评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,617评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,276评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,882评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,740评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,967评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,315评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,486评论 2 348

推荐阅读更多精彩内容

  • 本文主要介绍移动端的加解密算法的分类、其优缺点特性及应用,帮助读者由浅入深地了解和选择加解密算法。文中会包含算法的...
    苹果粉阅读 11,470评论 5 29
  • 消息摘要算法 友情提示,本文档的图床使用极简图床进行图片存储,默认存储到七牛云空间 本文档依赖的jar maven...
    Mr_魏阅读 960评论 0 3
  • 在开发应用过程中,客户端与服务端经常需要进行数据传输,涉及到重要隐私安全信息时,开发者自然会想到对其进行加密,即使...
    闲庭阅读 3,262评论 0 11
  • 这篇文章主要讲述在Mobile BI(移动商务智能)开发过程中,在网络通信、数据存储、登录验证这几个方面涉及的加密...
    雨_树阅读 2,354评论 0 6
  • 一、简述对称加密算法就是能将数据加解密。加密的时候用密钥对数据进行加密,解密的时候使用同样的密钥对数据进行解密。D...
    K1024阅读 1,094评论 0 1