A. 關於AES加解密中CBC模式的IV初始化向量的安全性問題
前段時間,在研究HLS的AES加密,由於一個地方電視台的HLS流有AES加密,在查看了相關的加解密方案後發現使用的是簡單的AES的CBC模式,在CBC的模式下,會設置一個IV,初始化向量。但是我在解密的時候,使用了一個由於理解錯誤而產生的一個錯誤IV居然也能解密視頻並進行播放,於是就有了這篇張文章。
雖然有五種加密,但是常用的還是CBC,CBC的全稱Cipher Block Chaining ,有點類似於區塊鏈哈,我們先來看下加密方式
上面的圖片從左往右看,初始化IV只有在第一個塊加密的時候才會用到,而第N個塊的加密IV則是用的N-1(N>1)個加密後的二進制數組。
CBC的解密則也是從左往右看,但是加密時IV在解密時候,只會用於對第一個塊進行解密,其他塊的解密則是使用上一塊的加密二進製作為IV進行解密操作。
通過上面的分析就能知道,加密的時候,iv會影響所有數據的加密結果,而解密時,iv只會影響第一個加密塊的解密結果,其他塊的解密可以直接通過分隔加密數據獲取正確是N-1塊的IV。
這也就印證了為什麼ff能播放我用錯誤的iv解密出來的視頻流數據,因為第一塊的大小存儲大概是id3 的數據,ff直接丟掉id3的數據,直接解碼後面的視頻數據 ,ff 應該是識別h264編碼頭開始解碼視頻。
那麼從這點可以看出,在使用了key的情況下,IV對整個數據的保密性沒有太大的作用。
再來說說我是怎麼發現這個問題,因為錯誤的IV只會影響第一個塊的數據,我在第一次嘗試解密後,直接用ff進行播放,ff能夠解碼並且播放成功,但是相對於其他未加密的HLS流來說,播放我解密後的數據會有3-5s的延時,這讓我很是頭疼,後來我就通過 ffplay -v trace 列印播放解密的日誌,發現視頻數據的id3信息丟失了,那麼出問題出在第一個塊。然後再次研究m3u8加解密IV的賦值方法,後發來經過多次試驗,正確賦值IV,解密出來的數據能夠及時播放。再後來,就出現了這篇文章的來由。
由此帶來的延展,針對iv在CBC模式下的弱用,AES提供了更多的模式可供選擇,詳細的可以到wiki上了解。
https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
B. AES加解密使用總結
AES, 高級加密標准, 是採用區塊加密的一種標准, 又稱Rijndael加密法. 嚴格上來講, AES和Rijndael又不是完全一樣, AES的區塊長度固定為128比特, 秘鑰長度可以是128, 192或者256. Rijndael加密法可以支持更大范圍的區塊和密鑰長度, Rijndael使用的密鑰和區塊長度均可以是128,192或256比特. AES是對稱加密最流行的演算法之一.
我們不去討論具體的AES的實現, 因為其中要運用到大量的高等數學知識, 單純的了解AES流程其實也沒什麼意義(沒有數學基礎難以理解), 所以我們今天著重來總結一些使用過程中的小點.
當然了分組密碼的加密模式不僅僅是ECB和CBC這兩種, 其他的我們暫不涉及.
上面說的AES是一種區塊加密的標准, 那加密模式其實可以理解為處理不同區塊的方式和聯系.
ECB可以看做最簡單的模式, 需要加密的數據按照區塊的大小分為N個塊, 並對每個塊獨立的進行加密
此種方法的缺點在於同樣的明文塊會被加密成相同的密文塊, 因此, 在某些場合, 這種方法不能提供嚴格的數據保密性. 通過下面圖示例子大家就很容易明白了
我們的項目中使用的就是這種模式, 在CBC模式中, 每個明文塊與前一個塊的加密結果進行異或後, 在進行加密, 所以每個塊的加密都依賴前面塊的加密結果的, 同時為了保證第一個塊的加密, 在第一個塊中需要引入初始化向量iv.
CBC是最常用的模式. 他的缺點是加密過程只能是串列的, 無法並行, 因為每個塊的加密要依賴到前一個塊的加密結果, 同時在加密的時候明文中的細微改變, 會導致後面所有的密文塊都發生變化. 但此種模式也是有優點的, 在解密的過程中, 每個塊的解密依賴上一個塊的加密結果, 所以我們要解密一個塊的時候, 只需要把他前面一個塊也一起讀取, 就可以完成本塊的解密, 所以這個過程是可以並行操作的.
AES加密每個塊blockSize是128比特, 那如果我們要加密的數據不是128比特的倍數, 就會存在最後一個分塊不足128比特, 那這個塊怎麼處理, 就用到了填充模式. 下面是常用的填充模式.
PKCS7可用於填充的塊大小為1-255比特, 填充方式也很容易理解, 使用需填充長度的數值paddingSize 所表示的ASCII碼 paddingChar = chr(paddingSize)對數據進行冗餘填充. (後面有解釋)
PKCS5隻能用來填充8位元組的塊
我們以AES(128)為例, 數據塊長度為128比特, 16位元組, 使用PKCS7填充時, 填充長度為1-16. 注意, 當加密長度是16整數倍時, 反而填充長度是最大的, 要填充16位元組. 原因是 "PKCS7" 拆包時會按協議取最後一個位元組所表徵的數值長度作為數據填充長度, 如果因真實數據長度恰好為16的整數倍而不進行填充, 則拆包時會導致真實數據丟失.
舉一個blockSize為8位元組的例子
第二個塊中不足8位元組, 差4個位元組, 所以用4個4來填充
嚴格來講 PKCS5不能用於AES, 因為AES最小是128比特(16位元組), 只有在使用DES此類blockSize為64比特演算法時, 考慮使用PKCS5
我們的項目最開始加解密庫使用了CryptoSwift, 後來發現有性能問題, 就改為使用IDZSwiftCommonCrypto.
這里咱們結合項目中邊下邊播邊解密來提一個點, 具體的可以參考之前寫的 邊下邊播的總結 . 因為播放器支持拖動, 所以我們在拖拽到一個點, 去網路拉取對應數據時, 應做好range的修正, 一般我們都會以range的start和end為基準, 向前後找到包含這個range的所有塊范圍. 打比方說我們需要的range時10-20, 這是我們應該修正range為0-31, 因為起點10在0-15中, 20 在16-31中. 這是常規的range修正.(第一步 找16倍數點).
但是在實際中, 我們請求一段數據時, 還涉及到解密器的初始化問題, 如果我們是請求的0-31的數據, 因為是從0開始, 所以我們的解密器只需要用key和初始的iv來進行初始化, 那如果經過了第一步的基本range修正後, 我們請求的數據不是從0開始, 那我們則還需要繼續往前讀取16個位元組的數據, 舉個例子, 經過第一步修正後的range為16-31, 那我們應該再往前讀取16位元組, 應該是要0-31 這32個位元組數據, 拿到數據後,使用前16個位元組(上一個塊的密文)當做iv來初始化解密器.
還有一個要注意的點是, 數據解密的過程中, 還有可能會吞掉後面16個位元組的數據, 我暫時沒看源碼, 不知道具體因為什麼, 所以保險起見, 我們的range最好是再向後讀取6個位元組.
感謝閱讀
參考資料
https://zh.wikipedia.org/zh-cn/%E9%AB%98%E7%BA%A7%E5%8A%A0%E5%AF%86%E6%A0%87%E5%87%86
https://segmentfault.com/a/1190000019793040
https://ithelp.ithome.com.tw/articles/10250386
C. 關於分組密碼CBC模式與CTR模式的對比
在對稱分組密碼體制中 CBC模式(密文分組鏈接模式) 與 CTR模式(計數器模式) 是安全性最高且舉圓最常用的兩種模式,在這兩種模式中前一分組會以不同的形式影響下一分組的加密過程,因此這兩種模式的安全性相對較高。
在項目研發過程中,需求是要在嵌入式節點間實現實時安全通信,而CTR模式能夠支持並行加解密過程計算,因而 在項目中選擇CTR模式的SM4對稱加密演算法。
以下對於分組密碼中CBC模式以及CTR模式的原理進行簡賀毀單介紹:
CBC模式的全稱是Cipher Block Chaining模式(密文分組鏈接模式),之所以叫這個名字,是因為密文分組像鏈條一樣相互連接在一起。首先將明文分組與前一個密文禪答備分組進行XOR運算,然後再進行加密。 註:對於第一個分組需要構造一個長度為分組長度的初始向量IV。
1)能夠隱蔽明文的數據模式,相同的明文對應的密文一般是不同的;
2)無法單獨對中間的明文分組進行加密。例如,如果要生成密文分組3,必須按序生成密文分組1和密文分組2。
CTR模式全稱counter模式(計數器模式)。CTR模式通過對逐次累加的計數器加密來生成密鑰分組與明文分組異或產生密文分組。
CTR模式的解密過程將明文分組與密文分組位置調換即可。
從原理圖中可以看出:
1)能夠隱蔽明文的數據模式,相同的明文對應的密文一般是不同的;
2)CTR模式中可以以任意順序對分組進行加密和解密,能夠以任意順序處理分組,意味著能夠實現並行計算。使用並行計算,CTR模式的加解密是非常快的。
D. AES共有ECB,CBC,CFB,OFB,CTR五種模式分別有什麼區別
轉:
JCE中AES支持五中模式:CBC,CFB,ECB,OFB,PCBC;支持三種填充:NoPadding,PKCS5Padding,ISO10126Padding。不支持SSL3Padding。不支持「NONE」模式。
其中AES/ECB/NoPadding和我現在使用的AESUtil得出的結果相同(在16的整數倍情況下)。
不帶模式和填充來獲取AES演算法的時候,其默認使用ECB/PKCS5Padding。
演算法/模式/填充
16位元組加密後數據長度 不滿16位元組加密後長度
AES/CBC/NoPadding
16
不支持
AES/CBC/PKCS5Padding
32
16
AES/CBC/ISO10126Padding
32
16
AES/CFB/NoPadding
16
原始數據長度
AES/CFB/PKCS5Padding
32
16
AES/CFB/ISO10126Padding
32
16
AES/ECB/NoPadding
16
不支持
AES/ECB/PKCS5Padding
32
16
AES/ECB/ISO10126Padding
32
16
AES/OFB/NoPadding
16
原始數據長度
AES/OFB/PKCS5Padding
32
16
AES/OFB/ISO10126Padding
32
16
AES/PCBC/NoPadding
16
不支持
AES/PCBC/PKCS5Padding
32
16
AES/PCBC/ISO10126Padding
32
16
可以看到,在原始數據長度為16的整數倍時,假如原始數據長度等於16*n,則使用NoPadding時加密後數據長度等於16*n,其它情況下加密數據長度等於16*(n+1)。在不足16的整數倍的情況下,假如原始數據長度等於16*n+m[其中m小於16],除了NoPadding填充之外的任何方式,加密數據長度都等於16*(n+1);NoPadding填充情況下,CBC、ECB和PCBC三種模式是不支持的,CFB、OFB兩種模式下則加密數據長度等於原始數據長度。
E. 密碼技術(四、二)之分組模式(CBC模式)
CBC模式是指將前一個密文分組與當前明文分組的內容混合起來進行加密,這樣就可以避免ECB模式的弱點。
CBC模式的全稱Cipher Block Chaining 模式(密文分組組鏈接模式),之所以叫這個名字是因為密文分組是像鏈條一樣相互連接在一起。
在CBC模式中,首先將明文分組與前一個密文分組進行XOR運算,然後再進行加密。
ECB模式 和 CBC模式比較
當加密第一個明文分組是,由於不存在「前一個密文分組」,因此需要事先准備一個長度為一個分組的比特序列來替代「前一個密文分組」,這個比特序列稱為 初始化向量 ,通常縮寫為IV。每次加密時都會隨機產生一個不同的比特序列來作為初始化向量。
明文分組在加密之前一定會與「前一個密文分組」進行XOR運算,因此即便明文分組1和2的值是相等的,密文分組1和2的值也不一定是相等的。這樣一來,ECB模式的缺陷在CBC模式中就不存在了。
在CBC模式找那個,我們無法單獨對一個中間的明文分組進行加密。例如,如果要生成密文分組3,則至少需要湊齊明文分組1、2、3才行。
假設CBC模式加密的密文分組中有一個分組損壞了。在這種情況下,只要密文分組的長度沒有發生編號,則解密時,最多隻會影響2個分組受到數據損壞的影響。
假設CBC模式的密文分組中有一些比特缺失了,那麼此時即便只缺失了1比特,也會導緻密文分組的長度發生變化,此後的分組發生錯位,這樣一來,缺失比特的位置之後的密文分組也就全部無法解密了。
假設主動攻擊者Mallory的目的是通過修改密文來操縱解密後的明文。如果Mallory能夠對初始化向量中的任意比特進行反轉,則明文分組中相應的比特也會被反轉。這是因為在CBC模式的解密過程中,第一個明文分組會和初始化向量進行XOR運算。
這樣,Mallory 就可以對初始化向量進行攻擊,但是想要對密文分組也進行同樣的攻擊就非常困難了。
填充提示攻擊 (Padding Oracle Attack)是一種利用分組密碼中的填充部分來進行攻擊的方法。在分組密碼中,當明文長度不為分組長度的整數倍時,需要在最後一個分組填充一些數據使其湊滿一個分組的長度。在填充提示攻擊中,攻擊者會反復發送一段密文,每次發送時都對填充的數據進行少許改變。由於接收者在無法正確解密時會返回一個錯誤消息,攻擊者通過這一錯誤消息就可以獲得一部分與明文相關的信息。這一攻擊方式並不僅限於CBC模式,而是適用於所有需要進行分組填充的模式。2014年對SSL3.0造成重大影響的POODLE攻擊實際上就是一種填充攻擊。要防禦這種攻擊,需要對密文進行認證,確保這段密文的確是由合法的發送者在制定明文內容的前提下生成的。
初始化向量必須使用不可預測的隨機數。然後在SSL/TSL1.0的版本協議中,初始向量並沒有使用不可預測的隨機數,而是使用了上一次CBC模式加密時的最後一個分組。為了防禦攻擊者對此進行攻擊,TSL1.1以上的版本中改為了必須顯式得傳送初始化向量。
確保互聯網安全的通信協議之一SSL/TSL,就是使用CBC模式來確保通信的機密性的,如使用CBC模式三重DES的3DES_EDE_CBC以及CBC模式256比特AES的AES_256_CBC等。
分組密碼中海油一種模式叫作CTS模式(Cipher Text Stealing模式)。在分組密碼中,當明文長度不能被分組長度整除時,最後一個分組就需要進行填充。CTS模式是使用最後一個分組的其哪一個密文分組數據來講信息填充的,它通常和ECB模式以及CBC模式配合使用。根據最後一個分組的發送順序不同,CTS模式有幾種不同的變體(CBC-CS1、CBC-CS2、CBC-CS3)。
該系列的主要內容來自《圖解密碼技術第三版》
我只是知識的搬運工
文章中的插圖來源於原著
F. 密碼學基礎(二):對稱加密
加密和解密使用相同的秘鑰稱為對稱加密。
DES:已經淘汰
3DES:相對於DES有所加強,但是仍然存在較大風險
AES:全新的對稱加密演算法。
特點決定使用場景,對稱加密擁有如下特點:
速度快,可用於頻率很高的加密場景。
使用同一個秘鑰進行加密和解密。
可選按照128、192、256位為一組的加密方式,加密後的輸出值為所選分組位數的倍數。密鑰的長度不同,推薦加密輪數也不同,加密強度也更強。
例如:
AES加密結果的長度由原字元串長度決定:一個字元為1byte=4bit,一個字元串為n+1byte,因為最後一位為'