Figure 16 加密 Demo 程序
因為加密和解密例程都需要知道用戶定義的密鑰長度,我把它當作一個類范圍的變量來聲明,像這樣:
private Aes.KeySize keysize;
注意種子密鑰並不是由用戶定義的。這個 demo 程序用一個“空密鑰”(null key)作為種子密鑰,通過為構造函數提供一個啞參數 new byte[16] 使得它全部由零字節組成。啞參數的長度是不相關的,因為種子密鑰還是要被初始化為零。空密鑰加密和解密是一個容易和有效的辦法來阻止外界對數據偶然的檢查。在System.Text中的 Encoding.Unicode.GetBytes和Encoding.Unicode.GetString 方法使得將一個.Net 字符串轉換成一個字節數組變得非常容易,反之亦然。
實現選擇
現在讓我們看看本文 AES 實現中出現的一些重要的變量,本文提供的代碼可能出現的擴展,以及針對 AES的密碼分析學攻擊。
和我曾經處理的任何代碼一樣,AES 算法也可以用其它可選的途徑來實現。為什麼這很重要呢?AES 被試圖廣泛應用於各種系統,從只有很少內存容量的智能卡(smart cards)到大型的多處理器主機系統。在許多情況下,性能是關鍵因素,並且有時內存或處理器資源是有限的。事實上,AES的每個例程都能針對非常昂貴的內存資源進行性能優化,反之亦然。比如,為替換表Sbox[] 分配 256 個值看起來好像很簡單直白。但是,這些值是基於GF(28) 理論的,它們都可以用編程方式來生成。逆向替換表和輪常數表也是如此。
可選實現另外一個有趣的可能性是 Cipher和InvCipher 方法所用的 GF(28) 乘法。我的實現代碼是一個被 0x02 乘的基本函數,而後是六個調用 gfmultby02的附加函數。另一個可能性應該是寫一個一般的乘法函數,並用它代替我目前實現的七個單獨函數。另一個極端是你可以用被 0x01, 0x02, 0x03, 0x09, 0x0b, 0x0d和0x0e 乘好的所有 256 個可能的字節值構成的一個完整乘積表。此外,實現 GF(28) 乘法另一途徑是通過在兩個 256 個字節的數組裡查找,通常稱為alog[]和log[],因為它們在GF(28)中基於某些類似對數的方法。
雖然這裡給出的 AES 類完全能用於加密任何形式的.Net數據,你可能考慮想用各種方法擴展它。首先,因為本文的重點在於清楚地解釋 AES,所有 錯誤檢查被剝離掉,以我的經驗,為某個象 AES 這樣的類添加合理數量的錯誤檢查將會產生三倍的代碼量膨脹。因為AES 使用了這麼多的數組,需要做很多索引 邊界檢查。例如,所給出的構造函數甚至都不檢查種子密鑰參數的長度。
你可能還考慮通過添加更多的特性來擴展 AES 類。最明顯的一個地方是添加加密和解密.Net基本數據類型的方法,比如:System.String和System.Int32。更加雄心勃勃的擴展可能會是實現一個 流數據加密類。
AES的安全性怎樣呢?這是一個很難回答的問題,但是一般多數人的意見是:它是目前可獲得的最安全的加密算法。AES 已被列為比任何現今其它加密算法更 安全的一種算法。在理論和實踐基礎上,AES 被認為是“安全的”,因為要破解它的話,唯一有效的方法是強行(brute-force)生成所有可能的密鑰。 如果密鑰長度為256 位,還沒有已知的攻擊可以在一個可接受的時間內破解 AES(即便在當今最快的系統上,它也要花費數年時間)。
注意針對 AES 密碼最可能成功的攻擊來自一個允許時間選擇攻擊的弱實現。攻擊者用不同的密鑰並精確地測量出加密例程所需的時間。如果加密例程被粗心編碼 ,因此執行時間便依賴於密鑰值,它就有可能推導出有關密鑰的信息。在AES中,這種事情最可能發生在MixColumns 例程中,因為有域乘。 針對這種攻擊的兩個安全措施是加入虛指令,以便所以所有乘法都需要相同數量的指令,或者將域乘實現為一個查詢表,就象我前面描述的那樣。
AES 有許多種可能的實現,尤其是是使用查詢表而不是計算。本文提供的 AES 基本類可以被用於加解密任何形式的.Net數據或 被擴展成一個具有更多功能的類。
結束語
新的 AES 將無疑成為加密所有形式電子信息的事實上的標准,取代 DES。AES 加密的數據在某種意義上是牢不可破的,因為沒有已知的密碼分析攻擊可以解密 AES 密文,除非強行遍歷搜索所有可能的 256 位密鑰。
我發現在Microsoft .Net Framework 上實現 AES 類的主要的障礙是官方文檔是以一個數學家的觀點,而不是以一個軟件開發者的觀點來寫的。尤其是該規范假定讀者十分熟悉 GF(28) 域,並省略了幾個正確實現 AES 所必需的關於GF(28) 乘法的關鍵事實。我在本文中試圖努力去掉 AES的神秘面紗,特別是圍繞在GF(28) 域乘法部分的。
以 .Net Framework 庫的形式從 Microsoft 以及第三方供應商處獲得對 AES的廣泛支持只是一個時間問題。然而,處於種種理由,讓本文代碼作為你的技能儲備仍然是有價值的。這個實現尤其簡單,並且是低資源開銷。另外,閱讀並理解源代碼將使你能定制 AES 類且更有效地使用它的任何實現。
在任何軟件設計過程中安全已不再是後顧之憂。AES 是一個重大進步,使用並理解它將大大增加軟件系統的可靠性和安全性。
本文配套源碼