為什麼說密文鏈接模式已經喪失安全性?
我在《Java加密與解密的藝術》中看到,密文鏈接模式——CBC(已經失去安全性,不推薦使用),為什麼CBC失去了安全性?
看到 @玄星 同學回答了這麼一個密碼學中的經典問題,我自己也興奮了起來,準備補充一下玄星同學的答案。這也算是不請自來吧~本回答的代碼來自我自己的博客http://blog.sina.com.cn/s/blog_6e451145010137zz.html。本回答的題目來自Dan Boneh在Coursera上的公開課「Cryptology」。==============================分割線==================================
0. CBC模式的安全性問題總述
玄星同學的回答是正確的,CBC模式提供了使用Padding Oracle Attack攻擊。這個Padding技術本身其實是一個分組加密技術的一個補充。但是,這個技術如果結合了CBC模式的加密,就出現了潛在的漏洞。攻擊者有可能通過這個漏洞,在不知道密鑰的前提下,完全解密用CBC模式加密的信息。 我想補充的是,Padding Oracle Attack本身是密碼學系統中Chosen Ciphertext Attack(CCA)的一種典型攻擊。理論界一直在強調CCA安全,但是不具有CCA安全的加密系統真的不安全嗎?Padding Oracle Attack回復了這個問題,並且呼籲在實際中使用具有CCA安全的加密系統。 下面,我分幾個部分詳細解釋一下CBC模式,Padding技術,以及Padding Oracle Attack,並且通過Dan Boneh在Coursera中「Cryptology I」上的一個習題,來實際演示一下Padding Oracle Attack到底如何進行。==============================分割線==================================1. Padding技術介紹 我們知道,DES,AES等加密方案是分組加密(Block Cipher),而流加密(Stream Cipher)不是分組加密。分組加密的基本原理是,對消息進行分組,比如每128bit分成一份,然後對每一份進行加密,並在最後組合成密文。對於DES來說,消息的分組長度是64bit,對於AES來說,消息的分組長度是128bit。值得注意的是,AES剛開始的時候分組長度是可以選擇為128bit,192bit和256bit的,但是在最後確定為AES標準後,固定了分組長度為128bit。 那麼就有個問題了,並不是所有的消息長度都是固定為128的整數倍的。因此,如果對消息進行分組,分組多出來不夠128bit的部分怎麼辦呢?一種行之有效的方法就是對不夠的地方進行填充,這就是Padding技術。 Padding技術的原理是,對於消息進行分組後,最後一組後面缺了多少位,那麼就在後面補上多少個缺的位數的數字。這聽起來比較繞口,我們來舉個例子:比如分組長度為4byte,也就是32bit。數據分組後,最後一組就剩下了1byte(比如為8A),那麼就在後面填充三個03,變為8A030303。這樣就補夠了4byte。如果數據本身有2byte(比如為4FFF),那麼就在後面填充兩個02,變為4FFF0202。如果數據正好為4byte(4F3E2D1C),那麼就在後面再多加上4byte的04,即為4F3E2D1C04040404。這樣一來,就保證了對於任何長度的消息,都能夠進行正確的分組,隨後再進行後面的加密過程。==============================分割線==================================
2. CBC模式介紹
分組以後,我們再應用AES演算法對每組進行加密,看起來挺有效的,這種模式也稱作單鑰密碼體制中的ECB模式。但是這將出現一個問題:對於相同的密鑰,如果消息內容相同,那麼加密的結果也相同,而這無疑會給攻擊者透露消息。 舉個簡單的例子,假設Alice和Bob進行通信之前,Alice都需要先打個招呼,比如發送給Bob一個"Hello Bob"的消息,Bob收到後返回一個"Hello Alice",然後雙方進行通信。現在為了安全,我們對Alice和Bob的通信進行加密。假設"Hello Bob"的加密結果是「!!#$%^」,"Hello Alice"的加密結果是"^%$#!"。那麼,無論怎麼加密,只要Alice和Bob互相之間的密鑰不變,他們每次通信開始時,Alice都會發一個「!!#$%^」給Bob,Bob會回復一個"^%$#!"給Alice。這樣一來,攻擊者就可以竊聽信道,如果收到了類似「!!#$%^」或者"^%$#!",就知道Alice和Bob要通信了。更嚴重的是,攻擊者也可以偽裝成Alice,向Bob發送一個「!!#$%^」,這樣就欺騙了Bob,讓其以為要與Alice通信了。 這個攻擊的問題就在於,如果密鑰不變,那麼對於相同的消息,其加密結果一定是相同的。如何解決這個問題呢?人們提出了CBC模式。CBC模式是用於一般數據加密的一個普通的分組密碼演算法。在這個模式中,第一個密文分組的計算需要一個特殊的明文,習慣上稱之為初始向量(IV)。IV是一個隨機的分組,每次會話加密時都要使用一個新的隨機IV,IV無須保密,但一定是不可預知的。由於IV的隨機性,IV將使得後續的密文分組都因為IV而隨機化。由於IV需要公開,且第一個分組的加密結果是IV,因此CBC模式對於m個分組的明文將輸出m+1個分組的密文。模式的原理圖如下(圖片來源:HappyHippy的博客對稱加密和分組加密中的四種模式(ECB、CBC、CFB、OFB)):因為IV的引入,每次加密IV的不同將導致整個密文都會產生變化,這就解決了上面所說的問題。==============================分割線==================================3. CCA攻擊在講CCA攻擊前,我先大概說一下什麼叫做安全的加密。具體的定義呢,大家需要去參考一下語義安全(Semantic Security),CPA安全(Chosen Plaintext Security),以及CCA安全的形式化定義。我們直觀上認為,一個加密是安全的,只要從密文中恢復不出明文就行了。但實際上密碼學中對於安全的概念要高的多。密碼學要求:密文不能泄露任意有關消息的信息。換個說法就是:密文看起來要像一個隨機數。大家可以稍微想一下這裡面的關係。那麼,如果攻擊者能夠從密文中獲取到對應明文哪怕一點點的信息,我們就認為這個加密方法是不安全的。CCA攻擊的意思是,攻擊者在攻擊演算法的過程中,可以獲得任意密文通過Key解密的明文。這是什麼意思呢?就是說,攻擊者雖然不知道私鑰Key,但是可以知道除了被攻擊的密文外,任意密文在Key下的解密結果。這樣一來,攻擊者就有了很強的能力。舉個例子,假定被攻擊的密文是C,攻擊者可以隨便變一變C,弄出一個密文來,並要求加密者解密。解密的結果當然不是C對應的明文了(因為C被改了嘛),但是解密的結果有可能會泄露一些有關C對應明文的信息。這樣一來,攻擊者就更有可能成功對密文C進行攻擊,從密文中獲取有用的信息了。
==============================分割線==================================4. Padding Oracle Attack如果我們用公式寫出CBC模式的話,我們會發現有如下規律。假設有數據有4個分組,第一個分組當然是初始化向量IV了,第二個分組就是密文c[0],後面依次為c[1],c[2], c[3]。這時:其中Enc是分組加密中的加密演算法。解密過程是反過來的,即:
這樣我們就猜測出了m[0]的最後一位;然後,我們猜測m[0]的第二位為g,即構造密文
進行循環猜測,最終把明文全部猜測出來。這個攻擊的演算法複雜度為遠遠小於猜測密鑰的複雜度,攻擊有效。==============================分割線==================================5. Padding Oracle Attack在實際中的應用這種攻擊在實際中有沒有用呢?畢竟我們在實際中根本可以不允許攻擊者進行解密問詢,即讓其獲得任意密文所對應的明文。然而,實際中確實有這種攻擊方法。在舊版本的TLS協議中,有如下問題:對於Padding有問題的密文,其返回padding錯誤(瀏覽器上顯示error 403);對於Padding正確但是解密消息不對,其返回失敗錯誤(瀏覽器上顯示error 404)。這樣一來,攻擊者可以像伺服器提交密文,看其返回的錯誤是403還是404,來進行這樣的攻擊了。==============================分割線==================================6. 一種實際的攻擊我們在此引用Dan Boneh在公開課的一道習題,來演示Padding Oracle Attack。我們來看一下題目。
Problem Set:Padding oracles attack
A web site administrator found
these log entries in a web server log. After some digging, the
admin realized that the first log entry is an AES CBC encryption
with random IV of some secret data (the ciphertext is hex encoded
and appears right after the "GET /"). The secret data contains
private user data that should only be known to the web
site.
After more digging the admin realized that the
web site is vulnerable to a CBC padding oracle attack. In
particular, when a decrypted CBC ciphertext ends in an invalid pad
the web server returns a 403 error code (forbidden request). When
the CBC padding is valid, but the message is malformed the web
server returns a 404 error code (URL not found). To her horror, the
admin realized that the log entries following the first entry are a
result of a remote CBC padding oracle attack on the ciphertext in
the first log entry.
See if you can use the given log entries to
recover the decryption of the ciphertext in the first log entry.
Keep in mind that the first ciphertext block is the random IV. The
decrypted message is ASCII encoded.
We discussed CBC padding oracle attacks in
Lecture
7.6, but if you want to read more about them, please see
Vaudenays paper.
這個題目中也給出了Padding Oracle Attack的出處(Vaudenays Paper),有興趣的朋友們可以看看。我們來使用Java,通過Padding Oracle Attack來恢復明文。根據題目所給的log,我們先讀取到程序中:public static ArrayList&
File file = new File(FileDir);
try {
ArrayList&
FileInputStream fis = new FileInputStream(file);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
String line;
while((line = br.readLine()) != null){
result.add(line);
}
br.close();
fis.close();
result.remove(0);
return result;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
然後,我們把後面error是404的文件挑出來:
public static ArrayList&
ArrayList&
for (int i=0; i&
然後,我們把已經都猜測出來的數據列出來,也就是沒有2020重複的那組數據,最後我們得到:
dce6acb565dd951c642b9feeebcdffc9afa631b5b91c019d
d9dcd464e333b164
6b2866e615fb3944 1cccbdfdfe54684ddaffd5ebb46574cd
5bbe267664c56c93fa32af307095725b
4645bd2dfcd230df
由於這些都是猜了16輪的,也就是說他們的padding都是10101010101010101010101010101010。根據CBC的原理,我們知道第一組數據是沒有用的,那個是IV的轉換,沒有價值。從第二個開始我們將每一個數據xor
1010...1010。我們就得到了D(k, c[i])的值,得到的結果為:BFB621A5A90C118D
C9CCC474F323A1747B3876F605EB2954
0CDCADEDEE44785DCAEFC5FBA47564DD
4BAE366674D57C83
EA22BF206085624B 5655AD3DECC220CF
= c[0] xor D(k,
c[1]),而且我們現在也得到了所有需要的數據,我們就根據公式依次進行計算即可,最後得到的結果為:757365723D22416C
696365223B2070617373776F72643D22
70616464696E67206F7261636C657320
6172652064616E6765726F7573212209
0909090909090909
這顯然就是ASCII編碼的英文字母加上標點符號嘛~最後有9個09作為padding位。翻譯以後,我們得到明文為:user="Alice"; password="padding
oracles are dangerous!"
因為CBC提供了使用Padding Oracle攻擊的可能性。
Padding oracle attack
wiki裡面說到:
In symmetric cryptography, the padding oracle attack is most commonly applied to the CBC mode of operation, where the "oracle" (usually a server) leaks data about whether the padding of an encrypted message is correct or not. Such data can allow attackers to decrypt (and sometimes encrypt) messages through the oracle using the oracles key, without knowing the encryption key.
在CBC模式下,IV(初始化向量)的改變可以直接反映在解密後的明文上,且IV是黑客可以操縱的。如果Server對兩種錯誤 1. Padding錯誤,2. 明文錯誤分別報錯的話,就有可能被黑客利用,讓黑客可以在不知道密鑰的情況下解密信息。
這個不能說cbc不安全。cbc+Padding+錯誤報警全產生這個問題。程序設計需要全面的調試信息,與信息安全衝突。
上面幾位說的很清楚,我再來擴充下。題主可以從cbc.ecb.ofb.cfb這4種模式入手,比較出優缺點。
推薦閱讀:
※AES加密標準怎麼樣?
※大神們幫忙解一下這串密碼,應該是四方或者二方密碼(我也不知道對不對)?
TAG:加密解密 |