消息认证码
消息认证码的作用
-
消息认证码同时解决消息的完整性和发送者正确性。
- 消息完整性解决的是消息是否有被篡改的问题,也就是保证了消息的完整性。
- 消息认证解决的是消息的发送者正确性的问题,确保消息不是其他人伪装发送的。
什么是消息认证码
- 是一种确认完整性并进行认证的技术,英文是message authentication code,简称MAC。
- 消息认证码的输入是任意长度的消息和一个发送者与接收者之间共享的密钥,输出是固定长度的数据,这个数据称为MAC值。
- 从上面的输入和输出关系,我们很容易想到,消息认证码和单向散列函数有相似之处。所以可以理解为,消息认证码是一种与密钥相关联的单向散列函数。
- 单向散列函数保证了完整性,无法被篡改;共享密钥只有发送者和接收者知道,保证了可以检查发送者身份的正确性。
消息认证码使用过程
- 发送者发送消息后,使用发送的消息和共享密钥计算出MAC值,并发送给接收者
- 接收者接收到消息后,使用接收到的消息和共享密钥计算出MAC值
- 接收者接收到MAC值后,使用接收到的MAC值和自己计算的MAC值做比对。如果相同,则表示消息没有被篡改,且发送者的身份正确。
共享密钥配送问题
从上面的描述中可以得出,消息认证码能够检查发送者身份的关键因素就是共享密钥。所以,共享密钥的配送问题就是关键环节。
解决的办法在第五章的公钥章节中有总结,基本也就包括:公钥、Diffie-Hellman密钥交换等解决思路。
消息认证码实例
-
SWIFT
全称是 Society for Worldwide Interbank Financial Telecommunication(环球银行金融电信协会),银行与银行之间传递交易消息是使用SWIFT,使用了消息认证码保障完整性和对消息进行验证。
共享密钥在使用公钥密码之前,是用人进行配送的。 -
IPsec
此协议是针对IP协议增加爱安全性的一种方式,使用消息认证码对消息内容进行认证和保证完整性。 -
SSL/TLS
这个后续会有专门章节进行介绍。
消息认证码的实现方法
消息认证码有多种实现方式:
- 使用SHA-1等单向散列函数实现,其中一种实现方式为HMAC。
- 使用AES等分组密码实现。
- 分组的密钥作为共享密钥。
- 使用CBC模式进行加密。简单回顾一下CBC模式,就是前一个分组的密文与此分组的明文XOR后,再加密生成当前分组的密文。
- 由于不需要进行解密,所以只保留最后一个分组。由于最后一个分组会受到密钥和整个消息的双重影响,所以可以作为消息认证码。
- 流密码和公钥密码也可以实现消息认证码。
HMAC详细介绍
什么是HMAC
HMAC的H是hash的意思,就是使用单向散列函数来实现的消息认证码。
单向散列函数的具体算法随意选择,如果使用SHA-1,则被称为HMAC-SHA-1。
HMAC具体步骤
-
密钥填充
如果共享密钥小于散列值的长度,则用0补充。
如果共享密钥大于散列值的长度,则使用单向散列函数计算出共享密钥的散列值。 -
填充后的密钥与ipad的XOR
ipad是一种比特序列,是使用00110110这一比特序列不断循环直到分组长度的比特序列。i是inner的意思。
填充后的密钥和ipad XOR计算后的值称为 ipadkey。 -
与消息组合
将ipadkey附在消息的开头。 -
计算散列值
使用单向散列函数计算消息和ipadkey组合的散列值。 -
填充后的密钥与opad XOR
opad是一种比特序列,是使用01011100这一比特序列不断循环直到分组长度的比特序列。o是outer的意思。
填充后的密钥和opad XOR计算后的值称为 opadkey。 -
与散列值合并
将第4步计算的散列值拼接在opadkey后面。 -
计算散列值
将第6步组合后的值进行hash,计算出的散列值就是MAC值。
对消息认证码的攻击
-
重放攻击
- 攻击者可以截获发送者的请求消息和MAC值,然后对接收者重放发送。这时虽然攻击者没有破解消息认证码,但对于接收者来说消息和MAC值是匹配的,所以只能执行。
- 解决的办法。
- 序号。增加一个流水号,每次都加1。有效果,但是通信双方都需要记录最后一个消息的序号。
- 时间戳。发送消息中包含当前时间,如果收到以前的消息则当做错误消息不执行。有效果,但是通信双方的时钟必须一致,不一致也会留下重放攻击的空间。
- nonce。先发送一个伪随机数(称为nonce),然后发送消息计算MAC值时包含nonce。由于每次通信nonce都会发生变化,也就无法进行重放攻击。此办法的缺点是增加了通信量。
-
密钥推测攻击
如果是单向散列函数来进行生成MAC,则使用攻击单向散列函数的暴力破解和生日攻击来完成攻击。
消息认证码无法解决的问题
-
对第三方认证
如果接收者想要让第三方来认证发送者,这点是没法办到的。因为共享密钥只有一个,对于第三方来说无法通过共享密钥来判断到底哪个是发送者,哪个是接收者。 -
防止否认
假设发送者否认自己没有发送消息,