0%

MAC & HMAC

在前一段做安全接入的时候,结合了多种安全和密码学的算法,设计了一套敏感数据传输方案。今天主要介绍的是其中用到的消息认证码(Message authentication code,缩写为MAC)。这里的MAC并不是网卡物理地址的那个MAC,注意区分。

介绍

在密码学中,MAC是一小段字节信息,用于验证发送消息的完整性(data integrity),以及消息的身份认证(确定消息的发送者的身份 - its authenticity)。
另一方面来说,MAC可以做到识别内容篡改和内容伪造。
回忆一下,Hash算法例如SHA256、MD5等,也可以完成消息完整性的验证,数字签名算法(其实内部也结合了消息散列函数)也可以达到MAC的这两项作用。

定义

MAC(生成tag)由三个算法组成:

  • 密钥key生成算法。从密钥空间中选择出来的key是均匀和随机的。
  • 签名算法。给定Key和消息,生成唯一的tag。
  • 验证算法。给定Key,tag和消息,验证是否符合。

安全

MAC方法必须能够抵御chosen-plaintext attacks。
简单解释一下:
Alice和Bob约定一个只有他们两个知道的MAC key。Eve在监视他们的通信,并且可以获取到他们通信的信息和对应的tags。
但是Eve根据得到的这些对应信息,并不能推算出其他消息的有效tag。
即使Eve可以说服Alice和Bob发送一些指定的信息,也依旧不能推算出来。
在Eve看来,tag是完全随机的字节。

MAC与数字签名的主要不同点,在于MAC在生成和验证阶段使用的是相同的key,接收者和发送者必须实现约定相同的key,才能使用MAC方法进行通信。
数字签名则是使用的非对称的公钥和私钥机制,使用私钥进行签名,公钥验证签名。

实现

HMAC是MAC方法的一种具体实现,使用key和一些特点的Hash函数来生成MAC,常见的有Hmac_MD5,Hmac_SHA1,Hmac_SHA256,Hmac_SHA384,Hmac_SHA512.

Java代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
private static final String HMAC_ALGORITHM = "HmacSHA256";
private static final int HMAC_KEY_LENGTH_BITS = 256;

public static SecretKey getSecretKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance(HMAC_ALGORITHM);
return keyGenerator.generateKey();

}

private static byte[] randomBytes(int length) {
SecureRandom random = new SecureRandom();
byte[] b = new byte[length];
random.nextBytes(b);
return b;
}

/**
* Generate the mac based on HMAC_ALGORITHM
*
* @param integrityKey The key used for hmac
* @param byteCipherText the cipher text
*
* @return A byte array of the HMAC for the given key and ciphertext
*
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
*/
public static byte[] generateMac(byte[] byteCipherText, SecretKey integrityKey)
throws NoSuchAlgorithmException, InvalidKeyException {
// Now compute the mac for later integrity checking
Mac sha256HMAC = Mac.getInstance(HMAC_ALGORITHM);
sha256HMAC.init(integrityKey);
return sha256HMAC.doFinal(byteCipherText);
}

参考:
https://en.wikipedia.org/wiki/Message_authentication_code
https://en.wikipedia.org/wiki/Chosen-plaintext_attack