1. 程式人生 > >crypto++ 中DES AES RC5 RC6 TEA XTEA XXTEA加密演算法效能比較

crypto++ 中DES AES RC5 RC6 TEA XTEA XXTEA加密演算法效能比較

加密是網際網路資料安全的保證,但是現在感覺多數網頁遊戲和手遊都已經拋棄了資料加密,幾乎都是直接明文傳送。不過現在遊戲爛大街,除非很牛的遊戲才會有人去破解,垃圾遊戲我想沒有那個蛋疼的會去破解。本著學習的精神下載了crypto++ 對常用的對稱加密演算法進行效能比較,由於遊戲資料包都比較小,所以測試中選擇的最大資料長度為200k,我想如果一個遊戲資料包超過200k那隻能是載入資源的時候了,其他時候沒有人受的了長時間的轉菊花。曾經在專案中有一次因為特殊原因弄了一個100k的資料包直接客戶端超時。下面的測試中應用了vs2102的debug和release,gcc4.8+O2優化,clang3.5 +O2優化。加密演算法後面帶_EX表示從crypto++中或者在網上搜索的加密演算法進行自己封裝的函式的效能測試,這樣可以減少函式呼叫,也利於以後在專案中使用,不用承受龐大的程式碼庫,模板等其他開銷。所有測試都是進行100次加密後計算的平均值,時間單位為微妙,如果為0表示平均之後時間不到1微妙,AES加密是應用了AES-NI指令,AES_EX測試的時間是應用了AES-NI指令的四路並行加密,具體演算法可以看crypto++實現。所有加密都使用ECB模式(沒有進行異或處理)。測試機子就是一臺普通筆記本,gcc和clang測試在ubuntu13.4虛擬機器上進行測試的。

測試結果如下:





總結:

從測試結果發現AES演算法在支援AES-NI指令並且使用四路並行加密是遊戲加密的首選,因為在各種情況下都是最好的,200k的資料不到1毫妙,這在高併發遊戲中是可以接收的加密演算法。如果不支援AES-NI指令則AES演算法效能會降低10倍左右,只進行了一次測試,具體數值需要做更多測試。如果不支援AES-NI指令則選擇XXTEA比較好,200k能夠在4毫秒以內還是可以接受的,並且一般來說遊戲中90%的協議在1k以內。以上測試只是進行簡單的比較,應用不同對加密效能和安全也不同。所以還是需要根據專案選擇合適的加密演算法。

番外:

在將crypto++中AES演算法提取出來自己封裝的時候AES-NI指令在linux中編譯報錯,報錯資訊很多,下面是開始的報錯資訊:

usr/lib/gcc/x86_64-linux-gnu/4.8/include/wmmintrin.h: In function ‘__m128i _mm_aesdec_si128(__m128i, __m128i)’:

/usr/lib/gcc/x86_64-linux-gnu/4.8/include/wmmintrin.h:45:70: error: ‘__builtin_ia32_aesdec128’ was not declared in this scope

這個報錯是GCC中的wmmintrin.h 標頭檔案需要一些預定巨集,也就是他會檢查cpu是否支援AES-NI指令 度娘根本找不到,谷歌這幾天ip都不能用了,最後只好看了下crypto++的makefile檔案找到了答案,在編譯選擇中加上-march=native 選擇,編譯器會自動檢查本機的cpu指令集,這樣就ok了。如果想編譯出來在其他主機上使用需要保證機子的cpu支援相同的指令集主要是AES-NI和SSE2,等指令。在自己提取AES演算法的時候圈金鑰需要限制16位元組對齊要不是在使用AES-NI指令的時候會crash,具體如下:

#if defined(CRYPTOPP_MSVC6PP_OR_LATER)
#define CRYPTOPP_ALIGN_DATA(x) __declspec(align(x))
#elif defined(__GNUC__)
#define CRYPTOPP_ALIGN_DATA(x) __attribute__((aligned(x)))
#else
#define CRYPTOPP_ALIGN_DATA(x)
#endif

CRYPTOPP_ALIGN_DATA(16) uint32_t pTabKey[60]={0};

pTabKey是用於加密的圈金鑰,這樣他的起始地址摸16會為0,這樣在使用_mm_aesimc_si128,_mm_aesenc_si128等這些指令的時候才不會又問題。如果要動態分配記憶體好像需要_mm_malloc函式,沒用進行測試。

在測試中發現AES加密中的Rijndael_Enc_AdvancedProcessBlocks這個函式加密後解密不出來,這個函式是應用SSE2指令集編寫的一個加密函式,裡面全是組合語言所以也就沒有去深入研究了,另外在使用AES-NI的加密使用小端進行加解密,而crypto++中AES普通加解密演算法使用的是大端進行加解密,所以crypto++庫中的AES-NI加密的資料不能用庫中的普通解密演算法解密,反之也不行。