学习《图解密码技术》补充密码学相关基础知识过程中所做的简单学习笔记,只记录要点,所用图例的来源均为《图解密码技术》一书。
本篇主要参考本书第八章——消息认证码
引子
消息是正确的吗?真的是发送者发给我的吗?真的不是坏蛋伪造的吗?
当A银行给B银行发送一条转账请求时,B银行收到这条转账请求时,如何判断这条消息到底是不是A银行发送的呢?会不会是恶意攻击者伪造的发送的消息呢?这就涉及到了消息的“认证”。
单向散列函数可以保证信息的完整性(一致性)。而这里,我们用消息认证码(Message Authentication Code)来对消息进行认证,同时,消息认证码还可以同时识别出消息是否被篡改,既可以确认消息的完整性,也可以对消息进行认证。
消息认证码概要
消息认证码,Message Authentication Code,简称MAC。
消息认证码的输入包括任意长度的消息和一个发送者与接受者之间共享的密钥,输出的是一个固定长度的数值,即MAC值(消息认证码)。
任意长度的输入和固定长度的输出,这一点和单向散列函数。但是单向散列函数在计算时不需要密钥,相对地,消息认证码中就需要使用发送者与接受者之间共享的密钥。消息认证码正是根据这个密钥来完成认证的。因为这个密钥是仅有发送者和接受者持有,第三方没有这个密钥的话就无法计算出消息认证码,无法进行伪造。
消息认证码的使用步骤
消息认证码的步骤如下图所示
- 发送者与接受者事先共享密钥
- 发送者根据消息计算出MAC值(使用共享密钥)
- 发送者将消息和MAC值发送给接受者
- 接受者根据收到的消息计算出MAC值(使用共享密钥)
- 接受者将计算出来的MAC值与发送者发送过来的MAC值进行比较
- 如果两个MAC一只,则接受者可以认定这条消息来自发送者,反之则认证失败
密钥配送问题
由于消息认证码需要发送者与接受者事先共享密钥,那么和对称密码类似,这里也存在一个密钥配送的问题。
解决的方法也一样:
- 公钥密码
- Diffie-Hellman密钥交换
- 密钥分配中心
- 或者使用其他安全方式发送密钥
消息认证码的实现
使用分组密码实现
将分组密码的密钥作为消息认证码的共享密钥来使用,并用CBC模式(密文分组链接模式)对消息全部加密。此时,初始化向量是固定的,由于消息认证码的使用中不需要解密(消息认证码只保证完整性和认证,没有机密性的功能),因此直接将最后一个密文分组外的密文丢弃,取最后一个密文分组来作为MAC值。因为CBC模式的最后一个分组会受到整个消息以及密钥的双重影响,因此可以将它用作消息认证码,起到保证完整性和认证的功能。
使用单向散列函数实现
使用SHA之类的单向散列函数也可以实现消息认证码,称之为HMAC,这里的H
是Hash
的意思。
HMAC的计算消息认证码的步骤如下图所示:
密钥填充
如果密钥比单向散列函数的分组长度要短,则在末尾填充0;如果密钥长度比分组长度长,则计算出密钥的散列值,然后将这个散列值作为HMAC的密钥
填充后的密钥与ipad进行XOR运算
“ipad”是一个固定的比特序列的循环重复(直到达到分组长度为止),这个固定的比特序列是
00110110 (0x36)
,其中ipad的i是inner(内部)的意思。运算后得到的值就是一个和单向散列函数分组长度相同,且和密钥相关的比特序列,这里称为“ipadkey”与消息组合
将ipadkey与消息进行组合,将ipadkey附在消息的开头
计算散列值
将「步骤3」的结果输入单向散列函数,计算出散列值
填充后的密钥与opad逆行XOR运算
“opad”是一个固定的比特序列的循环重复(直到达到分组长度为止),这个固定的比特序列是
01011100 (0x5c)
,其中opad的o是outer(外部)的意思。运算后得到的值就是一个和单向散列函数分组长度相同,且和密钥相关的比特序列,这里称为“opadkey”与散列值组合
将「步骤4」计算出的散列值拼在opadkey的后面
计算散列值
将「步骤6」的结果输入单向散列函数,并计算出散列值,这个散列值就是最终的MAC值
HMAC的伪代码如下图所示:
消息认证码的应用
- SWIFT 环球银行金融电信协会
- IPsec
- SSL/TLS
对消息认证码的攻击
重放攻击
主动攻击者可以将截获的消息和MAC值保存,并重复发送以达到一些效果。例如,保存银行转账的消息和MAC值,然后不断重复发送,就可以不断汇款。这个过程中并没有破解MAC,只是将截获的消息和MAC循环利用而已,这就是重放攻击。
解决方法:
- 每次发送都对消息赋予一个递增的编号(序号),并包含在消息中,纳入MAC的计算过程,这样一来,由于攻击者没有共享密钥,就无法重新计算新的MAC值。
- 时间戳,在发送消息时包含当时的时间,如果收到以前的消息,即便MAC正确也可以将其当作错误的消息来处理,这样也能防御重放攻击。但是这里发送者与接受者的时钟必须一致,并且考虑到通信的延迟,必须在时间的判断上留下缓冲,因此还是存在重放攻击的时间窗口。
密钥推测攻击
和对单向散列函数的攻击一样,同样可以对消息认证码进行暴力破解和生日攻击。
因此对于消息认证码来说,应保证不能根据MAC值反推出通信双方使用的密钥。例如HMAC就是利用单向散列函数的单向性和抗碰撞性来保证这一点的。
消息认证码无法解决的问题
对第三方证明
由于密钥是发送者和接受者双方之间共享的,因此无法向第三方证明,消息是发送者发送的。(接受者也可以自行编写消息并计算MAC值,第三方无法判断这条消息是发送者发送的还是接受者自己编造的)。
防否认
与上一点类似,由于密钥时发送者和接受者双方之间共享的,所以也无法防止发送者否认自己发送了这条消息(比如发送者可以声称这条消息是接受者伪造的,或者是声称接受者泄漏了密钥,可能是其他攻击者伪造的,这种行为称为否认,repudiation)。因此,消息认证码无法防止否认(nonrepudiation)。
要解决这两个问题,就需要使用数字签名技术了。