AES加解密使用總結

Sunxb發表於2021-12-17

AES

AES, 高階加密標準, 是採用區塊加密的一種標準, 又稱Rijndael加密法. 嚴格上來講, AES和Rijndael又不是完全一樣, AES的區塊長度固定為128位元, 祕鑰長度可以是128, 192或者256. Rijndael加密法可以支援更大範圍的區塊和金鑰長度, Rijndael使用的金鑰和區塊長度均可以是128,192或256位元. AES是對稱加密最流行的演算法之一.

我們不去討論具體的AES的實現, 因為其中要運用到大量的高等數學知識, 單純的瞭解AES流程其實也沒什麼意義(沒有數學基礎難以理解), 所以我們今天著重來總結一些使用過程中的小點.

加密模式 - ECB, CBC

當然了分組密碼的加密模式不僅僅是ECB和CBC這兩種, 其他的我們暫不涉及.

上面說的AES是一種區塊加密的標準, 那加密模式其實可以理解為處理不同區塊的方式和聯絡.

ECB

ECB可以看做最簡單的模式, 需要加密的資料按照區塊的大小分為N個塊, 並對每個塊獨立的進行加密

ECB.png

此種方法的缺點在於同樣的明文塊會被加密成相同的密文塊, 因此, 在某些場合, 這種方法不能提供嚴格的資料保密性. 通過下面圖示例子大家就很容易明白了

EBC2.png

CBC

我們的專案中使用的就是這種模式, 在CBC模式中, 每個明文塊與前一個塊的加密結果進行異或後, 在進行加密, 所以每個塊的加密都依賴前面塊的加密結果的, 同時為了保證第一個塊的加密, 在第一個塊中需要引入初始化向量iv.

CBC.png

CBC是最常用的模式. 他的缺點是加密過程只能是序列的, 無法並行, 因為每個塊的加密要依賴到前一個塊的加密結果, 同時在加密的時候明文中的細微改變, 會導致後面所有的密文塊都發生變化. 但此種模式也是有優點的, 在解密的過程中, 每個塊的解密依賴上一個塊的加密結果, 所以我們要解密一個塊的時候, 只需要把他前面一個塊也一起讀取, 就可以完成本塊的解密, 所以這個過程是可以並行操作的.

填充模式

AES加密每個塊blockSize是128位元, 那如果我們要加密的資料不是128位元的倍數, 就會存在最後一個分塊不足128位元, 那這個塊怎麼處理, 就用到了填充模式. 下面是常用的填充模式.

PKCS7 / PKCS5

PKCS7可用於填充的塊大小為1-255位元, 填充方式也很容易理解, 使用需填充長度的數值paddingSize 所表示的ASCII碼 paddingChar = chr(paddingSize)對資料進行冗餘填充. (後面有解釋)

PKCS5只能用來填充8位元組的塊

我們以AES(128)為例, 資料塊長度為128位元, 16位元組, 使用PKCS7填充時, 填充長度為1-16. 注意, 當加密長度是16整數倍時, 反而填充長度是最大的, 要填充16位元組. 原因是 "PKCS7" 拆包時會按協議取最後一個位元組所表徵的數值長度作為資料填充長度, 如果因真實資料長度恰好為16的整數倍而不進行填充, 則拆包時會導致真實資料丟失.

舉一個blockSize為8位元組的例子

| DD DD DD DD DD DD DD DD | DD DD DD DD 04 04 04 04 |

第二個塊中不足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最好是再向後讀取16個位元組.

參考

感謝閱讀

參考資料

https://zh.wikipedia.org/zh-c...
https://segmentfault.com/a/11...
https://ithelp.ithome.com.tw/...

相關文章