CBC加密模式本身不能抵禦重放攻擊
阿新 • • 發佈:2018-12-18
一些文章書籍中講到,ECB、CFB加密模式不能抵禦重放攻擊,舉的例子是:用舊報文替換部分新報文達到欺騙接收者的目的。言外之意,似乎CBC模式可以抵禦這種攻擊。實際情況是不是這樣呢?網上一通翻騰竟然無果,那就自己試試吧。雖然小白,不明白大佬的高明,但單從示例類同性上確實要弄清楚為什麼。 首先從理論上分析,CBC加密模式的原理是,對每一個明文塊,先用前一個密文塊與之異或,爾後再用密碼演算法加密,就得到新的密文塊,以此類推,初始的密文塊由初始向量提供。計算公式為:C[i]=E(K, P[i]^C[i-1]),這裡C代表密文、P代表明文、K代表金鑰、E代表密碼演算法、i代表第幾個塊;解密公式是反過來,即先經過密碼演算法、再與前一密文塊異或。示意圖見下,引自維基百科。
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)
}
// plain/cipher text 1
be := cipher.NewCBCEncrypter(b, []byte("11111111"))//iv1
bd := cipher.NewCBCDecrypter(b, []byte("11111111"))
p1 := []byte ("12345678abcdefghABCDEFGH87654321")//plaintext
var c1 = make([]byte, len(p1))//ciphertext
var r1 = make([]byte, len(p1))//decrypttext
be.CryptBlocks(c1, p1)
bd.CryptBlocks(r1, c1)
fmt.Printf("// nomal encrypt/decrypt 1:\n")
fmt.Printf("plaintext1 : %s\n", p1)
fmt.Printf("ciphertext1: % 2x\n", c1)
fmt.Printf("decryptext1: %s\n\n", r1)
// plain/cipher text 2
be = cipher.NewCBCEncrypter(b, []byte("22222222"))//iv2
bd = cipher.NewCBCDecrypter(b, []byte("22222222"))
p2 := []byte("ABCDEFGH8765432112345678abcdefgh")
var c2 = make([]byte, len(p2))
var r2 = make([]byte, len(p2))
be.CryptBlocks(c2, p2)
bd.CryptBlocks(r2, c2)
fmt.Printf("// nomal encrypt/decrypt 2:\n")
fmt.Printf("plaintext2 : %s\n", p2)
fmt.Printf("ciphertext2: % 2x\n", c2)
fmt.Printf("decryptext2: %s\n\n", r2)
// replay attack with fault cipher(c2[0:8]+c1[8:])
bd = cipher.NewCBCDecrypter(b, []byte("22222222"))
c := append(c2[:8], c1[8:]...)
var r = make([]byte, len(p1))
bd.CryptBlocks(r, c)
fmt.Printf("// replay attack with cipher2[:8] + cipher1[8:]:\n")
fmt.Printf("faultcipher: % 2x\n", c)
fmt.Printf("decryptext : %s\n\n", r)
}
執行結果如下,最後解密亂碼部分對應的正好是重放的第一塊密文:
// nomal encrypt/decrypt 1:
plaintext1 : 12345678abcdefghABCDEFGH87654321
ciphertext1: 6e 8b 79 29 82 6f ae de af ea b3 18 51 0e 83 25 d6 11 19 34 d4 82 f4 0d ed 0e 1f fc a5 da cc 6e
decryptext1: 12345678abcdefghABCDEFGH87654321
// nomal encrypt/decrypt 2:
plaintext2 : ABCDEFGH8765432112345678abcdefgh
ciphertext2: 1b 6d eb 8b f7 cd ce bd 48 eb 3b 5c 4b fe cb 66 9b d1 7b f0 c1 aa 77 04 22 fa 95 c3 c5 a2 4e f7
decryptext2: ABCDEFGH8765432112345678abcdefgh
// replay attack with cipher2[:8] + cipher1[8:]:
faultcipher: 1b 6d eb 8b f7 cd ce bd af ea b3 18 51 0e 83 25 d6 11 19 34 d4 82 f4 0d ed 0e 1f fc a5 da cc 6e
decryptext : ABCDEFGH����ABCDEFGH87654321
如上說明,防止這種“混搭”式的重放攻擊,還需要從應用協議的角度引入nonce、序號、時間戳、簽名、認證等要素,單純依靠這種通用模式是不行的。