博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
第五章 消息摘要算法--MAC
阅读量:6263 次
发布时间:2019-06-22

本文共 7388 字,大约阅读时间需要 24 分钟。

注意:本节内容主要参考自《Java加密与解密的艺术(第2版)》第6章“验证数据完整性--消息摘要算法”

5.1、mac(又称为Hmac)

原理:在md与sha系列算法的基础上加入了密钥,是三大常用的消息摘要算法中最安全的一个。

常用的mac算法:

  • HmacMD5
  • HmacSHA1
  • HmacSHA256

5.2、实现方式

  • JDK(缺少二进制字节数组转十六进制的工具,可借助CC或BC的工具类完成)
  • Commons Codec(CC,在1.10版本中加入的,其中,产生相应算法密钥的API没有找到,如果有人找到了,请和我讲一下,谢谢
  • Bouncy Castle(BC,比较麻烦,具体参考“慕课网”)

5.2.1、基于JDK实现的Hmac系列算法

1 package com.util.mac; 2  3 import java.io.UnsupportedEncodingException; 4 import java.security.InvalidKeyException; 5 import java.security.NoSuchAlgorithmException; 6  7 import javax.crypto.KeyGenerator; 8 import javax.crypto.Mac; 9 import javax.crypto.SecretKey;10 import javax.crypto.spec.SecretKeySpec;11 12 import org.bouncycastle.util.encoders.Hex;13 14 /**15  * 基于JDK的HmacMD5算法16  */17 public class HmacMD5JDK {18     private static final String ENCODING = "UTF-8";19     private static final String ALGORITHM = "HmacMD5";//指定具体算法HmacMD5,HmacSHA1,HmacSHA25620     21     /**22      * 产生密钥两种方式 1)是由jdk自己来产生的,2)我们可以自己指定一个字节数组23      * 注意:密钥是以二进制字节数组存储的24      */25     public static byte[] getKey() throws NoSuchAlgorithmException{26         SecretKey key = KeyGenerator.getInstance(ALGORITHM).generateKey();27         return key.getEncoded();28     }29     30     /**31      * HmacMD5加密32      * @param data     带加密数据33      * @param keyByte  密钥34      */35     public static byte[] encode(String data, byte[] keyByte) throws NoSuchAlgorithmException, 36                                                                     InvalidKeyException, 37                                                                     IllegalStateException, 38                                                                     UnsupportedEncodingException {39         SecretKey key = new SecretKeySpec(keyByte, ALGORITHM);//还原密钥40         Mac mac = Mac.getInstance(key.getAlgorithm());41         mac.init(key);//为mac实例初始化密钥42         return mac.doFinal(data.getBytes(ENCODING));43     }44     45     /**46      * HmacMD5加密,并转为16进制47      */48     public static String encodeHmacMD5Hex(String data, byte[] keyByte) throws NoSuchAlgorithmException, 49                                                                               UnsupportedEncodingException, 50                                                                               InvalidKeyException, 51                                                                               IllegalStateException {52         byte[] encodedByte = encode(data, keyByte);53         return new String(Hex.encode(encodedByte));//借助BC54         //return new String(org.apache.commons.codec.binary.Hex.encodeHexString(encodedByte));//借助CC55     }56     57     /**58      * 测试59      * @throws IllegalStateException 60      * @throws InvalidKeyException 61      */62     public static void main(String[] args) throws UnsupportedEncodingException, 63                                                   NoSuchAlgorithmException, 64                                                   InvalidKeyException, 65                                                   IllegalStateException {66         String data = "找一个好姑娘做老婆是我的梦 想!";67         /*************测试encode()**************/68         System.out.println("原文-->"+data);69         byte[] keyByte = HmacMD5JDK.getKey(); 70         byte[] encodedByte = HmacMD5JDK.encode(data, keyByte);71         System.out.println("加密后-->"+encodedByte);72         byte[] encodedByte2 = HmacMD5JDK.encode(data, keyByte);73         System.out.println("加密后-->"+encodedByte2);74         for(int i=0;i
"+data);79 String encodedStr = HmacMD5JDK.encodeHmacMD5Hex(data, keyByte);80 System.out.println("加密后-->"+encodedStr);81 String encodedStr2 = HmacMD5JDK.encodeHmacMD5Hex(data, keyByte);82 System.out.println("加密后-->"+encodedStr2);83 System.out.println(encodedStr.equals(encodedStr2));84 }85 }

注意几点:

  • 产生密钥两种方式:1)直接使用JDK的类(如上边代码所示)2)自己指定字节数组(参考5.2.1)
  • 密钥是一个二进制数组,当然为了提高可读性,可以使用Base64加密后,在传递可对方
  • 在实际使用中,我们可以将密钥产生后,发送者通过安全途径(线下传递等)传给接收方。
  • 在上述的测试中,去测一下同一个消息在使用同一个密钥的情况下,多次mac后结果是否相同。
  • 想切换算法,只需要修改ALGORITHM常数即可,当然如果在实际项目中需要用到多种算法,并且需要实现平滑切换,可以采用策略模式,这个以后会再讲。

5.2.1、基于CC实现的Hmac系列算法

1 package com.util.mac; 2  3 import java.io.UnsupportedEncodingException; 4 import java.security.InvalidKeyException; 5 import java.security.NoSuchAlgorithmException; 6  7 import org.apache.commons.codec.DecoderException; 8 import org.apache.commons.codec.binary.Hex; 9 import org.apache.commons.codec.digest.HmacUtils;10 11 /**12  * 基于CC的HmacMD5算法13  */14 public class HmacMD5CC {15     private static final String ENCODING = "UTF-8";16     /**17      * 产生密钥18      */19     public static byte[] getKey() throws NoSuchAlgorithmException, DecoderException{20         return Hex.decodeHex(new char[]{'a','b','c','d'}); 21     }22     23     /**24      * HmacMD5加密25      * @param data     带加密数据26      * @param keyByte  密钥27      */28     public static byte[] encode(String data, byte[] keyByte) throws NoSuchAlgorithmException, 29                                                                     InvalidKeyException, 30                                                                     IllegalStateException, 31                                                                     UnsupportedEncodingException {32         return HmacUtils.hmacMd5(keyByte, data.getBytes(ENCODING));33     }34     35     /**36      * HmacMD5加密,并转为16进制37      */38     public static String encodeHmacMD5Hex(String data, byte[] keyByte) throws NoSuchAlgorithmException, 39                                                                               UnsupportedEncodingException, 40                                                                               InvalidKeyException, 41                                                                               IllegalStateException {42         return HmacUtils.hmacMd5Hex(keyByte, data.getBytes(ENCODING));43     }44     45     /**46      * 测试47      * @throws IllegalStateException 48      * @throws InvalidKeyException 49      * @throws DecoderException 50      */51     public static void main(String[] args) throws UnsupportedEncodingException, 52                                                   NoSuchAlgorithmException, 53                                                   InvalidKeyException, 54                                                   IllegalStateException, 55                                                   DecoderException {56         String data = "找一个好姑娘做老婆是我的梦 想!";57         /*************测试encode()**************/58         System.out.println("原文-->"+data);59         byte[] keyByte = HmacMD5CC.getKey(); 60         byte[] encodedByte = HmacMD5CC.encode(data, keyByte);61         System.out.println("加密后-->"+encodedByte);62         byte[] encodedByte2 = HmacMD5CC.encode(data, keyByte);63         System.out.println("加密后-->"+encodedByte2);64         for(int i=0;i
"+data);69 String encodedStr = HmacMD5CC.encodeHmacMD5Hex(data, keyByte);70 System.out.println("加密后-->"+encodedStr);71 String encodedStr2 = HmacMD5CC.encodeHmacMD5Hex(data, keyByte);72 System.out.println("加密后-->"+encodedStr2);73 System.out.println(encodedStr.equals(encodedStr2));74 }75 }

注意:

  • CC很好的封装了jdk的底层,但是CC是在1.10版本中才添加了hmac系列算法
  • 在使用中,若想切换其他算法,只需要调用不同的方法即可,具体的查看本文最下边的CC1.10的API文档链接地址
  • 其中,生成密钥在这里是自己指定了一个字节数组,具体的有CC来产生相应算法的密钥的API并没有看到,如果需要,可以自己去封装,当然,如果在CC中有相应的API,请大家和我讲一下,谢谢!

CC API文档:

 

转载地址:http://ljzpa.baihongyu.com/

你可能感兴趣的文章
用delphi实现完美屏幕截图
查看>>
matlab练习程序(差异演化DE)
查看>>
这就是搜索引擎:核心技术详解
查看>>
加解密技术处理时间对比
查看>>
g++命令行详解 (转)
查看>>
Ubuntu菜鸟入门(九)—— 支付宝支付控件安装
查看>>
什么是 SRS 呢?在我们大部分的音频播放器里都内欠有这种音效。
查看>>
对/etc/rc.d/init.d目录的一点理解(转)
查看>>
c#使用params重载方法
查看>>
浅析C# 中object sender与EventArgs e
查看>>
遇到Audio/Speech相关问题,如何抓取log
查看>>
数学之路(3)-机器学习(4)-专家系统(1)
查看>>
Android中常用单位dp,px,sp之间的相互转换
查看>>
C++线性方程求解
查看>>
nginx负载均衡的实现
查看>>
Oracle PL/SQL之LOOP循环控制语句
查看>>
Webkit内核的浏览器中用CSS3+jQuery实现iphone滑动解锁效果(译)
查看>>
Can't create handler inside thread that has not called Looper.prepare()
查看>>
MDaemon运行六年方法
查看>>
SQL SERVER 存储过程应用
查看>>