消息摘要算法-MAC算法系列

来源:互联网 发布:白城广逸网络地点 编辑:程序博客网 时间:2024/04/30 23:23

一、简述

  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系列算法支持表

 

算法摘要长度备注HmacMD5128JAVA6实现HmacSHA1160JAVA6实现HmacSHA256256JAVA6实现HmacSHA384384JAVA6实现HmacSHA512512JAVA6实现HmacMD2128BouncyCastle实现HmacMD4128BouncyCastle实现HmacSHA224224BouncyCastle实现

 

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

[java] view plaincopyprint?
  1. package com.ca.test;  
  2. import java.security.Security;  
  3. import javax.crypto.KeyGenerator;  
  4. import javax.crypto.Mac;  
  5. import javax.crypto.SecretKey;  
  6. import javax.crypto.spec.SecretKeySpec;  
  7. import org.bouncycastle.jce.provider.BouncyCastleProvider;  
  8. import org.bouncycastle.util.encoders.Hex;  
  9. /** 
  10.  * MAC消息摘要组件 
  11.  * @author kongqz 
  12.  * */  
  13. public class MACCoder {  
  14. ///////////////////////////HmacMD5///////////////////////////////  
  15.     /** 
  16.      * 初始化HmacMD5的密钥 
  17.      * @return byte[] 密钥 
  18.      *  
  19.      * */  
  20.     public static byte[] initHmacMD5Key() throws Exception{  
  21.         //初始化KeyGenerator   
  22.         KeyGenerator keyGenerator=KeyGenerator.getInstance("HmacMD5");  
  23.         //产生密钥   
  24.         SecretKey secretKey=keyGenerator.generateKey();  
  25.         //获取密钥   
  26.         return secretKey.getEncoded();  
  27.     }  
  28.     /** 
  29.      * HmacMD5消息摘要 
  30.      * @param data 待做摘要处理的数据 
  31.      * @param key 密钥 
  32.      * @return  byte[] 消息摘要 
  33.      * */  
  34.     public static byte[] encodeHmacMD5(byte[] data,byte[] key) throws Exception{  
  35.         //还原密钥,因为密钥是以byte形式为消息传递算法所拥有   
  36.         SecretKey secretKey=new SecretKeySpec(key,"HmacMD5");  
  37.         //实例化Mac   
  38.         Mac mac=Mac.getInstance(secretKey.getAlgorithm());  
  39.         //初始化Mac   
  40.         mac.init(secretKey);  
  41.         //执行消息摘要处理   
  42.         return mac.doFinal(data);  
  43.     }  
  44.       
  45. ///////////////////////////////HmacSHA1//////////////////////////////////  
  46.     /** 
  47.      * 初始化HmacSHA1的密钥 
  48.      * @return byte[] 密钥 
  49.      *  
  50.      * */  
  51.     public static byte[] initHmacSHAKey() throws Exception{  
  52.         //初始化KeyGenerator   
  53.         KeyGenerator keyGenerator=KeyGenerator.getInstance("HmacSHA1");  
  54.         //产生密钥   
  55.         SecretKey secretKey=keyGenerator.generateKey();  
  56.         //获取密钥   
  57.         return secretKey.getEncoded();  
  58.     }  
  59.     /** 
  60.      * HmacSHA1消息摘要 
  61.      * @param data 待做摘要处理的数据 
  62.      * @param key 密钥 
  63.      * @return  byte[] 消息摘要 
  64.      * */  
  65.     public static byte[] encodeHmacSHA(byte[] data,byte[] key) throws Exception{  
  66.         //还原密钥,因为密钥是以byte形式为消息传递算法所拥有   
  67.         SecretKey secretKey=new SecretKeySpec(key,"HmacSHA1");  
  68.         //实例化Mac   
  69.         Mac mac=Mac.getInstance(secretKey.getAlgorithm());  
  70.         //初始化Mac   
  71.         mac.init(secretKey);  
  72.         //执行消息摘要处理   
  73.         return mac.doFinal(data);  
  74.     }  
  75.       
  76. ///////////////////////////////HmacSHA256//////////////////////////////////  
  77.     /** 
  78.      * 初始化HmacSHA256的密钥 
  79.      * @return byte[] 密钥 
  80.      *  
  81.      * */  
  82.     public static byte[] initHmacSHA256Key() throws Exception{  
  83.         //初始化KeyGenerator   
  84.         KeyGenerator keyGenerator=KeyGenerator.getInstance("HmacSHA256");  
  85.         //产生密钥   
  86.         SecretKey secretKey=keyGenerator.generateKey();  
  87.         //获取密钥   
  88.         return secretKey.getEncoded();  
  89.     }  
  90.     /** 
  91.      * HmacSHA256消息摘要 
  92.      * @param data 待做摘要处理的数据 
  93.      * @param key 密钥 
  94.      * @return  byte[] 消息摘要 
  95.      * */  
  96.     public static byte[] encodeHmacSHA256(byte[] data,byte[] key) throws Exception{  
  97.         //还原密钥,因为密钥是以byte形式为消息传递算法所拥有   
  98.         SecretKey secretKey=new SecretKeySpec(key,"HmacSHA256");  
  99.         //实例化Mac   
  100.         Mac mac=Mac.getInstance(secretKey.getAlgorithm());  
  101.         //初始化Mac   
  102.         mac.init(secretKey);  
  103.         //执行消息摘要处理   
  104.         return mac.doFinal(data);  
  105.     }  
  106.       
  107. ///////////////////////////////HmacSHA384//////////////////////////////////  
  108.     /** 
  109.      * 初始化HmacSHA384的密钥 
  110.      * @return byte[] 密钥 
  111.      *  
  112.      * */  
  113.     public static byte[] initHmacSHA384Key() throws Exception{  
  114.         //初始化KeyGenerator   
  115.         KeyGenerator keyGenerator=KeyGenerator.getInstance("HmacSHA384");  
  116.         //产生密钥   
  117.         SecretKey secretKey=keyGenerator.generateKey();  
  118.         //获取密钥   
  119.         return secretKey.getEncoded();  
  120.     }  
  121.     /** 
  122.      * HmacSHA384消息摘要 
  123.      * @param data 待做摘要处理的数据 
  124.      * @param key 密钥 
  125.      * @return  byte[] 消息摘要 
  126.      * */  
  127.     public static byte[] encodeHmacSHA384(byte[] data,byte[] key) throws Exception{  
  128.         //还原密钥,因为密钥是以byte形式为消息传递算法所拥有   
  129.         SecretKey secretKey=new SecretKeySpec(key,"HmacSHA384");  
  130.         //实例化Mac   
  131.         Mac mac=Mac.getInstance(secretKey.getAlgorithm());  
  132.         //初始化Mac   
  133.         mac.init(secretKey);  
  134.         //执行消息摘要处理   
  135.         return mac.doFinal(data);  
  136.     }  
  137.       
  138. ///////////////////////////////HmacSHA512//////////////////////////////////  
  139.     /** 
  140.      * 初始化HmacSHA512的密钥 
  141.      * @return byte[] 密钥 
  142.      *  
  143.      * */  
  144.     public static byte[] initHmacSHA512Key() throws Exception{  
  145.         //初始化KeyGenerator   
  146.         KeyGenerator keyGenerator=KeyGenerator.getInstance("HmacSHA512");  
  147.         //产生密钥   
  148.         SecretKey secretKey=keyGenerator.generateKey();  
  149.         //获取密钥   
  150.         return secretKey.getEncoded();  
  151.     }  
  152.     /** 
  153.      * HmacSHA512消息摘要 
  154.      * @param data 待做摘要处理的数据 
  155.      * @param key 密钥 
  156.      * @return  byte[] 消息摘要 
  157.      * */  
  158.     public static byte[] encodeHmacSHA512(byte[] data,byte[] key) throws Exception{  
  159.         //还原密钥,因为密钥是以byte形式为消息传递算法所拥有   
  160.         SecretKey secretKey=new SecretKeySpec(key,"HmacSHA512");  
  161.         //实例化Mac   
  162.         Mac mac=Mac.getInstance(secretKey.getAlgorithm());  
  163.         //初始化Mac   
  164.         mac.init(secretKey);  
  165.         //执行消息摘要处理   
  166.         return mac.doFinal(data);  
  167.     }  
  168. ///////////////////////////////HmacMD2-BouncyCastle才支持的实现//////////////////////////////////  
  169.     /** 
  170.      * 初始化HmacMD2的密钥 
  171.      * @return byte[] 密钥 
  172.      * */  
  173.     public static byte[] initHmacMD2Key() throws Exception{  
  174.           
  175.         //加入BouncyCastleProvider的支持   
  176.         Security.addProvider(new BouncyCastleProvider());  
  177.         //初始化KeyGenerator   
  178.         KeyGenerator keyGenerator=KeyGenerator.getInstance("HmacMD2");  
  179.         //产生密钥   
  180.         SecretKey secretKey=keyGenerator.generateKey();  
  181.         //获取密钥   
  182.         return secretKey.getEncoded();  
  183.     }  
  184.     /** 
  185.      * HmacMD2消息摘要 
  186.      * @param data 待做摘要处理的数据 
  187.      * @param key 密钥 
  188.      * @return  byte[] 消息摘要 
  189.      * */  
  190.     public static byte[] encodeHmacMD2(byte[] data,byte[] key) throws Exception{  
  191.         //加入BouncyCastleProvider的支持   
  192.         Security.addProvider(new BouncyCastleProvider());  
  193.         //还原密钥,因为密钥是以byte形式为消息传递算法所拥有   
  194.         SecretKey secretKey=new SecretKeySpec(key,"HmacMD2");  
  195.         //实例化Mac   
  196.         Mac mac=Mac.getInstance(secretKey.getAlgorithm());  
  197.         //初始化Mac   
  198.         mac.init(secretKey);  
  199.         //执行消息摘要处理   
  200.         return mac.doFinal(data);  
  201.     }  
  202.     /** 
  203.      * HmacMD2Hex消息摘要 
  204.      * @param data 待做消息摘要处理的数据 
  205.      * @param String 密钥 
  206.      * @return byte[] 消息摘要 
  207.      * */  
  208.     public static String encodeHmacMD2Hex(byte[] data,byte[] key) throws Exception{  
  209.         //执行消息摘要处理   
  210.         byte[] b=encodeHmacMD2(data,key);  
  211.         //做十六进制转换   
  212.         return new String(Hex.encode(b));  
  213.     }  
  214.       
  215. ///////////////////////////////HmacMD4-BouncyCastle才支持的实现//////////////////////////////////  
  216.     /** 
  217.      * 初始化HmacMD2的密钥 
  218.      * @return byte[] 密钥 
  219.      * */  
  220.     public static byte[] initHmacMD4Key() throws Exception{  
  221.           
  222.         //加入BouncyCastleProvider的支持   
  223.         Security.addProvider(new BouncyCastleProvider());  
  224.         //初始化KeyGenerator   
  225.         KeyGenerator keyGenerator=KeyGenerator.getInstance("HmacMD4");  
  226.         //产生密钥   
  227.         SecretKey secretKey=keyGenerator.generateKey();  
  228.         //获取密钥   
  229.         return secretKey.getEncoded();  
  230.     }  
  231.     /** 
  232.      * HmacMD4消息摘要 
  233.      * @param data 待做摘要处理的数据 
  234.      * @param key 密钥 
  235.      * @return  byte[] 消息摘要 
  236.      * */  
  237.     public static byte[] encodeHmacMD4(byte[] data,byte[] key) throws Exception{  
  238.         //加入BouncyCastleProvider的支持   
  239.         Security.addProvider(new BouncyCastleProvider());  
  240.         //还原密钥,因为密钥是以byte形式为消息传递算法所拥有   
  241.         SecretKey secretKey=new SecretKeySpec(key,"HmacMD4");  
  242.         //实例化Mac   
  243.         Mac mac=Mac.getInstance(secretKey.getAlgorithm());  
  244.         //初始化Mac   
  245.         mac.init(secretKey);  
  246.         //执行消息摘要处理   
  247.         return mac.doFinal(data);  
  248.     }  
  249.     /** 
  250.      * HmacMD4Hex消息摘要 
  251.      * @param data 待做消息摘要处理的数据 
  252.      * @param String 密钥 
  253.      * @return byte[] 消息摘要 
  254.      * */  
  255.     public static String encodeHmacMD4Hex(byte[] data,byte[] key) throws Exception{  
  256.         //执行消息摘要处理   
  257.         byte[] b=encodeHmacMD4(data,key);  
  258.         //做十六进制转换   
  259.         return new String(Hex.encode(b));  
  260.     }  
  261. ///////////////////////////////HmacSHA224-BouncyCastle才支持的实现//////////////////////////////////  
  262.     /** 
  263.      * 初始化HmacSHA224的密钥 
  264.      * @return byte[] 密钥 
  265.      * */  
  266.     public static byte[] initHmacSHA224Key() throws Exception{  
  267.           
  268.         //加入BouncyCastleProvider的支持   
  269.         Security.addProvider(new BouncyCastleProvider());  
  270.         //初始化KeyGenerator   
  271.         KeyGenerator keyGenerator=KeyGenerator.getInstance("HmacSHA224");  
  272.         //产生密钥   
  273.         SecretKey secretKey=keyGenerator.generateKey();  
  274.         //获取密钥   
  275.         return secretKey.getEncoded();  
  276.     }  
  277.     /** 
  278.      * HmacSHA224消息摘要 
  279.      * @param data 待做摘要处理的数据 
  280.      * @param key 密钥 
  281.      * @return  byte[] 消息摘要 
  282.      * */  
  283.     public static byte[] encodeHmacSHA224(byte[] data,byte[] key) throws Exception{  
  284.         //加入BouncyCastleProvider的支持   
  285.         Security.addProvider(new BouncyCastleProvider());  
  286.         //还原密钥,因为密钥是以byte形式为消息传递算法所拥有   
  287.         SecretKey secretKey=new SecretKeySpec(key,"HmacSHA224");  
  288.         //实例化Mac   
  289.         Mac mac=Mac.getInstance(secretKey.getAlgorithm());  
  290.         //初始化Mac   
  291.         mac.init(secretKey);  
  292.         //执行消息摘要处理   
  293.         return mac.doFinal(data);  
  294.     }  
  295.     /** 
  296.      * HmacSHA224Hex消息摘要 
  297.      * @param data 待做消息摘要处理的数据 
  298.      * @param String 密钥 
  299.      * @return byte[] 消息摘要 
  300.      * */  
  301.     public static String encodeHmacSHA224Hex(byte[] data,byte[] key) throws Exception{  
  302.         //执行消息摘要处理   
  303.         byte[] b=encodeHmacSHA224(data,key);  
  304.         //做十六进制转换   
  305.         return new String(Hex.encode(b));  
  306.     }  
  307.     /** 
  308.      * 进行相关的摘要算法的处理展示 
  309.      * @throws Exception  
  310.      * **/  
  311.     public static void main(String[] args) throws Exception {  
  312.         String str="HmacMD5消息摘要";  
  313.         //初始化密钥   
  314.         byte[] key1=MACCoder.initHmacMD5Key();  
  315.         //获取摘要信息   
  316.         byte[] data1=MACCoder.encodeHmacMD5(str.getBytes(), key1);  
  317.           
  318.         System.out.println("原文:"+str);  
  319.         System.out.println();  
  320.         System.out.println("HmacMD5的密钥:"+key1.toString());  
  321.         System.out.println("HmacMD5算法摘要:"+data1.toString());  
  322.         System.out.println();  
  323.           
  324.         //初始化密钥   
  325.         byte[] key2=MACCoder.initHmacSHA256Key();  
  326.         //获取摘要信息   
  327.         byte[] data2=MACCoder.encodeHmacSHA256(str.getBytes(), key2);  
  328.         System.out.println("HmacSHA256的密钥:"+key2.toString());  
  329.         System.out.println("HmacSHA256算法摘要:"+data2.toString());  
  330.         System.out.println();  
  331.           
  332.           
  333.         //初始化密钥   
  334.         byte[] key3=MACCoder.initHmacSHAKey();  
  335.         //获取摘要信息   
  336.         byte[] data3=MACCoder.encodeHmacSHA(str.getBytes(), key3);  
  337.         System.out.println("HmacSHA1的密钥:"+key3.toString());  
  338.         System.out.println("HmacSHA1算法摘要:"+data3.toString());  
  339.         System.out.println();  
  340.           
  341.           
  342.         //初始化密钥   
  343.         byte[] key4=MACCoder.initHmacSHA384Key();  
  344.         //获取摘要信息   
  345.         byte[] data4=MACCoder.encodeHmacSHA384(str.getBytes(), key4);  
  346.         System.out.println("HmacSHA384的密钥:"+key4.toString());  
  347.         System.out.println("HmacSHA384算法摘要:"+data4.toString());  
  348.         System.out.println();  
  349.           
  350.           
  351.         //初始化密钥   
  352.         byte[] key5=MACCoder.initHmacSHA512Key();  
  353.         //获取摘要信息   
  354.         byte[] data5=MACCoder.encodeHmacSHA512(str.getBytes(), key5);  
  355.         System.out.println("HmacSHA512的密钥:"+key5.toString());  
  356.         System.out.println("HmacSHA512算法摘要:"+data5.toString());  
  357.         System.out.println();  
  358.           
  359.         System.out.println("================以下的算法支持是bouncycastle支持的算法,sun java6不支持=======================");  
  360.         //初始化密钥   
  361.         byte[] key6=MACCoder.initHmacMD2Key();  
  362.         //获取摘要信息   
  363.         byte[] data6=MACCoder.encodeHmacMD2(str.getBytes(), key6);  
  364.         String datahex6=MACCoder.encodeHmacMD2Hex(str.getBytes(), key6);  
  365.         System.out.println("Bouncycastle HmacMD2的密钥:"+key6.toString());  
  366.         System.out.println("Bouncycastle HmacMD2算法摘要:"+data6.toString());  
  367.         System.out.println("Bouncycastle HmacMD2Hex算法摘要:"+datahex6.toString());  
  368.         System.out.println();  
  369.           
  370.         //初始化密钥   
  371.         byte[] key7=MACCoder.initHmacMD4Key();  
  372.         //获取摘要信息   
  373.         byte[] data7=MACCoder.encodeHmacMD4(str.getBytes(), key7);  
  374.         String datahex7=MACCoder.encodeHmacMD4Hex(str.getBytes(), key7);  
  375.         System.out.println("Bouncycastle HmacMD4的密钥:"+key7.toString());  
  376.         System.out.println("Bouncycastle HmacMD4算法摘要:"+data7.toString());  
  377.         System.out.println("Bouncycastle HmacMD4Hex算法摘要:"+datahex7.toString());  
  378.         System.out.println();  
  379.           
  380.         //初始化密钥   
  381.         byte[] key8=MACCoder.initHmacSHA224Key();  
  382.         //获取摘要信息   
  383.         byte[] data8=MACCoder.encodeHmacSHA224(str.getBytes(), key8);  
  384.         String datahex8=MACCoder.encodeHmacSHA224Hex(str.getBytes(), key8);  
  385.         System.out.println("Bouncycastle HmacSHA224的密钥:"+key8.toString());  
  386.         System.out.println("Bouncycastle HmacSHA224算法摘要:"+data8.toString());  
  387.         System.out.println("Bouncycastle HmacSHA224算法摘要:"+datahex8.toString());  
  388.         System.out.println();  
  389.     }  
  390. }  
  391. 控制台输出结果如下:  
  392. 原文:HmacMD5消息摘要  
  393. HmacMD5的密钥:[B@136228  
  394. HmacMD5算法摘要:[B@913750  
  395. HmacSHA256的密钥:[B@bfbdb0  
  396. HmacSHA256算法摘要:[B@3e86d0  
  397. HmacSHA1的密钥:[B@253498  
  398. HmacSHA1算法摘要:[B@9fef6f  
  399. HmacSHA384的密钥:[B@f38798  
  400. HmacSHA384算法摘要:[B@4b222f  
  401. HmacSHA512的密钥:[B@b0f13d  
  402. HmacSHA512算法摘要:[B@ae000d  
  403. ================以下的算法支持是bouncycastle支持的算法,sun java6不支持=======================  
  404. Bouncycastle HmacMD2的密钥:[B@4741d6  
  405. Bouncycastle HmacMD2算法摘要:[B@337d0f  
  406. Bouncycastle HmacMD2Hex算法摘要:0fbabb3bb1a2be81fbc823013f6920fe  
  407. Bouncycastle HmacMD4的密钥:[B@1e0bc08  
  408. Bouncycastle HmacMD4算法摘要:[B@158b649  
  409. Bouncycastle HmacMD4Hex算法摘要:a3fa5935ca554f83c8987efd2bcfe605  
  410. Bouncycastle HmacSHA224的密钥:[B@8a0d5d  
  411. Bouncycastle HmacSHA224算法摘要:[B@173831b  
  412. Bouncycastle HmacSHA224算法摘要:542d47250e5ff9f8bb3a7607799b1685a8accd65580410ea1d4dd578  

五、总结

 

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

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

 

0 0
原创粉丝点击