看本文前,最好先看看之前的对于MD5算法和SHA算法的介绍。


本文目录

  • 定义
  • 常见应用场景
  • 1、linux客户端:SecureCRT
  • 2、Google身份验证器
  • 3、银联pos机终端
  • 原理
  • java实现和使用


定义

MAC(Message Authentication Codes),是一种消息摘要算法,也叫消息认证码算法。
这种算法的核心是基于秘钥的散列函数。
可以理解为,MAC算法,是MD5算法和SHA算法的升级版,是在这两种算法的基础上,又加入了秘钥的概念,更加安全。
所以,有时候又叫MAC算法为HMAC算法(keyed-Hash Message Authentication Codes),即含有秘钥的散列算法。

常见的MAC算法有以下两大类:
MD系列:HmacMD2、HmacMD4、HmacMD5
SHA系列:HmacSHA1、HmacSHA224、HmacSHA256、HmacSHA384、HmacSHA512

大致用法:

如下图,发送端根据message和一个mac算法,生成mac秘钥

将mac秘钥和message同时发送

接收端收到message,用同样的mac算法,得到mac秘钥,

判断自己生成mac秘钥和接收到的mac秘钥是否一致,从而判断message是否一致

mac算法的Python实现 mac算法有哪些_散列

常见应用场景

mac算法的应用场景,相比MD和SHA系列,要更为复杂,高级一点。

1、linux客户端:SecureCRT

SecureCRT就用到了MAC算法

2、Google身份验证器

服务提供商为每个用户生成80位的密钥(然而RFC 4226 §4要求使用128位并建议使用160位密钥)。它以16位、26位或者32位base32的字符串亦或是二维码的方式提供出来。客户端使用此密钥生成HMAC-SHA1。
具体可看维基百科的介绍

3、银联pos机终端

中国银联直联POS终端规范下载链接 主要截图如下:

mac算法的Python实现 mac算法有哪些_mac算法的Python实现_02


mac算法的Python实现 mac算法有哪些_散列_03


mac算法的Python实现 mac算法有哪些_hmac_04

原理

mac算法的Python实现 mac算法有哪些_算法_05


根据RFC 2104,HMAC的数学公式为:

mac算法的Python实现 mac算法有哪些_散列_06

其中:

H为密码散列函数(如MD5或SHA-1)
K为密钥(secret key)
m是要认证的消息
K’是从原始密钥K导出的另一个秘密密钥(如果K短于散列函数的输入块大小,则向右填充(Padding)零;如果比该块大小更长,则对K进行散列)
|| 代表串接
⊕ 代表异或(XOR)
opad 是外部填充(0x5c5c5c…5c5c,一段十六进制常量)
ipad 是内部填充(0x363636…3636,一段十六进制常量)

java实现和使用

import org.apache.commons.codec.binary.Hex;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;

public class HmacMD5Util {
    public static void main(String[] args) throws IOException, NoSuchAlgorithmException {
        System.out.println(encodeString("123"));
    }

    public static String encodeString(String plainText) throws UnsupportedEncodingException {
        return encodeBytes(plainText.getBytes("utf-8"));
    }

    public static String encodeBytes(byte[] bytes) {
        try {
//            // JDK的获取秘钥
//            byte[] key = getKey();
            // 指定秘钥
            byte[] key = Hex.decodeHex(new char[]{'a', 'b', 'c', 'd'});
            SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacMD5");
            Mac mac = Mac.getInstance("HmacMD5");
            mac.init(secretKeySpec);

            byte[] b = mac.doFinal(bytes);
//            return Hex.encodeHexString(b);
            int i;

            StringBuffer buf = new StringBuffer("");
            for (int offset = 0; offset < b.length; offset++) {
                i = b[offset];
                if (i < 0) {
                    i += 256;
                }
                if (i < 16) {
                    buf.append("0");
                }
                buf.append(Integer.toHexString(i));
            }
            return buf.toString();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }


    public static byte[] getKey() throws NoSuchAlgorithmException {
        KeyGenerator hmacMD5 = KeyGenerator.getInstance("HmacMD5");
        SecretKey secretKey = hmacMD5.generateKey();
        String algorithm = secretKey.getAlgorithm();// algorithm=HmacMD5

        byte[] encoded = secretKey.getEncoded();
        return encoded;
    }

}

结果:

4b1dd5bb09ae59a17a65168da372c90e