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

原文:http://blog.csdn.net/kongqz/article/details/6281710


一、简述

  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算法实现

[java]  view plain copy
  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进制转换

你可能感兴趣的:(消息摘要算法-MAC算法系列)