AES加密算法C代码分析
来源:互联网 发布:windows luajit 安装 编辑:程序博客网 时间:2024/04/30 00:15
对于加密算法的软件实现,通常已经有很多的成熟的库可供选择,只需要根据自己的要求进行选择即可相应的库即可(有的可能需要进行些许修改)。这里选择的是C语言实现的一个开源密码库mbedTLS,mbedTLS由XySSL发展而来,后改为PolarSSL,PolarSSL被ARM公司收购后改成了mbedTLS,主要用于物联网等安全嵌入式领域。mbedTLS实现了常见的分组加密算法、hash算法、RSA以及ECC公钥密码体制,一个适用于嵌入式的SSL协议以及X509证书等,基本能够满足大部分的嵌入式安全应用。
1.AES加密算法代码分析
这里不再详细的介绍AES的数学原理以及设计思路等,只是结合软件进行代码分析,关于AES的官方文档可以在NIST网站上下载得到。
1)数据结构
数据结构与算法密切相关,通常分组加密算法定义的数据结构都较为类似,mbedTLS的AES定义了如下数据结构:
typedef struct{ int nr; /*!< number of rounds */ uint32_t *rk; /*!< AES round keys */ uint32_t buf[68]; /*!< unaligned data */}mbedtls_aes_context;
2)算法主体
分组加密算法的软件实现通常会采用“查找表”的方式来提高算法的运算速度,通过表格或者预计算表格直接查表得到对应的算法运算结果。
对算法的分析仅仅以加密算法为例,解密算法的过程基本类似,只是前向表格改为逆向表格而已。
下面先给出代码再进行分析:
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 constants25 */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-boxes34 */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 tables54 */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.算法简介
……
- AES加密算法C代码分析
- objective-c加密算法AES
- AES加密算法(C++)
- JAVA实现AES加密算法代码
- aes加密算法java代码实现
- JAVA AES加密算法实现代码
- AES加密算法源代码(c语言版)
- 基于c语言aes加密算法
- AES加密算法(c语言)
- openssl AES 加密算法及代码实例
- openssl AES 加密算法及代码实例
- AES 加密算法的 C 语言实现
- AES 加密算法的 C 语言实现
- C# Andriod AES 加密算法
- AES加密算法
- AES加密算法
- AES加密算法
- AES加密算法
- 常见的传输码型
- 常见的串行通信协议
- VCS仿真器加密代码方法
- verilog PLI简介
- 超酷手机端HTML5电子请柬在线免费制作与分享
- AES加密算法C代码分析
- 国密杂凑算法SM3
- java 多态
- FPGA约束设置
- 科学论文写作工具TEX/LaTEX/CTEX
- 学习使用LATEX排版
- hadoop2.6.2高可用配置
- 最大岛屿 第八届
- HTML的几个标签简单记录