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定义了如下数据结构:

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 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.算法简介

……

时间: 2024-10-20 19:16:23

AES加密算法C代码分析的相关文章

【Android开发经验】DES加密时代的终结者——AES加密算法

转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992 在前面的两篇文章中,我们介绍了DES算法,3DES算法以及他们的Android程序实现,并研究了如何才能实现不同平台下加密算法的一致性.不过话说起来,DES算法是在1976年被美国的国家标准局定为联邦资料的加密标准的,到现在已经接近40年了.我们都知道,在计算机的世界里有一个摩尔定律,就是每过18个月,计算机的晶体管的数量就会翻一番,对应的计算速度也会翻倍,虽然现在的发展速度有所放缓,但是每过三年左右,计

PHP android ios相互兼容的AES加密算法

APP项目用户密码传输一直没有用HTTPS,考虑到用户的隐私暂时先用AES对密码加密,以后也可以用于手机端与服务端加密交互. PHP的免费版phpAES项目,手机端解码各种不对. 好不容易找了PHP ANDROID IOS,相互加解密正常的AES加密算法代码. PHP的AES加密算法: [codesyntax lang=”php”] <?php class MCrypt { private $hex_iv = '00000000000000000000000000000000'; # conve

恶意代码分析实战

恶意代码分析实战(最权威的恶意代码分析指南,理论实践分析并重,业内人手一册的宝典) [美]Michael Sikorski(迈克尔.斯科尔斯基), Andrew Honig(安德鲁.哈尼克)著   <恶意代码分析实战>是一本内容全面的恶意代码分析技术指南,其内容兼顾理论,重在实践,从不同方面为读者讲解恶意代码分析的实用技术方法. <恶意代码分析实战>分为21章,覆盖恶意代码行为.恶意代码静态分析方法.恶意代码动态分析方法.恶意代码对抗与反对抗方法等,并包含了 shellcode分析

jsencrypt代码分析——openssl的rsa加密解密在js的实现

在js上做rsa,感觉jsencrypt这个是封装的比较好的,但用起来还是遇到了些坑,所以踩进代码里填填坑- 项目在这里 https://github.com/travist/jsencrypt [rsa算法] 首先科普一下rsa:公钥私钥成对,用其中一个加密只能用另一个解密,常用公钥加密私钥解密. 一开始看到斯坦佛那个库,原始的算法实现: 长度,建议至少1024.模数n(常取默认65537)两边都要用. 指数e,和n一起就是公钥.指数d,和n一起就是私钥.质数p和q用于生成密钥对,然后就丢弃不

jsencrypt代码分析

jsencrypt代码分析--openssl的rsa加密解密在js的实现 在js上做rsa,感觉jsencrypt这个是封装的比较好的,但用起来还是遇到了些坑,所以踩进代码里填填坑- 项目在这里 https://github.com/travist/jsencrypt [rsa算法] 首先科普一下rsa:公钥私钥成对,用其中一个加密只能用另一个解密,常用公钥加密私钥解密. 一开始看到斯坦佛那个库,原始的算法实现: 长度,建议至少1024.模数n(常取默认65537)两边都要用. 指数e,和n一起

iOS,Android,.NET通用AES加密算法

原文:iOS,Android,.NET通用AES加密算法 这两天为移动App开发API,结果实现加密验证时碰到一大坑.这里不得不吐槽下又臭又硬的iOS,Windows Server无法解密出正确的结果,Android则可以,后来使用了通用的AES256加密算法才最终搞定. 搞服务器端小伙伴没有接触过iOS,所以也没料到过这种情形.他使用了AES128 with IV的加密算法,Android端可以顺利通过加密验证. 但是iOS端使用AES128算法后出现问题,虽然可以在本地加密解密,但是无法被服

【转】PHP android ios相互兼容的AES加密算法

APP项目用户密码传输一直没有用HTTPS,考虑到用户的隐私暂时先用AES对密码加密,以后也可以用于手机端与服务端加密交互. PHP的免费版phpAES项目,手机端解码各种不对. 好不容易找了PHP ANDROID IOS,相互加解密正常的AES加密算法代码. PHP的AES加密算法: <?php class MCrypt { private $hex_iv = '00000000000000000000000000000000'; # converted JAVA byte code in t

Qt使用AES加密算法对字符串进行加密

因工作需要,需要对字符串进行加密处理,在网上找了很长时间,终于找到了一个可以使用的aes加密算法.其源代码采用c++编写而成,但其头文件引用windows.h,经过修改部分代码,将#include<windows.h>去掉,这样可是使用与多个编译器.下面的代码中列出了测试用的代码(中文出现乱码现象): 点击(此处)折叠或打开 int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); TAesClass *aes = n

AES 加密算法的原理详解

AES 加密算法的原理详解 本教程摘选自 https://blog.csdn.net/qq_28205153/article/details/55798628 的原理部分. AES简介 高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的).对称加密算法也就是加密和解密用相同的密钥,具体的加密流程如下图: 下面简单介绍下各个部分的作用与意义: 明文P 没有经过加密的数据. 密钥K 用来加密明文的密码,在对称