消息认证码(Message Authentication Code,MAC)是一种用于验证数据完整性和来源可信性(对消息进行认证)的技术。它通常由一个密钥和被保护的消息通过特定算法计算得出,接收方可以使用相同的密钥(共享密钥)来验证发送者是否真的发送了这条消息,防止被篡改和伪造。常用的SSL/TLS、IPsec协议均使用了MAC技术。
1. 产生背景
随着网络通信的发展,安全需求日益增强,传统的加密技术无法仅凭密码就保证信息的完整性和真实性。因此,MAC应运而生,作为数据完整性的一种轻量级解决方案,适用于对实时性和计算资源有限的系统。
当然,如果不考虑实时性和资源限制,我们完全有更好的解决方案,即采用数字签名技术进行通信,数字签名不仅能保障完整性、支持任何第三方证明,还能防止对方否认(抵赖)。
2. MAC工作原理
为了容易理解消息认证码的工作原理,我们再次请出密码学的老朋友Alice和Bob,在本文中Alice要向Bob发送一个转账请求。
具体工作流程:
- Alice与Bob事先共享密钥。(PS:关于如何事先共享密钥请参阅《对称密码中的密钥是如何实现安全配送的?》)
- Alice根据转账请求消息计算MAC值,MAC值的计算方法详见第3章节(HMAC)。
- Alice将转账请求消息和MAC值发送给Bob。
- Bob使用共享密钥结合收到的转账请求消息计算得出MAC值。
- Bob将自己计算的MAC值与接收到的MAC值进行比较,如果值一致则可以确认转账请求来自Allice(即认证成功),否则消息不是来自Alice(即认证失败)。
3. MAC值的经典实现方法(HMAC)
HMAC(Hash-based Message Authentication Code)是一种基于哈希函数的消息认证码机制。它结合了密钥和哈希函数,用于保护信息安全。HMAC工作的核心思想是先使用一个预共享的密钥对原始数据进行加密,然后通过哈希函数处理加密后的结果,得到一个固定长度的摘要,即HMAC值。
从上述流程中可以看出MAC值一定是和消息、密钥相关的且固定长度的比特序列。
上图中的 7 个步骤可以简化为以下 4 步(方便记忆):
-
密钥预处理:将密钥与一个固定的填充字符串(如0x36或0x5C)进行XOR运算,确保密钥长度与哈希函数的块大小一致。
-
消息预处理:将预处理后的密钥与消息进行拼接。
-
一次哈希:对拼接后的结果进行哈希运算,得到一个哈希值。
HMAC中用到的单向散列函数有多种,只要满足高强度的单向散列函数就可用于HMAC。比如使用
SHA-256
构造的HMAC称为HMAC-SHA-256
,使用MD5构造的HMAC称为HMAC-MD5
。 -
二次哈希:将预处理后的密钥与上一步得到的哈希值再次进行哈希运算,得到最终的HMAC值。
或者可以用以下公式记忆:
H M A C ( K , M ) = H ( H ( i p a d k e y ∣ ∣ M ) ∣ ∣ o p a d k e y ) HMAC(K,M) = H(H(ipadkey || M) || opadkey ) HMAC(K,M)=H(H(ipadkey∣∣M)∣∣opadkey)
其中:
- H 为共享密钥(Key),
- H 为密码散列函数(如SHA256),
- M 是要认证的消息,
- || 表示组合的意思,
- ipadkey 是内部填充(0x36…36,十六进制循环序列)与密钥XOR得到的内部序列,其中
ipadkey = inner + pad +key
, - opadkey 是外部填充(0x5c…5c,十六进制循环序列)与密钥XOR得到的外部序列,其中
opadkey = outer + pad +key
。
此外,还可以通过分组密码(如AES)、公钥密码、流密码等来实现MAC。
疑问1:大家猜猜看,为何HMAC的计算过程中一定要涉及到两次哈希运算,改成一次可行么?可以评论区留下你的答案。
4. 消息认证码无法解决的问题
4.1. 无法对第三方证明
假设Bob在接收了来自Alice的消息之后,想要向第三方验证者证明这条消息的确是Alice发送的,但是用消息认证码无法进行这样的证明,这是为什么呢?
- 首先,第三方验证者要校验MAC值,就需要知道Alice和Bob之间共享的密钥;
- 其次,即便Bob相信第三方验证者并将密钥告诉了第三方验证者,但此时第三方验证者仍无法断定这条消息是由Alice发送的,因为第三方验证者可能认为:“即使MAC值是正确的,发送这条消息的人也不一定是Alice,还有可能是Bob自己发给自己的”。
4.2. 无法防止否认
假设Bob收到了包含MAC值的消息,这个MAC值是用Alice和Bob共享的密钥计算出来的,因此Bob能够判断这条消息来自Alice。但上面我们提过,Bob无法向第三方验证者证明这一点,因为发送者Alice可以向第三方验证者声称:“我没有向Bob发送过这条消息(即Bob否认了消息发送)”。 故而消息认证码无法防止否认。
如果要想解决以上两个问题,我们就要改用数字签名技术,可以参阅博文:
-
《一文彻底搞懂公钥密码、数字签名和数字证书》
5. 消息认证码面临的攻击
即便消息认证码可以解决认证和完整性问题,但依然存在如下安全风险:
-
重放攻击:Alice与Bob的通信过程可以被攻击者窃听到,如果攻击者保存了Alice发送的消息及其对应的MAC值,就可以基于此消息和MAC值重复多送发送给Bob,最终导致Bob执行了多次转账。
-
密钥推测攻击:由于HMAC中使用了单向散列函数,那么针对单向散列函数的暴力破解和生日攻击同样可应用于消息认证码攻击。
不过针对以上两种攻击,也有非常多的应对方案,欢迎大家在评论区留下你的答案。网络安全是一个永远聊不完的话题,欢迎大家一起来碰撞!