乐趣区

关于算法:奇妙的安全旅行之HMAC算法

hi,大家好,明天咱们开始介绍音讯摘要算法中的 HMAC(Keyed-Hashing for Message Authentication)音讯认证码算法,MAC(Message Authentication Code,音讯认证码算法)是含有密钥散列函数算法,兼容了 MD 和 SHA 算法的个性,并在此基础上加上了密钥,因而 MAC 算法也常常被称作 HMAC 算法。

MAC

在开始之前,咱们先说下 MAC 算法。在古代的网络中,身份认证是一个常常会用到的性能,在身份认证过程中,有很多种形式能够保障用户信息的平安,而 MAC(message authentication code) 就是一种罕用的办法。

音讯认证码是对音讯进行认证并确认其完整性的技术。通过应用发送者和接收者之间共享的密钥,就能够辨认出是否存在假装和篡改行为。

MAC 是通过【MAC 算法 + 密钥 + 要加密的信息】三个因素一起计算得出的。

同 hash 算法(音讯摘要)相比,音讯摘要只能保障音讯的完整性,即该音讯摘要 B 是这个音讯 A 生成的。而 MAC 算法可能保障音讯的正确性,即判断的确发的是音讯 A 而不是音讯 C。

同公私钥体系相比,因为 MAC 的密钥在发送方和接管方是一样的,所以发送方和接管方都能够来生成 MAC,而公私钥体系因为将公钥和私钥离开,所以减少了不可抵赖性。

MAC 有很多实现形式,比拟通用的是基于 hash 算法的 MAC,比方明天咱们要讲的 HMAC 算法。还有一种是基于分组明码的实现,比方 OMAC, CBC-MAC and PMAC 等。

HMAC

HMAC 算法首先它是基于信息摘要算法的。目前次要汇合了 MD 和 SHA 两大系列音讯摘要算法。其中 MD 系列的算法有 HmacMD2、HmacMD4、HmacMD5 三种算法;SHA 系列的算法有 HmacSHA1、HmacSHA224、HmacSHA256、HmacSHA384、HmacSHA512 五种算法。

HMAC 算法除了须要信息摘要算法外,还须要一个密钥。HMAC 的密钥能够是任何长度,如果密钥的长度超过了摘要算法信息分组的长度,则首先应用摘要算法计算密钥的摘要作为新的密钥。个别不倡议应用太短的密钥,因为密钥的长度与平安强度是相干的。通常选取密钥长度不小于所选用摘要算法输入的信息摘要的长度。

MD 算法的比照

算法 摘要长度(bit) 实现方
HmacMD5 128 JDK、Bouncy Castle、Commons Codec
HmacSHA1 160 JDK、Bouncy Castle、Commons Codec
HmacSHA224 224 JDK、Bouncy Castle、Commons Codec
HmacSHA256 256 JDK、Bouncy Castle、Commons Codec
HmacSHA384 384 JDK、Bouncy Castle、Commons Codec
HmacSHA512 512 JDK、Bouncy Castle、Commons Codec

HMAC 算法实现

JDK 的 HMAC 算法实现

JDK 对于 HMAC 算法的实现:

// 获取 HMAC Key
public static byte[] getHmacKey(String algorithm) {
    try {
        // 1、创立密钥生成器
        KeyGenerator keyGenerator = KeyGenerator.getInstance(algorithm);
        // 2、产生密钥
        SecretKey secretKey = keyGenerator.generateKey();
        // 3、获取密钥
        byte[] key = secretKey.getEncoded();
        // 4、返回密钥
        return key;
    } catch (Exception e) {throw new RuntimeException(e);
    }
}

// HMAC 加密
public static String encryptHmac(byte[] data, byte[] key, String algorithm) {
    try {
        // 1、还原密钥
        SecretKey secretKey = new SecretKeySpec(key, algorithm);
        // 2、创立 MAC 对象
        Mac mac = Mac.getInstance(algorithm);
        // 3、设置密钥
        mac.init(secretKey);
        // 4、数据加密
        byte[] bytes = mac.doFinal(data);
        // 5、生成数据
        String rs = encodeHex(bytes);
        // 6、返回十六进制加密数据
        return rs;
    } catch (Exception e) {throw new RuntimeException(e);
    }
}
Bouncy Castle 的 HMAC 算法实现

Bouncy Castle 对于 HMAC 算法的实现:

// 获取 HMAC Key
public static byte[] getHmacKey(String algorithm) {
    try {
        // 1、创立密钥生成器
        KeyGenerator keyGenerator = KeyGenerator.getInstance(algorithm);
        // 2、产生密钥
        SecretKey secretKey = keyGenerator.generateKey();
        // 3、获取密钥
        byte[] key = secretKey.getEncoded();
        // 4、返回密钥
        return key;
    } catch (Exception e) {throw new RuntimeException(e);
    }
}

// HMAC 加密
public static String encryptHmac(byte[] data, byte[] key, String algorithm) {HMac hmac = generateHmacByAlgorithm(algorithm);
    KeyParameter keyParameter = new KeyParameter(key);
    hmac.init(keyParameter);
    hmac.update(data, 0, data.length);
    byte[] rsData = new byte[hmac.getMacSize()];
    hmac.doFinal(rsData, 0);

    return Hex.toHexString(rsData);
}
Commons Codec 的 HMAC 算法实现

Commons Codec 提供的 HMAC 算法实现:

// 获取 HMAC Key
public static byte[] getHmacKey(String algorithm) {
    try {
        // 1、创立密钥生成器
        KeyGenerator keyGenerator = KeyGenerator.getInstance(algorithm);
        // 2、产生密钥
        SecretKey secretKey = keyGenerator.generateKey();
        // 3、获取密钥
        byte[] key = secretKey.getEncoded();
        // 4、返回密钥
        return key;
    } catch (Exception e) {throw new RuntimeException(e);
    }
}

// HMAC 加密
public static String encryptHmac(byte[] data, byte[] key, String algorithm) {Mac mac = HmacUtils.getInitializedMac(HmacAlgorithms.HMAC_MD5, key);
    return Hex.encodeHexString(mac.doFinal(data));
}

获取残缺代码请拜访:
https://github.com/ForTheDevelopers/JavaSecurity

HMAC 算法的利用

1、能够验证对端用户的合法性

HMAC 算法的一个典型利用是用在“挑战 / 响应”(Challenge/Response)身份认证中,认证流程如下:

(1) 先由客户端向服务器收回一个验证申请,(假如是浏览器的 GET 申请)。

(2) 服务器接到此申请后生成一个随机数并通过网络传输给客户端(此为挑战)。

(3) 客户端将收到的随机数与本人的密钥进行 HMAC 运算并失去一个后果作为认证证据返回给服务器(此为响应)。

(4) 与此同时,服务器也应用该随机数与存储在服务器数据库中的该客户密钥进行 HMAC 运算,如果服务器的运算后果与客户端传回的响应后果雷同,则认为客户端是一个非法用户。

在这个过程中,可能受到平安攻打的是服务器发送的随机数和客户端返回的 HMAC 后果,而对于截获了这两个值的黑客而言这两个值是没有意义的,随机值的引入使 HMAC 只在以后会话中无效,大大加强了安全性和实用性。

2、发消息给对方(或从对方接管音讯)

比方你和对方共享了一个密钥 K,当初你要发消息给对方,既要保障音讯没有被篡改(完整性),又要能证实信息的确是你自己发的(源认证),那么就把原信息和密钥 K 经 HMAC 计算的值一起发过来。对方接到之后,应用本人手中的密钥 K 和原音讯计算一下 HMAC 的值,如果和你发送的 HMAC 统一,那么能够认为这个音讯既没有被篡改也没有假冒。

一般散列算法和 HMAC 算法的区别

一般散列算法就是通过 hash 对要输入的数据进行摘要,接管到数据时,再同样对源数据进行散列,与给定的散列值比拟,看收到的数据与计算的 hash 值是否统一就能够了。

通常来说,传输的数据和散列值是不同的渠道给出的,比方网页上显示 MD5 或 SHA 的散列值,然而下载链接是某个镜像网站的,这并不影响你下载到的文件的正确性。

如果要通过同一个渠道发送数据和散列值的话(比方音讯认证码),就要思考数据和散列值是否会同时被篡改的问题,如果第三方批改了数据,而后进行 MD5 散列,并一块发给接管方,接管方并不能察觉到数据被篡改。

而 HMAC 算法就能够用一把发送方和接管方都有的密钥 key 进行计算,而没有这个密钥 key 的第三方是无奈计算出正确的散列值的,这样就能够避免数据的起源方被篡改。

总结

HMAC 算法目前的利用场景绝对还比拟少,通常会间接应用加密算法来保障起源方的正确性,不过 HMAC 在特定场景下还是有肯定用处的,大家能够依据本人的业务特点来抉择应用哪种加密算法。另外也欢送大家关注咱们的公众号,回复【加解密】获取本系列的全副源码。

创作不易,如果大家喜爱本文,欢送点赞,转发,你的关注是咱们继续前进的能源 ^_^

退出移动版