消息认证码
消息认证码(Message Authentication Code,简称 MAC)是一种能够识别通信对象发送的消息是否被篡改的认证技术,用于验证消息的完整性,以及对消息进行身份认证。消息认证码的算法中,最常用的是利用散列函数的 HMAC。HMAC 的构成不依赖于某一种具体的散列函数算法。消息认证码能够对通信对象进行认证,但无法对第三方进行认证。此外它也无法防止否认。
主要作用
- 完整性:消息的完整性也叫一致性,也可以理解消息没有被篡改
- 认证:消息的认证是指消息来自正确的发送者,也可以理解为消息不是其他人伪装成发送者所发出的
HMAC 实现原理
HMAC 是一种使用散列函数来构造消息认证码的方法(RFC2014),其中 HMAC 的 H 就是 Hash 的意思。HMAC 中所使用的散列函数并不仅限于一种,任何高强度的散列函数都可以被用于 HMAC,如果将来设计出新的散列函数,也同样可以使用。
对 message 生成消息认证码可以表示为:hmac(message, secret, hash)
,secret 为共享密钥,hash 为所使用散列函数。
(1)密钥填充:如果密钥比散列函数的分组长度要短,就需要在末尾填充 0,直到其长度达到散列函数的分组长度为止。如果密钥比分组长度要长,则要用散列函数求出密钥的散列值,然后将这个散列值用作 HMAC 的密钥。
(2)填充后的密钥与 ipad 的 XOR:将填充后的密钥与被称为 ipad 的比特序列进行 XOR 运算。 ipad 是将 00110110
这一比特序列(即 16 进制的 36)不断循环反复直到分组长度所形成的比特序列,其中 ipad 的 i 是 inner(内部)的意思。XOR 运算所得到的值,就是一个和散列函数的分组长度相同,且和密钥相关的比特序列。这里我们将这个比特序列称为 ipadkey。
(3)与消息组合:将 ipadkey 与消息进行组合,也就是将和密钥相关的比特序列(ipadkey)附加在消息的开头。
(4)计算散列值:将(3)的结果输入散列函数,并计算出散列值。
(5)填充后的密钥与 opad 的 XOR:将填充后的密钥与被称为 opad 的比特序列进行 XOR 运算。opad 是将 01011100
这一比特序列(即 16 进制的 5C)不断循环反复直到达到分组长度所形成的比特序列,其中 opad 的 o 是 outer(外部)的意思。XOR 运算所得到的结果也是一个和散列函数的分组长度相同,且和密钥相关的比特序列,这里我们将这个比特序列称为 opadkey。
(6)与散列值组合:将(4)的散列值拼在 opadkey 后面。
(7)将(6)的结果输入散列函数,并计算出散列值。这个散列值就是最终的 MAC 值。
对消息认证码的攻击
- 重放攻击:攻击者不需要破解消息认证码,只需要将发送者的正确 MAC 值保存下来重放利用就可以。
- 密钥推测攻击:与散列函数攻击一样,消息认证码也可以进行暴露破解以及生日攻击。
关于防止重放攻击的方式
- 序号:约定每次都对发送的消息赋予一个递增的序号,并且在计算 MAC 值时将序号也包含在消息中。由于攻击者无法计算序号递增之后的 MAC 值,因此就可以防御重放攻击。这种方法虽然有效,但是对每个通信对象都需要记录最后一个消息的序号。
- 时间戳:约定在发送消息时包含当前的时间,如果收到以前的消息,即便 MAC 值正确也将其当做错误的消息来处理,这样就能够防御重放攻击。这种方法虽然有效,但是发送者和接受者的时钟必须一致,而且考虑到通信的延迟,必须在时间的判断上留下缓冲,于是多多少少还是会存在可以进行重放攻击的空间。
- nonce:在通信之前,接收者先向发送者发送一个一次性的随机数,这个随机数一般称为 nonce。发送者在消息中包含这个 nonce 并计算 MAC 值。由于每次通信时 nonce 的值都会发生变化,因此无法进行重放攻击。这种方法虽然有效,但通信的数据量会有所增加。
消息认证码无法解决的问题
- 对第三方证明
- 防止否认
由于 MAC 值发送者和接受者都能生成,所以接受者如果要向第三方验证者证明消息的来源为发送者,第三方验证者是无法证明的,因为接受者也是可以生成 MAC 值的;第三方验证者无法判断发送者和接受者谁的主张才是正确的,也就是说,用消息认证码无法防止否认。
数字签名
数字签名是一种能够对第三方进行消息认证,并能够防止通信对象做出否认的认证技术。数字签名的算法包括 RSA,ELGamal,DSA,椭圆曲线 DSA 等。公钥基础设施(PKI)中使用的证书,就是对公钥加上认证机构的数字签名收构成的。要验证公钥的数字签名,需要通过某种途径获取认证机构自身的合法公钥。
数字签名的方法
- 直接对消息签名的方法
- 对消息的散列值签名的方法
直接对消息签名的方法比较容易理解,但实际上并不会使用;对消息的散列值签名的方法稍微复杂一点,但实际中我们一般都使用这种方法。
对数字签名的攻击
- 中间人攻击
- 对散列函数攻击
- 对数字签名攻击公钥密码
- 潜在伪造
数字签名无法解决的问题
用数字签名既可以识别出篡改和伪装,还可以防止否认。也就是说,我们同时实现了确认消息的完整性、进行认证以及否认防止。
然而,要正确使用数字签名,有一个前提,那就是用于验证签名的公钥必须属于真正的发送者。即使数字签名算法再强大,如果你得到的公钥是伪造的,那么数字签名也会完全失效。
为了能够确认自己得到的公钥是否合法,我们需要使用证书。所谓证书,就是将公钥当作一条消息,由一个可信的第三方对其签名后所得到的公钥。
消息认证码 VS 数字签名
- 消息认证基于对称密钥
- 数字签名基于非对称密码
- | 消息认证码 | 数字签名 |
---|---|---|
发送者 | 用共享密钥计算MAC值 | 用私钥生成签名 |
接受者 | 用共享密钥计算MAC值 | 用公钥验证签名 |
密钥配送问题 | 存在 | 不存在(公钥需要另外认证) |
完整性 | 是 | 是 |
认证 | 是(仅限通信对象双方) | 是(可适用任何第三方) |
防止否认 | 否 | 是 |
参考资料
- 图解密码技术(第三版)