一些文章书籍中讲到,ECB、CFB加密模式不能抵御重放攻击,举的例子是:用旧报文替换部分新报文达到欺骗接收者的目的。言外之意,似乎CBC模式可以抵御这种攻击。实际情况是不是这样呢?网上一通翻腾竟然无果,那就自己试试吧。虽然小白,不明白大佬的高明,但单从示例类同性上确实要弄清楚为什么。
首先从理论上分析,CBC加密模式的原理是,对每一个明文块,先用前一个密文块与之异或,尔后再用密码算法加密,就得到新的密文块,以此类推,初始的密文块由初始向量提供。计算公式为:C[i]=E(K, P[i]^C[i-1]),这里C代表密文、P代表明文、K代表密钥、E代表密码算法、i代表第几个块;解密公式是反过来,即先经过密码算法、再与前一密文块异或。示意图见下,引自维基百科。
可以看出每一个明密对(P,C)只与3个要素关联,一是密码算法E,二是密钥K,三是前一密文块C。E是不变的,假设K也是不变的,攻击者又掌握着多份截获的C,则P一定能计算出来,也就是攻击者用旧密文替换新密文中的连续块,就可以使合法接收者得到混杂了过时信息的“新”信息。这就是重放攻击,与一些书中描述的CFB重放攻击一模一样。
下面是CFB解密模式示意图,引自维基百科。
程序验证。以DES密码为例,采用CBC加密模式,密钥保持不变,先对一段明文加密,再对另一段明文加密,然后将两个密文重新组合成新密文,再解密,得到了明文1和明文2的混搭。
package main
import (
"fmt"
"crypto/des"
"crypto/cipher"
)
func main() {
// new DES, key immutable
b, err := des.NewCipher([]byte("12345678"))
if err != nil {
fmt.Println(err)
}