HMAC简介及HMAC-SHA256实现Demo

一、什么是HMAC

HMAC是一种使用单向散列函数来构造消息认证码的方法,其中HMAC中的H就是Hash的意思。

HMAC中所使用的单向散列函数并不仅限于一种,任何高强度的单向散列函数都可以被用于HMAC,如果将来设计出的新的单向散列函数,也同样可以使用。

使用SHA-1、SHA-224、SHA-256、SHA-384、SHA-512所构造的HMAC,分别称为HMAC-SHA1、HMAC-SHA-224、HMAC-SHA-384、HMAC-SHA-512。

二、HMAC的计算步骤

 

 

 1、密钥填充

如果密钥比单向散列函数分组长度要短,就需要在末尾填充0,直到其长度达到单向散列函数的分组长度为止。

如果密钥比分组长度要长,则要用单向散列函数求出密钥的散列值,然后将这个散列值用作HMAC的密钥。

2、填充后的密钥与ipad的XOR

将填充后的密钥与被称为ipad的比特序列进行XOR运算。ipad是将00110110这一比特序列不断循环反复直到达到分组长度所形成的比特序列,其中ipad的i是inner的意思。

XOR运算所得到的值,就是一个和单向散列函数的分组长度相同,且和密钥相关的比特序列。这里将这个比特序列称为ipadkey。

ipad为常量0x36...36,长度为Hash Block Size。

3、与消息组合

随后,将ipadkey与消息组合,也就是将和密钥相关的比特序列(ipadkey)附加在消息的开头。

4、计算散列值

将3的结果输入单向散列函数,并计算出散列值。

5、填充后的密钥与opad的XOR

将填充后的密钥与被称为opad的比特序列进行XOR运算,opad是将01011100这一比特序列不断循环反复直到达到分组长度所形成的比特序列,其中opad的o是outer的意思。

XOR运算所得到的结果也是一个和单向散列函数的分组长度相同,且和密钥相关的比特序列。这里将这个比特序列称为opadkey。

opad为常量0x5c...5c,长度为Hash Block Size。

6、与散列值组合

将4的散列值拼在opadkey后面。

7、计算散列值

将6的结果输入单向散列函数,并计算出散列值,这个散列值就是最终的MAC值。

通过上述流程可以看出,最后得到的MAC值,一定是一个和输入的消息以及密钥都相关的长度固定的比特序列。

 三、HMAC应用

HAMC主要应用在身份验证,服务器对访问者进行鉴权,流程如下图所示:

 

 

 四、HMAC-SHA256实现Demo

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class Sha256_mac {
    public static String sha256_mac(String message,String key){
        String outPut= null;
        try{
            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(),"HmacSHA256");
            sha256_HMAC.init(secret_key);
            byte[] bytes = sha256_HMAC.doFinal(message.getBytes());
            outPut = byteArrayToHexString(bytes);
        }catch (Exception e){
            System.out.println("Error HmacSHA256========"+e.getMessage());
        }
        return outPut;
    }
    public static String byteArrayToHexString(byte[] b) {
        StringBuilder sb = new StringBuilder();
        String stmp;
        for (int n = 0; b != null && n < b.length; n++) {
            stmp = Integer.toHexString(b[n] & 0XFF);
            if (stmp.length() == 1)
                sb.append('0');
            sb.append(stmp);
        }
        return sb.toString().toLowerCase();
    }

}

 

posted @ 2020-03-05 19:24  Eleven_Liu  阅读(32246)  评论(0编辑  收藏  举报