注意:本节内容主要参考自《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. Ajax返回乱码

    1.关于JSP页面中的pageEncoding和contentType两种属性的区别: pageEncoding是jsp文件本身的编码,contentType的charset是指服务器发送给客户端时的 ...

  2. 006-Redis 发布订阅

    Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息. Redis 客户端可以订阅任意数量的频道. 下图展示了频道 channel1 , 以及订 ...

  3. [LeetCode] 711. Number of Distinct Islands II_hard tag: DFS

    Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) conn ...

  4. Fuzzy and fun on Air Jordan 12 Doernbecher design

    Carissa Navarro keeps it warm, fuzzy and fun on her 2017 Air Jordan 12 Doernbecher design. Nike's 20 ...

  5. ubuntu shell脚本出错 dash

    今天在Ubuntu下调试代码,明明是正确的,却仍然报错,查了错误信息才知道:Ubuntu中默认不是bash,而是为了加快开机速度,使用了dash. dash中需要严格的语法,而且与bash语法不同.例 ...

  6. excel输入数字变成特殊符号问题

    问题,在单元格里输入数字,结果变成文件夹类型的小图片或特殊符号了,原因是字体为Wingdings,将其设为Times New Roman即可

  7. STA分析(二) multi_cycle and false

    multicycle path:当FF之间的组合逻辑path propagate delay大于一个时钟cycle时,这条combinational path能被称为multicycle path. ...

  8. RVDS编译器

    不同ARM的体系结构,使用的ARM RealView编译工具时的异同点. 1)ARM体系结构v6K首次引入对4个CPU的MPCore处理器支持,高效的多重处理系统与单CPU系统相比,功耗更低,散热量更 ...

  9. 利用javascript实现css操作

    在很多情况下,都需要对网页上元素的样式进行动态的修改.在JavaScript中提供几种方式动态的修改样式,下面将介绍方法的使用.效果.以及缺陷. 1.使用obj.className来修改样式表的类名. ...

  10. CE寻找游戏基址

    什么是游戏基址? 游戏基址是保持恒定的两部分内存地址的一部分并提供一个基准点,从这里可以计算一个字节数据的位置.基址伴随着一个加到基上的偏移值来确定信息准确的位置(绝对地址). 全局基址 一级基址 二 ...