信息认证码

信息认证码(message authentication code,MAC),是一段比较短的比特数据,用来检查一段信息、消息的可靠性和完整性,也被称为 tag。一个 MAC 算法接收一段任意长度的消息和一个固定长度的密钥 key,产生 tag 标记。一个 MAC 算法也有一个对应的校验算法,通过接收消息、key 和 tag,告诉是否合法。

如果只是需要确定一段特定消息的可靠性和完整性,可以使用签名算法,这个在后面会介绍。目前可以简单的认为签名算法通常用在非对称加密中,这里的 MAC 通常用于对称加密。

如果只需要检验一段消息的完整性,那么使用 CRC 之类的校验码或者 SHA 之类的哈希函数,都可以做到。但是为了保证可靠性,当有人攻击的时候,如果消息被篡改,那么攻击这可以重新计算校验码或者哈希。所以 MAC 类方法都需要有一个别人都不知道的 key。

MAC Encrypt

MAC 和 Encrypt 有三种结合使用的方式。

  1. Encrypt-then-MAC:$ C = E(K_C, P), t = MAC(K_M, C)$。先将原文加密,然后计算密文的 MAC。然后把 C 和 t 一块发送出去。
  2. MAC-then-Encrypt:$ t = MAC(K_M, P), C = E(K_C, P || t)$。先计算原文的 MAC,然后把原文和计算出来的 tag 和在一块,进行加密。最后只需要发送加密后的密文即可。
  3. Encrypt-and-MAC:$ C = E(K_C, P), t = MAC(K_M, P) $ 分别计算密文和 tag,分别把密文和 tag 发送出去。

总得说来,更推荐使用 Encrypt-then-MAC,优点在于收到 C 和 t 之后,可以先检验 t,如果不正确,就不用对 C 进行解密了。IPSec 就使用这个方式。MAC-then-Encrypt 也可以使用,但是收到密文之后,必须先全部解密出来之后,才能校验消息是否完整。TLS 早期使用这种方式。Encrypt-and-MAC 最差,通过 t 就可以暴露出原文的一些特征。同样的原文会得到同样的 t。SSH 使用这种方式。

HMAC

HMAC 是目前最常用,也是目前比较安全的一种 MAC 算法。他底层的哈希函数要求很低,哪怕是目前不是特别安全的 MD5 或者 SHA-0 都可以。HMAC 的工作示意如下图:

hmac-sha1

其中 i_pad 是 0x363636…3636,一个常量,o_pad 是 0x5c5c5c…5c5c,另一个常量。

Authenticated encrption modes

在通常的密码学应用中,保密性用加密实现,消息认证用 MAC 实现。这两种算法的配合方式,引发了很多安全漏洞,上述的 3 种方法 Encrypt-then-MAC、MAC-then-Encrypt 和 Encrypt-and-MAC ,后来发现,后两者都是有安全问题的,所以,2008年起,逐渐提出了用一个算法在内部同时实现 cipher+ MAC 的想法,称为 AEAD(Authenticated encryption with additional data)。 在AEAD这种概念里,cipher + MAC 被一个 AEAD 算法替换。

AES-GCM

目前网络上最常用的 AEAD 类算法就是 AES-GCM。互联网上大部分的 HTTPS 流量都依赖于这个算法。

与 AES-GCM 相似的还有个 Chacha20-Poly1305 算法。但是目前最常用的还是 AES-GCM,因为在 Intel 的 CPU 中有专门优化的硬件指令,所以 AES-GCM 依然比 Chacha20-Poly1305 快很多。但是在移动端,ARM 处理器上,Chacha20-Poly1305 就比 AES-GCM 快了。