AES加密演算法研究
1、AES簡介
AES稱為高階加密標準(英語:Advanced Encryption Standard),在密碼學中又稱Rijndael加密法,是美國聯邦政府採用的一種區塊加密標準。這個標準用來替代原先的DES,已經被多方分析且廣為全世界所使用。2006年,高階加密標準已然成為對稱金鑰加密中最流行的演算法之一。
2、設計思想
根據使用的密碼長度,AES最常見的有3種方案,用以適應不同的場景要求,分別是AES-128、AES-192和AES-256。本文主要對AES-128進行介紹,另外兩種的思路基本一樣,只是輪數會適當增加。
以下是演算法程式碼簡要 :
Rijndael (State, ExpandedKey){ AddRoundKey (State, ExpandedKey); for (i=1; i <Nr; i ++) Round (State, ExpandedKey+Nb* i); FinalRound (State, ExpandedKey+Nb*Nr) } } Round (State, RoundKey){ ByteSub (State); ShiftRow (State); MixColumn (State); AddRoundKey (State, RoundKey) } FinalRound (State, RoundKey){ ByteSub (State); ShiftRow (State); AddRoundKey (State, RoundKey) }
AES加密過程是在一個4×4的位元組矩陣上運作,這個矩陣又稱為“狀態(state)”,其初值就是一個明文區塊(矩陣中一個元素大小就是明文區塊中的一個Byte)。(Rijndael加密法因支援更大的區塊,其矩陣行數可視情況增加)加密時,各輪AES加密迴圈(除最後一輪外)均包含4個步驟:
- AddRoundKey : 矩陣中的每一個位元組都與該次輪祕鑰(round key)做XOR運算;每個子金鑰由金鑰生成方案產生。
- SubBytes : 通過非線性的替換函式,用查詢表的方式把每個位元組替換成對應的位元組。
- ShiftRows : 將矩陣中的每個橫列進行迴圈式移位。
- MixColumns : 為了充分混合矩陣中各個直行的操作。這個步驟使用線性轉換來混合每列的四個位元組。
最後一個加密迴圈中省略MixColumns步驟,而以另一個AddRoundKey取代。
3、AES的填充模式
演算法/模式/填充 | 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的整數倍時,假如原始資料長度等於16n,則使用NoPadding時加密後資料長度等於16 n,其它情況下加密資料長度等於16(n+1)。在不足16的整數倍的情況下,假如原始資料長度等於16 n+m[其中m小於16],除了NoPadding填充之外的任何方 式,加密資料長度都等於16*(n+1);NoPadding填充情況下,CBC、ECB和PCBC三種模式是不支援的,CFB、OFB兩種模式下則加密資料長度等於原始資料長度。
4、加密總結:
-
把祕鑰硬編碼在程式碼中有很大風險,通過反編譯程式碼很容易拿到祕鑰。Android開發裡建議用JNI把祕鑰值寫到C 程式碼裡。或是拆分成幾份,最後再組合成真正的祕鑰。也可以使用Android 6.0之後推出的Android KeyStore來儲存金鑰。個人建議是使用Android KeyStore來儲存金鑰。
-
如果先把一個檔案轉換成位元組陣列,然後再加密,最後生成檔案,這樣很大機率很會產生OOM,所以這裡利用了FileChannel,一次讀取一定的位元組數,而後再進行加密解密,最後再通過Channel生成新檔案
-
一個加密的金鑰和加密的字串,然後通過AES演算法密碼把位元組陣列加密,然後轉換成了16進位制,得到數字和字母
-
加密和解密都一樣,就是在設定AES模式(加密和解密)不一樣,還有一個就是對內容的處理,位元組和16進位制的相互轉換
-
同樣的程式碼,Android和java的執行結果是不同的,這應該是兩端的編碼不同導致。
5、什麼時候採用對稱加密?
我們都知道,有對稱加密和非對稱加密,而非對稱加密還分公鑰和私鑰,那是否後者更加安全一點呢?其實兩者都有存在的必要,非對稱加密一般不會單獨拿來使用,他並不是為了取代對稱加密而出現的,非對稱加密速度比對稱加密慢很多,
極端情況下會慢1000 倍,所以一般不會用來加密大量資料,通常我們經常會將對稱加密和非對稱加密兩種技術聯合起來使用,例如用非對稱加密來給稱加密裡的祕鑰進行加密。