AES加密算法C代碼分析

0.引言算法

對於加密算法的軟件實現,一般已經有不少的成熟的庫可供選擇,只須要根據本身的要求進行選擇便可相應的庫便可(有的可能須要進行些許修改)。這裏選擇的是C語言實現的一個開源密碼庫mbedTLS,mbedTLS由XySSL發展而來,後改成PolarSSL,PolarSSL被ARM公司收購後改爲了mbedTLS,主要用於物聯網等安全嵌入式領域。mbedTLS實現了常見的分組加密算法、hash算法、RSA以及ECC公鑰密碼體制,一個適用於嵌入式的SSL協議以及X509證書等,基本可以知足大部分的嵌入式安全應用。安全

1.AES加密算法代碼分析數據結構

這裏再也不詳細的介紹AES的數學原理以及設計思路等,只是結合軟件進行代碼分析,關於AES的官方文檔能夠在NIST網站上下載獲得。函數

1)數據結構網站

數據結構與算法密切相關,一般分組加密算法定義的數據結構都較爲相似,mbedTLS的AES定義了以下數據結構:ui

typedef struct
{
    int nr;                     /*!<  number of rounds  */
    uint32_t *rk;               /*!<  AES round keys    */
    uint32_t buf[68];           /*!<  unaligned data    */
}
mbedtls_aes_context;

2)算法主體加密

分組加密算法的軟件實現一般會採用「查找表」的方式來提升算法的運算速度,經過表格或者預計算表格直接查表獲得對應的算法運算結果。spa

對算法的分析僅僅以加密算法爲例,解密算法的過程基本相似,只是前向表格改成逆向表格而已。設計

下面先給出代碼再進行分析:code

 1 void mbedtls_aes_encrypt( mbedtls_aes_context *ctx,
 2                           const unsigned char input[16],
 3                           unsigned char output[16] )
 4 {
 5     int i;
 6     uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
 7 
 8     RK = ctx->rk;
 9 
10     GET_UINT32_LE( X0, input,  0 ); X0 ^= *RK++;
11     GET_UINT32_LE( X1, input,  4 ); X1 ^= *RK++;
12     GET_UINT32_LE( X2, input,  8 ); X2 ^= *RK++;
13     GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++;
14 
15     for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- )
16     {
17         AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
18         AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
19     }
20 
21     AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
22 
23     X0 = *RK++ ^ \
24             ( (uint32_t) FSb[ ( Y0       ) & 0xFF ]       ) ^
25             ( (uint32_t) FSb[ ( Y1 >>  8 ) & 0xFF ] <<  8 ) ^
26             ( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
27             ( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
28 
29     X1 = *RK++ ^ \
30             ( (uint32_t) FSb[ ( Y1       ) & 0xFF ]       ) ^
31             ( (uint32_t) FSb[ ( Y2 >>  8 ) & 0xFF ] <<  8 ) ^
32             ( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
33             ( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
34 
35     X2 = *RK++ ^ \
36             ( (uint32_t) FSb[ ( Y2       ) & 0xFF ]       ) ^
37             ( (uint32_t) FSb[ ( Y3 >>  8 ) & 0xFF ] <<  8 ) ^
38             ( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
39             ( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
40 
41     X3 = *RK++ ^ \
42             ( (uint32_t) FSb[ ( Y3       ) & 0xFF ]       ) ^
43             ( (uint32_t) FSb[ ( Y0 >>  8 ) & 0xFF ] <<  8 ) ^
44             ( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
45             ( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
46 
47     PUT_UINT32_LE( X0, output,  0 );
48     PUT_UINT32_LE( X1, output,  4 );
49     PUT_UINT32_LE( X2, output,  8 );
50     PUT_UINT32_LE( X3, output, 12 );
51 }

分析能夠獲得算法的過程爲:

輪密鑰加->N-1輪輪變換->末輪變換

其中末輪變換隻有:字節置換(subbyte)/行移位(shiftrow)/輪密鑰加(addroundkey)

中間的輪變換則爲:字節置換(subbyte)/行移位(shiftrow)/列混合(mixcol)/輪密鑰加(addroundkey)

上述代碼中,RK爲輪密鑰,FSb爲S盒(Subbyte)的查找表,FTx則包括字節置換與列混合兩個過程,由於行移位爲線性變換,其運算過程能夠和列混合進行交換。

AES_ROUND由宏定義獲得,代碼以下:

 1 #define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)     \
 2 {                                               \
 3     X0 = *RK++ ^ FT0[ ( Y0       ) & 0xFF ] ^   \
 4                  FT1[ ( Y1 >>  8 ) & 0xFF ] ^   \
 5                  FT2[ ( Y2 >> 16 ) & 0xFF ] ^   \
 6                  FT3[ ( Y3 >> 24 ) & 0xFF ];    \
 7                                                 \
 8     X1 = *RK++ ^ FT0[ ( Y1       ) & 0xFF ] ^   \
 9                  FT1[ ( Y2 >>  8 ) & 0xFF ] ^   \
10                  FT2[ ( Y3 >> 16 ) & 0xFF ] ^   \
11                  FT3[ ( Y0 >> 24 ) & 0xFF ];    \
12                                                 \
13     X2 = *RK++ ^ FT0[ ( Y2       ) & 0xFF ] ^   \
14                  FT1[ ( Y3 >>  8 ) & 0xFF ] ^   \
15                  FT2[ ( Y0 >> 16 ) & 0xFF ] ^   \
16                  FT3[ ( Y1 >> 24 ) & 0xFF ];    \
17                                                 \
18     X3 = *RK++ ^ FT0[ ( Y3       ) & 0xFF ] ^   \
19                  FT1[ ( Y0 >>  8 ) & 0xFF ] ^   \
20                  FT2[ ( Y1 >> 16 ) & 0xFF ] ^   \
21                  FT3[ ( Y2 >> 24 ) & 0xFF ];    \
22 }

mbedTLS給出了兩種實現,1.ROM_TABLE的方式,全部表格直接給出,再也不一一列出各類表格;2.表格預計算的方式,因爲AES的設計是基於有限域的,表格預計算須要一些有限域的輔助函數,整個預計算的過程以下:

 1 #define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 )
 2 #define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
 3 #define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 )
 4 
 5 static int aes_init_done = 0;
 6 
 7 static void aes_gen_tables( void )
 8 {
 9     int i, x, y, z;
10     int pow[256];
11     int log[256];
12 
13     /*
14      * compute pow and log tables over GF(2^8)
15      */
16     for( i = 0, x = 1; i < 256; i++ )
17     {
18         pow[i] = x;
19         log[x] = i;
20         x = ( x ^ XTIME( x ) ) & 0xFF;
21     }
22 
23     /*
24      * calculate the round constants
25      */
26     for( i = 0, x = 1; i < 10; i++ )
27     {
28         RCON[i] = (uint32_t) x;
29         x = XTIME( x ) & 0xFF;
30     }
31 
32     /*
33      * generate the forward and reverse S-boxes
34      */
35     FSb[0x00] = 0x63;
36     RSb[0x63] = 0x00;
37 
38     for( i = 1; i < 256; i++ )
39     {
40         x = pow[255 - log[i]];
41 
42         y  = x; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
43         x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
44         x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
45         x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
46         x ^= y ^ 0x63;
47 
48         FSb[i] = (unsigned char) x;
49         RSb[x] = (unsigned char) i;
50     }
51 
52     /*
53      * generate the forward and reverse tables
54      */
55     for( i = 0; i < 256; i++ )
56     {
57         x = FSb[i];
58         y = XTIME( x ) & 0xFF;
59         z =  ( y ^ x ) & 0xFF;
60 
61         FT0[i] = ( (uint32_t) y       ) ^
62                  ( (uint32_t) x <<  8 ) ^
63                  ( (uint32_t) x << 16 ) ^
64                  ( (uint32_t) z << 24 );
65 
66         FT1[i] = ROTL8( FT0[i] );
67         FT2[i] = ROTL8( FT1[i] );
68         FT3[i] = ROTL8( FT2[i] );
69 
70         x = RSb[i];
71 
72         RT0[i] = ( (uint32_t) MUL( 0x0E, x )       ) ^
73                  ( (uint32_t) MUL( 0x09, x ) <<  8 ) ^
74                  ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^
75                  ( (uint32_t) MUL( 0x0B, x ) << 24 );
76 
77         RT1[i] = ROTL8( RT0[i] );
78         RT2[i] = ROTL8( RT1[i] );
79         RT3[i] = ROTL8( RT2[i] );
80     }
81 }

在有限域運算中,使用了對數表的方式來實現有限域的乘法操做,這是AES設計者在提交算法是所提供的一種計算方式。

38~50行代碼進行有限域求逆算法(使用對數表),再進行仿射變換,求得S盒,同時能夠獲得逆向S盒。AES的S盒設計爲(A*x-1+b),A爲2進制矩陣,b爲2進制列向量(0x63)。

再計算FTx,FTx的計算須要有限域乘法操做,其乘法爲固定乘法操做,主要有x2與x3,(逆變換乘數爲0x0e,0x09,0x0d,0x0b)。其中有限域的乘法運算也是基於對數表完成的。

2.算法簡介

……

相關文章
相關標籤/搜索