產生背景:高級加密標准AES(Advanced Encryption Standard)是在DES受到不斷攻擊威脅的背景下推出的。1997年4月15日,美國國家標准技術研究所(NIST)向全世界征集高級加密標准算法(主要指標:(1)安全性,(2)成本,(3)算法和實現特性等)。有5個候選算法進入了最后一輪評選,分別是:MARS,RC6,Rijndael,Serpent和Twofish,最終獲勝的Rijndael算法即為目前通稱的AES算法。
Rijndael由兩位比利時密碼學家Vincent Rijmen和Joan Daemen設計,具有良好的有限域以及有限環數學理論基礎(只會簡要介紹)。Rijndael算法屬於分組加密算法,分組長度可以是128比特、192比特和256比特,密鑰長度也是這三個可選值。不同的分組組合,迭代次數和密鑰拓展時略有差異,只介紹AES-128版本的加密部分。
數學基礎:字節運算是Rijndael的基本運算,一個字節可以用\(GF(2^8 )\)中的元素表示。有限域\(GF(2^8 )\)的運算可以采用幾種不同方法表示,Rijndael算法選擇傳統的多項式表示。將\(b_7 b_6 b_5 b_4 b_3 b_2 b_1 b_0\)構成的字節b看成系數在{0,1}中的多項式:\(b_7 x^7+b_6 x^6+b_5 x^5+b_4 x^4+b_3 x^3+b_2 x^2+b_1 x+b_0\),例如十六進制數‘57’對應的二進制為01010111,看成一個字節,對應的多項式為\(x^6+x^4+x^2+x+1\)。
在多項式表示中,兩個元素的和仍然是一個次數不超過7的多項式,其系數等於兩個元素對應系數的模2加(按位異或)。由於每個元素的加法逆元等於自己,所以減法和加法相同。
在\(GF(2^8 )\)上的乘法定義為二進制多項式的乘積以8次不可約多項式\(m(x)=x^8+x^4+x^3+x+1\)(十六進制表示為'11B')為模約減的結果。例如十六進制的'80'⋅'02'='1B':
\('80'⋅'02'=(1000 0000)_2⋅(0000 0010)_2\)
\(=x^7⋅x=x^8+(x^8+x^4+x^3+x+1)(mod m(x))\)
\(=x^4+x^3+x+1=(0001 0000)_2='1B'\)
\(GF(2^8 )\)上還定義了一個運算,稱之為x乘法,其定義為:\(x⋅b(x)=b_7 x^8+b_6 x^7+b_5 x^6+b_4 x^5+b_3 x^4+b_2 x^3+b_1 x^2+b_0 x(mod m(x))\)。如果\(b_7=0\)的話,則乘積結果求模后不變,反之乘積結果求模則會減去m(x)(即異或)。於是,當x(十六進制數'02')與b(x)相乘時,可以先將b(x)在字節內左移一位(最后一位補0),若\(b_7=1\),則再和'1B'(其二進制為00011011,因為要模\(m(x)=x^8+x^4+x^3+x+1\))做逐比特異或來實現。乘法運算滿足分配律,可以將復雜的乘法運算分解成'01'和'02'的乘法組合來簡化計算。
AES:高級加密標准AES(Advanced Encryption Standard)的明文及中間處理結果(迭代各輪的輸入、輸出)都稱為狀態,且被表示成4行的矩陣,矩陣的每個元素是一個字節,並看成是\(GF(2^8 )\)上的一個元素。把一個明文分組寫成矩陣時,按先列后行的規則寫入。對於AES-128來說,明文和密鑰都是4×4的矩陣。AES的加解密原理框圖如下:
AES-128算法由10輪組成,加解密過程滿足可逆性。AES-128加密過程如下:1. 初始變換之輪密鑰加。明文狀態數組與第一個輪密鑰進行加法運算。輪密鑰被表示成與明文狀態同樣大小的矩陣,由種子密鑰通過密鑰擴展算法產生。2. 完全相同的9輪迭代。每輪以此執行字節替換、行移位、列混合和輪密鑰加。每一輪以上一輪的輸出為輸入。3. 結尾輪變換。與前面各輪稍有不同,依次執行字節替換、行移位和輪密鑰加。取消了列混合。執行完結尾輪后的狀態按先列后行輸出就是密文。
字節替換(ByteSub)是一個關於字節的非線性變換,具體的數學結構比較復雜,不展開描述。實現的時候,使用一個事先構造好的16×16的S盒來完成替換,S盒替換表如下:
這個S盒完成一個8比特輸入到8比特輸出的映射,比如說輸入的字節是\((CB)_16=(11001011)_2\),S盒中第C行第B列交叉處的值(1F)即為替換的輸出。
行移位變換(ShiftRow)是將狀態陣列的各行進行循環移位,不同狀態行的位移量不同,下圖展示的是128位版本的移位情況:
列混合變換(MixColumn)是將狀態陣列的每個列視為系數在\(GF(2^8)\)上、次數小於4的多項式,再與同一個固定的多項式c(x)進行模\(x^4+1\)乘法運算。AES設計者給出的\(c(x) ='03' x^3 +'01' x^2 + '01' x+'02'\),背后的數學原理略過,寫成矩陣形式如下:
上面已經是按模\(x^4+1\)計算后的結果,至於里面的乘法運算則還是之前數學基礎中定義的\(x^8+x^4+x^3+x+1\)。另外,所乘因子都是比較簡單的,乘\((01)_{16}\)還是不變,乘\((02)_{16}\)即前面介紹的x乘法,而\((03)_{16} \cdot s=(02)_{16} \cdot s \oplus s\)。
輪密鑰加變換(AddRoundKey)是輪密鑰陣列簡單地與狀態陣列做矩陣加法運算,定義在\(GF(2^8)\)上的加即為兩個字節逐比特異或。輪密鑰陣列由密鑰拓展算法得到。
密鑰拓展是AES密碼算法的一個重要組成部分,原理示意圖如下:
將密鑰矩陣每列四個字節看做一個元素,即上圖中的\(w_0\),\(w_1\),\(w_2\)和\(w_3\),對於輸出的子密鑰\(w_j (j∈[4,43])\),定義為:
至於函數g,會先把輸入的w循環左移8位,再對每個字節做S盒替換,最后與32比特的常量(RC[j/4], 0, 0, 0)進行異或。RC是一個一維數組:[0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36]。RC的值只需要有10個,而此處用了11個,實際上RC[0]在運算中沒有用到,增加是為了便於程序中用數組表示。由於j的最小取值是4,j/4的最小取值則是1,因此不會產生錯誤。
參考實現:python
參考資料: