注意:本节内容主要参考自《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系列算法

package com.util.mac;

import java.io.UnsupportedEncodingException;
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;

import org.bouncycastle.util.encoders.Hex;

/**
 * 基于JDK的HmacMD5算法
 */
public class HmacMD5JDK {
    private static final String ENCODING = "UTF-8";
    private static final String ALGORITHM = "HmacMD5";//指定具体算法HmacMD5,HmacSHA1,HmacSHA256

    /**
     * 产生密钥两种方式 1)是由jdk自己来产生的,2)我们可以自己指定一个字节数组
     * 注意:密钥是以二进制字节数组存储的
     */
    public static byte[] getKey() throws NoSuchAlgorithmException{
        SecretKey key = KeyGenerator.getInstance(ALGORITHM).generateKey();
        return key.getEncoded();
    }

    /**
     * HmacMD5加密
     * @param data     带加密数据
     * @param keyByte  密钥
     */
    public static byte[] encode(String data, byte[] keyByte) throws NoSuchAlgorithmException,
                                                                    InvalidKeyException,
                                                                    IllegalStateException,
                                                                    UnsupportedEncodingException {
        SecretKey key = new SecretKeySpec(keyByte, ALGORITHM);//还原密钥
        Mac mac = Mac.getInstance(key.getAlgorithm());
        mac.init(key);//为mac实例初始化密钥
        return mac.doFinal(data.getBytes(ENCODING));
    }

    /**
     * HmacMD5加密,并转为16进制
     */
    public static String encodeHmacMD5Hex(String data, byte[] keyByte) throws NoSuchAlgorithmException,
                                                                              UnsupportedEncodingException,
                                                                              InvalidKeyException,
                                                                              IllegalStateException {
        byte[] encodedByte = encode(data, keyByte);
        return new String(Hex.encode(encodedByte));//借助BC
        //return new String(org.apache.commons.codec.binary.Hex.encodeHexString(encodedByte));//借助CC
    }

    /**
     * 测试
     * @throws IllegalStateException
     * @throws InvalidKeyException
     */
    public static void main(String[] args) throws UnsupportedEncodingException,
                                                  NoSuchAlgorithmException,
                                                  InvalidKeyException,
                                                  IllegalStateException {
        String data = "找一个好姑娘做老婆是我的梦 想!";
        /*************测试encode()**************/
        System.out.println("原文-->"+data);
        byte[] keyByte = HmacMD5JDK.getKey();
        byte[] encodedByte = HmacMD5JDK.encode(data, keyByte);
        System.out.println("加密后-->"+encodedByte);
        byte[] encodedByte2 = HmacMD5JDK.encode(data, keyByte);
        System.out.println("加密后-->"+encodedByte2);
        for(int i=0;i<encodedByte.length;i++){
            System.out.println(encodedByte[i]==encodedByte2[i]);
        }
        /*************测试encodeHmacMD5Hex()**************/
        System.out.println("原文-->"+data);
        String encodedStr = HmacMD5JDK.encodeHmacMD5Hex(data, keyByte);
        System.out.println("加密后-->"+encodedStr);
        String encodedStr2 = HmacMD5JDK.encodeHmacMD5Hex(data, keyByte);
        System.out.println("加密后-->"+encodedStr2);
        System.out.println(encodedStr.equals(encodedStr2));
    }
}

注意几点:

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

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

package com.util.mac;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.HmacUtils;

/**
 * 基于CC的HmacMD5算法
 */
public class HmacMD5CC {
    private static final String ENCODING = "UTF-8";
    /**
     * 产生密钥
     */
    public static byte[] getKey() throws NoSuchAlgorithmException, DecoderException{
        return Hex.decodeHex(new char[]{'a','b','c','d'});
    }

    /**
     * HmacMD5加密
     * @param data     带加密数据
     * @param keyByte  密钥
     */
    public static byte[] encode(String data, byte[] keyByte) throws NoSuchAlgorithmException,
                                                                    InvalidKeyException,
                                                                    IllegalStateException,
                                                                    UnsupportedEncodingException {
        return HmacUtils.hmacMd5(keyByte, data.getBytes(ENCODING));
    }

    /**
     * HmacMD5加密,并转为16进制
     */
    public static String encodeHmacMD5Hex(String data, byte[] keyByte) throws NoSuchAlgorithmException,
                                                                              UnsupportedEncodingException,
                                                                              InvalidKeyException,
                                                                              IllegalStateException {
        return HmacUtils.hmacMd5Hex(keyByte, data.getBytes(ENCODING));
    }

    /**
     * 测试
     * @throws IllegalStateException
     * @throws InvalidKeyException
     * @throws DecoderException
     */
    public static void main(String[] args) throws UnsupportedEncodingException,
                                                  NoSuchAlgorithmException,
                                                  InvalidKeyException,
                                                  IllegalStateException,
                                                  DecoderException {
        String data = "找一个好姑娘做老婆是我的梦 想!";
        /*************测试encode()**************/
        System.out.println("原文-->"+data);
        byte[] keyByte = HmacMD5CC.getKey();
        byte[] encodedByte = HmacMD5CC.encode(data, keyByte);
        System.out.println("加密后-->"+encodedByte);
        byte[] encodedByte2 = HmacMD5CC.encode(data, keyByte);
        System.out.println("加密后-->"+encodedByte2);
        for(int i=0;i<encodedByte.length;i++){
            System.out.println(encodedByte[i]==encodedByte2[i]);
        }
        /*************测试encodeHmacMD5Hex()**************/
        System.out.println("原文-->"+data);
        String encodedStr = HmacMD5CC.encodeHmacMD5Hex(data, keyByte);
        System.out.println("加密后-->"+encodedStr);
        String encodedStr2 = HmacMD5CC.encodeHmacMD5Hex(data, keyByte);
        System.out.println("加密后-->"+encodedStr2);
        System.out.println(encodedStr.equals(encodedStr2));
    }
}

注意:

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

CC API文档:

http://commons.apache.org/proper/commons-codec/apidocs/org/apache/commons/codec/digest/HmacUtils.html

第五章 消息摘要算法--MAC的更多相关文章

  1. 第四章 消息摘要算法--SHA

    注意:本节内容主要参考自<Java加密与解密的艺术(第2版)>第6章“验证数据完整性--消息摘要算法” 4.1.SHA 原理:消息摘要长度(可以定量为加密后的字符串的长度)越长,安全性越高 ...

  2. 第三章 消息摘要算法--MD5

    注意:本节内容主要参考自<Java加密与解密的艺术(第2版)>第6章“验证数据完整性--消息摘要算法” 3.1.消息摘要算法:防止消息在传递过程中被篡改. 原理:任何消息经过消息摘要算法后 ...

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

    一.简述 mac(Message Authentication Code,消息认证码算法)是含有密钥散列函数算法,兼容了MD和SHA算法的特性,并在此基础上加上了密钥.因此MAC算法也经常被称作HMA ...

  4. MD、SHA、MAC消息摘要算法实现与应用

    1.消息摘要概述 消息摘要(Message Digest)又称为数字摘要(Digital Digest).它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生 ...

  5. 信息加密之消息摘要算法的MAC

    MAC是消息摘要算法的第三种实现方式,另外两种方式分别为:MD2\4\5.SHA. MAC的jdk实现:1.默认密钥方式 private static void MAC_JDK(){ try { Ke ...

  6. MD5 Message Digest Algorithm MD5(中文名为消息摘要算法第五版)

    MD5 编辑 Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护.该算法的文件号为RFC 1321( ...

  7. password学4——Java 加密解密之消息摘要算法(MD5 SHA MAC)

    Java 加密解密之消息摘要算法(MD5 SHA MAC) 消息摘要 消息摘要(Message Digest)又称为数字摘要(Digital Digest). 它是一个唯一相应一个消息或文本的固定长度 ...

  8. 一步一步来做WebQQ机器人-(五)(发送消息||完结)

    × 本篇主要是: 发送QQ消息(to:好友,群),以及对小黄鸡抓包利用它的语言库 本文是WebQQ流程的最后一章 最后一章内容不多但我还是啰嗦,可能对大部分人都已知晓的流程方法我也会介绍一下 前面几个 ...

  9. 《Introduction to Tornado》中文翻译计划——第五章:异步Web服务

    http://www.pythoner.com/294.html 本文为<Introduction to Tornado>中文翻译,将在https://github.com/alioth3 ...

随机推荐

  1. webstorm添加调试nodejs

    打开run菜单选择Edit Configurations 展开defaults菜单,选择nodejs 点击+按钮,选择Node.js,出现下面弹出框. 点击ok保存

  2. npm的用户名添加不上的原因

    npm添加不上的错误e401 1.用cnpm提交,会提交的tao.org这个域名了,用npm提交试试 2.如果npm提交不上,那就查看配置文件配置中 registry=http://registry. ...

  3. SQL Server中灾难时备份结尾日志(Tail of log)的两种方法

    转自:http://www.cnblogs.com/CareySon/archive/2012/02/23/2365006.html SQL Server中灾难时备份结尾日志(Tail of log) ...

  4. 修改lastpass主密码后需重启firefox才能加载已保存的站点密码或用导入工具

    最近索尼事件闹得沸沸扬扬,预防黑客先从升级密码开始.由于开发的需要一般是用firefox作为默认的浏览器,很早以前就装了lastpass密码管理器作为必备附加组件,在注册时按一下Alt+G就会帮你生成 ...

  5. 换个字体解决Dreamweaver文字选不中的问题

    在使用Dreamweaver时,有时我们要选中一些字符进行编辑或删除,光标在英文字上面可以选中,在中文字上面就选不中,郁闷吧.比如在编辑下面这段文字的时候,如图所示, 想选中“你难得已经忘了吗?”,当 ...

  6. Intel 设计缺陷背后的原因是什么? | Linux 中国

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/F8qG7f9YD02Pe/article/details/79386769 wx_fmt=jpeg& ...

  7. (转)mysql数据文件解析

    一 数据文件 在 MySQL中每一个数据库都会在定义好(或者默认)的数据目录下存在一个以数据库名字命名的文件夹,用来存放该数据库中各种表数据文件.不同的 MySQL存储引擎有各自不同的数据文件,存放位 ...

  8. Qt界面控件值获取异常处理

    情景简述: 正常情况,我们从控件获取的值是OK的,但有时候就是奇怪的不对头,那么我们可以给获取后的值加上一个不痛不痒的函数,再返回,结果就OK了.至于原因嘛,[呲牙][呲牙] 比如: //正常情况 d ...

  9. rabbitmq_坑

      一.None of the specified endpoints were reachable 这个异常在创建连接时抛出(CreateConnection()),原因一般是ConnectionF ...

  10. JsonPath的使用

    语法: JsonPath 描述 $ 根节点 @ 当前节点 .or[] 子节点 .. 选择所有符合条件的节点 * 所有节点 [] 迭代器标示,如数组下标 [,] 支持迭代器中做多选 [start:end ...