一、头文件, B0 N+ ^0 A+ W) J/ i
6 u' P1 |3 m0 Q ?7 a! w: q* u9 G
- #ifndef _AES_H: [' u4 _6 j8 p
- #define _AES_H) T4 B9 r' h4 z
: o# a+ E9 d4 X" U" D
+ Z, J: X8 k C: N y4 q/ T1 p, J( o. ?- // 以bit为单位的密钥长度,只能为 128,192 和 256 三种
- L) h* v0 {! S7 g3 p. r - #define AES_KEY_LENGTH 128
7 R f* M5 v) F& ^- X# w- e - - N0 F- v/ y) T
- // 加解密模式9 U& q& h: q4 N1 m {/ j5 g
- #define AES_MODE_ECB 0 // 电子密码本模式(一般模式)
, ]/ L$ S8 P6 w, r1 i - #define AES_MODE_CBC 1 // 密码分组链接模式
# M" n6 d2 m, Y; q5 v - #define AES_MODE AES_MODE_CBC
8 X: o, M7 d$ m n% f
( B0 h; h7 t( ?: P- % `/ j9 l8 j1 x! J s/ L/ A
- ///; e& ?' J2 _! r e/ O ?
- // 函数名: aes_init' S/ B3 S9 h+ @
- // 描述: 初始化,在此执行扩展密钥操作。
/ q/ p1 y% @& S& A - // 输入参数: pKey -- 原始密钥,其长度必须为 AES_KEY_LENGTH/8 字节。
* s3 s2 i/ ^* Q, r, I - // 输出参数: 无。
; |7 T1 h. j( k( G2 G# I - // 返回值: 无。
9 ]* j U7 E& W7 H7 I* ^7 g - ///0 F/ f& E, T+ M
- void aes_init(const void *pKey);
, L, ^+ g# z2 H8 {0 r# C$ f - - Q' U4 z$ t5 V$ @$ o
- //1 |& _7 ?- W! l5 D' p" C
- // 函数名: aes_encrypt
. s) k7 ]7 a) u9 U - // 描述: 加密数据& p6 B& U' r; j- n: s9 g$ v# S' M
- // 输入参数: pPlainText -- 明文,即需加密的数据,其长度为nDataLen字节。& {- d" M: y; ^
- // nDataLen -- 数据长度,以字节为单位,必须为AES_KEY_LENGTH/8的整倍数。
W7 i* M+ F, h% r4 D - // pIV -- 初始化向量,如果使用ECB模式,可设为NULL。$ ?$ m. V8 Q, h/ C! ~
- // 输出参数: pCipherText -- 密文,即由明文加密后的数据,可以与pPlainText相同。
5 o( o& Z t \% Q/ s* L - // 返回值: 无。
- J4 I; E" h+ X. y) j" a- Z - //: R1 |+ _$ J3 L S; u7 w. x: J/ `2 n/ i
- void aes_encrypt(const unsigned char *pPlainText, unsigned char *pCipherText,
8 W; P+ s/ R$ D$ P - unsigned int nDataLen, const unsigned char *pIV);
0 n8 m7 }6 G5 M" G
- ?- g" r4 Q& D9 l' W- // r1 M f* d" U6 k2 q0 {4 ~8 J9 f
- // 函数名: aes_decrypt) N( C; I4 f) [% r
- // 描述: 解密数据
& s! c% `, Y- C# M - // 输入参数: pCipherText -- 密文,即需解密的数据,其长度为nDataLen字节。% n& T7 `* X/ D# k9 x3 n% l
- // nDataLen -- 数据长度,以字节为单位,必须为AES_KEY_LENGTH/8的整倍数。" h( m& r$ y4 q3 R3 n; N
- // pIV -- 初始化向量,如果使用ECB模式,可设为NULL。
* a- A9 O0 d& O4 D - // 输出参数: pPlainText -- 明文,即由密文解密后的数据,可以与pCipherText相同。6 x' y1 s! o6 G5 U% Q
- // 返回值: 无。" B) T- ^: g0 b' e0 [! {
- //' N( i! L/ I* e. D+ R6 u/ `
- void aes_decrypt( const unsigned char *pCipherText,unsigned char *pPlainText, * v3 Y0 y; H: d2 d, N' @2 G
- unsigned int nDataLen, const unsigned char *pIV);
9 T6 P% a# z% a$ R/ |6 F: F* X - #endif /* _AES_H */
复制代码 3 I+ e5 e/ |3 h. v
二、源文件
) u7 \4 g: s- z) I1 x* v
: ^, l* ]/ |' }- #include "aes.h": F$ ^( Y: l% t& u0 @7 n9 g
- #include "string.h"% s, N1 n3 `* J7 k6 L) A1 T
9 X# X+ [5 J/ Y$ L V5 U- 1 f' t+ f4 Z0 p7 [6 w9 k- i' A
- // 为了能针对C51进行优化,并且又使代码可用于ARM和PC等环境,4 V2 k9 J, c8 B/ g# h- }" s' ~
- // 在非C51环境(没有定义__C51__)下需要把C51特定的关键字定义为空
& A5 J( E3 Q( v" j9 ^ - #ifndef __C51__1 O9 n* f% z8 @ _4 s+ \4 T
- #define code8 H- T9 L) C% G' v
- #define data5 q0 F8 T0 c- z
- #define idata
7 P/ e; x& B* o% n$ ~+ x7 z - #define xdata$ w- m. _" P& C( _
- #define pdata
+ ]4 }2 b' m7 e1 h6 \ - typedef unsigned char BOOL;: O6 w n( c5 U/ A8 y- V G
- #else) Z1 @8 Y& L- v6 x9 P( N$ m: L
- typedef bit BOOL;
0 g' {) z5 |6 N- ]( Y4 Q - #endif6 B" Z' q! h+ ], ]5 h& r( e
: _4 l# g* }5 Q- #define Nk (AES_KEY_LENGTH / 32) // 以“字”(4字节)为单位的密钥长度
6 J5 {- o5 T. f - #define Nb 4 // 以“字”(4字节)为单位的加解密数据块大小,固定为4
. G/ x6 `* _5 L- r: Q6 Z8 C8 z
# {+ O- X! n1 X W- S/ O0 P0 S! g- // Nr:加密的轮数
, e# P( H: q; f8 Z1 W& A/ n - #if AES_KEY_LENGTH == 128. h2 `2 `( e- e
- #define Nr 10# S& ~0 v* T$ A1 T' S7 c1 t' }
- #elif AES_KEY_LENGTH == 192
3 _" b' k" i5 G0 ^1 E - #define Nr 12. p. i) B- j, S3 L% c2 P; t! M
- #elif AES_KEY_LENGTH == 256
8 @# M# t" S8 T* p# |+ G9 A% d - #define Nr 14
" h; @3 S- x0 { - #else. w( z) l3 w# }* ~
- #error AES_KEY_LENGTH must be 128, 192 or 256 BOOLs!
0 k' W8 H6 _* }4 D5 `, N: w% T. q - #endif
- Y" d" Q5 |( E. P5 ~. C - # X6 X% X7 x& m7 G, L8 j$ `, P
- // GF(28) 多项式$ n# n. e' s& e9 L/ Q
- #define BPOLY 0x1B // Lower 8 BOOLs of (x^8 + x^4 + x^3 + x + 1), ie. (x^4 + x^3 + x + 1).% b2 H, i8 f" b5 G
- . Z0 E8 t$ g5 n3 b9 F: `
- /*****************************************************************************
9 P' G0 c& E9 V* N9 U - * Typedef Enum 枚举定义
W5 j+ |3 X* A7 S \6 e# P0 e - *****************************************************************************/( U* m, G) w. J6 ^; t
6 C6 S* ]% o( P6 X- u2 ]- /*****************************************************************************
6 u K( M' }- H9 m k0 i, u& F# M - * Struct 数据结构定义
d* j) d9 m' m' A+ k# U4 V - ******************************************************************************/& K9 `/ o6 i+ ?3 V% E/ q
- 7 A& v0 s3 O7 z# L8 F1 h4 t* b& Y
; ^5 |# L1 m& S- /*****************************************************************************7 [& K) }" S: B4 p
- * Local variable 局部变量
% c! E9 w& k( E& | - *****************************************************************************/+ w ?6 b2 Q$ A" ~0 n/ O+ T
D# T E# b- X( m- // AES子密钥表,当密钥长度为128位时,占用176字节空间
4 T% B$ N- z: q6 @/ A+ m - static xdata unsigned char g_roundKeyTable[4*Nb*(Nr+1)];
+ G! f8 K/ ^7 a: a) _2 l: f - # I- k9 N. G0 n9 Y
- // 加密用的SBox7 J) g; _0 c6 e1 O
- static code const unsigned char sBox[256] = 3 H' L/ l9 y, q* i6 ^$ X7 Q
- {! x0 _! q, Y$ ]3 F' B
- 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,9 j( g" b1 L" f0 F
- 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
" b. k( ~3 y E, o& k" ? - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,. T' E1 n4 Q! k2 a
- 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+ x- Y( G9 |% [* i - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, x+ L" _; K! O
- 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,8 _, S) k9 e" `- n' v
- 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
$ c- H( {1 d) y# o: Y$ A - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
$ `$ r) w% S3 c; _( j! C% } - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
, j5 E0 X7 t( E - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0 d* @9 |, U% n& C# O& p - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,# U/ D" d% t, S% Q6 f
- 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,+ o2 b5 x; j9 M4 M8 \, W
- 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0**, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,$ P J1 M6 E _! ^, @
- 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,0 ?; D- l' V8 W. m" f
- 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,6 u: U2 A; u4 V. i0 g6 x2 q
- 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 4 n7 y$ E3 |7 R* D1 u3 L! r
- };& \8 `3 u8 n6 ^
- + f' b: U: _; Z9 W, b
- // 解密用的SBox
I2 J8 W! v \8 y* }/ @+ {2 _ - static code const unsigned char invSBox[256] = - N8 @) n6 r' r
- {
( {! a2 [- O; W3 Y0 C - 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
6 x, n& G3 O. `! z& M1 l - 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,2 o, g3 {8 q& H
- 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
- Z& r* D8 c1 I5 W+ L( W - 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
/ H6 n$ P, }* L - 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,0 ~: z5 `; A* l* }
- 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
( \( Y7 X$ U1 ?+ g" n% E" \7 J - 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
, {4 K) ^! F9 b7 X - 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,. R: q8 n; G. T8 d9 `$ w
- 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,/ N" b4 O) x; F" t2 K( U8 y) y
- 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,5 k D2 V! n8 H* h/ M
- 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
# t, V. h% u9 a- n/ g8 x8 e - 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
+ E4 T" V. M( K: l6 ^ - 0x1f, 0**, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
8 Y6 m# l# o0 Q4 o" W - 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef," y1 C: L0 M! K7 V+ X# n
- 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
: V0 l2 d- C# B/ b! T* |- d) A - 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
3 U8 W3 q2 n2 b) k7 Q( |* M4 m - };
2 H/ l5 ~& D/ I% j7 _ - : t" d. T, v! Z
- % M% y1 l" Z" l" p7 x
- ///
4 _! Z) w6 G% W- x, h( A - // 函数名: rotation_word8 K0 Z- P6 d! D" i
- // 描述: 对一个“字”数据进行循环右移。
# k& m2 h8 J* t! z- g t- q, f - // 输入参数: pWord -- 要右移的4字节数据。% x9 U# v x# i+ n: i8 v. D
- // 输出参数: pWord -- 右移后的4字节数据。
- w$ \6 O5 n* Y) a1 ]" D - // 返回值: 无。/ p. f1 P9 ?6 c- v0 y+ d1 s# S
- ///
1 p- |& X/ P, a7 X) u1 q - static void rotation_word(unsigned char *pWord), s: N$ z: b& ?- U5 Y
- {) y" Q) ~) }3 v! x2 d3 E
- unsigned char temp = pWord[0];
8 L/ ^1 _3 K1 x- O - pWord[0] = pWord[1];
; _( \& y, U* N7 m* d2 e - pWord[1] = pWord[2];4 z: x7 O' P' w1 b$ [
- pWord[2] = pWord[3];. M g6 `! {7 w' f6 S& @8 G
- pWord[3] = temp;
0 ~- j T; O6 D: O. S# @ - }# d" i' {1 p# X ]
- & f3 ?0 g# b$ f5 @2 u% t
- ///& }9 }+ u0 T* k, @1 _
- // 函数名: xor_bytes( u- K8 C. n; Q6 {: B
- // 描述: 批量异或两组数据。
2 i/ E; K: C ~' h: i5 R; o6 A - // 输入参数: pData1 -- 要异或的第一组数据。+ R) |; G$ {! J) `% K/ A v" C
- // pData1 -- 要异或的第二组数据。 Y' h" y9 f1 k4 u/ T: j
- // nCount -- 要异或的数据长度。; e8 W$ i( E/ y$ ] A6 J% Q
- // 输出参数: pData1 -- 异或后的结果。* W3 B5 @" L, R, @" C% |! X, S
- // 返回值: 无。+ U! I0 _: u/ h( L' w
- ///& c9 B+ P( {9 F' K( p& n
- static void xor_bytes(unsigned char *pData1, const unsigned char *pData2, unsigned char nCount)
I, I$ Z$ ?5 ~+ P) Z - {9 y" z l: B& p6 j/ U. U8 B1 Y; o
- unsigned char i;
: i8 `8 S" K. [- ` -
. n6 B% k6 q+ [6 n: j - for (i = 0; i < nCount; i++)
$ `5 a6 K8 W1 s/ q: z! U# R& V - {2 j& g5 f/ B$ I4 M
- pData1<i> ^= pData2<i>;* M3 L' m5 `/ N9 F% M0 R( o4 k
- }3 E+ u, w& j N: Y1 [6 u* y* @! B: Y
- }$ v( _' ? v% d6 B- F+ k) P
7 M4 y: p; Z5 Y, j. K- ///# G6 k* l5 E, _% \$ D
- // 函数名: AddRoundKey
2 }, }1 O) B5 M) U$ p - // 描述: 把 中间状态数据 加上(异或)子密钥,数据长度为16字节。; {9 d* o8 T) v$ i( b7 p
- // 输入参数: pState -- 状态数据。
7 D0 z7 g+ G8 m$ | - // pRoundKey -- 子密钥数据。, t. [/ g5 F# I" [! M( D
- // 输出参数: pState -- 加上子密钥后的状态数据。
7 G* t6 d$ _5 c/ M3 }( ~3 T3 F - // 返回值: 无。$ K9 _5 l- d2 F) ~ q
- ///3 X# w, q$ c7 K
- // static void AddRoundKey(unsigned char *pState, const unsigned char *pRoundKey)" z1 q/ W6 V5 P& ~) R. \7 L( N
- // {0 A7 n9 W9 Z- d; A4 e% {6 h
- // xor_bytes(pState, pRoundKey, 4*Nb);+ i% J, V# \: Z
- // }. Y; C* J3 i% W! P' |
- 1 i o. C$ ?1 @$ f, _9 K
- // AddRoundKey的宏形式,比函数形式可以节省4字节的data数据
1 G, ^, a' X3 w- c* | - #define AddRoundKey(pState, pRoundKey) \
4 {% q! z6 I$ ^6 j" e. p% m9 I3 \ - xor_bytes((pState), (pRoundKey), 4*Nb)
! z& Q! H& t) x# t8 @( L0 Z) ?, N
# M- n- O: [& t( B7 }0 D
- J* R# T7 [# T# }! c. t7 F- ///
; O' J U1 Y4 @0 @, p1 j% Y0 Y* o - // 函数名: sub_bytes
`# u9 e3 w4 F! z) ] { - // 描述: 通过S盒子置换状态数据。. H) S, j& r3 U% B1 ~( s
- // 输入参数: pState -- 状态数据。
2 Q M2 b4 Q, c/ F; G' ] - // nCount -- 状态数据长度。2 W' I2 _0 w, `
- // bInvert -- 是否使用反向S盒子(解密时使用)。; b2 d$ ^, g" `! g& Z
- // 输出参数: pState -- 置换后的状态数据。
1 M8 ^" R# i6 Z% ^3 b% N. }* i - // 返回值: 无。" |( R; y% G( X3 O0 s4 F. j4 r
- ///% ]+ G- w5 Z9 H6 Z/ A
- static void sub_bytes(unsigned char *pState, unsigned char nCount, BOOL bInvert)
! t/ x7 ~% y2 M* C' n - {) {6 `1 U0 s) [1 ]7 B+ l
- unsigned char i;
{; o# N! z; t V1 a - const unsigned char code *pSBox = bInvert ? invSBox : sBox;
( c! i/ q R1 _( u -
+ l5 l2 r" j, B! C" }. i+ @+ | - for (i = 0; i < nCount; i++)
2 F, L: t+ {# w: S5 r - {1 o% p! u0 B8 @
- pState<i> = pSBox[pState<i>];
) L# A( ]4 p% u8 U - }/ j; t& d( e: W* W/ q& m
- }
6 \, _) M |# s0 M1 g8 x; U+ Z" q
6 {/ K; k! C/ E/ Q8 N; f- ///4 d2 {/ s( E8 \8 N; v# Q$ U I" A
- // 函数名: shift_rows# X6 x6 J) a# g, h) d
- // 描述: 把状态数据移行。: ]2 k/ _; `* q& u
- // 输入参数: pState -- 状态数据。
2 l5 y7 }( e. f& _& `/ C$ E! t - // bInvert -- 是否反向移行(解密时使用)。
_, O1 T: C+ B8 t3 Y! H) t" ? - // 输出参数: pState -- 移行后的状态数据。
9 J2 O% z& Y6 O5 }8 @* P! ~) ? - // 返回值: 无。
; S9 }7 o( i( p9 I- T$ y3 \* B - ///
! K1 I9 h4 j: p- r0 Y% y4 N - static void shift_rows(unsigned char *pState, BOOL bInvert)8 w* l a, f" Y, ^+ [: Z
- {# U7 _: x2 Q9 q; _
- // 注意:状态数据以列形式存放!
" r2 c5 Z% \/ @5 u
* E5 U% ~: I+ `4 d- unsigned char r; // row, 行 g, Z- Z V" A6 c0 ?1 ]
- unsigned char c; // column,列6 F0 K2 M( y+ U- o7 ~, G* u5 d+ E
- unsigned char temp;
1 H8 H7 s2 v! x8 z9 y- M# A& C7 t - unsigned char rowData[4];
/ i: U$ H: m$ T e* z2 y2 N Y - ; T' m: \1 P, T! {! o, O
- for (r = 1; r < 4; r++)
3 x4 H- R* c5 U; E - {
+ h Z# O9 ^5 P" O) l1 \ - // 备份一行数据
; _* a1 ~8 _$ F* I7 J1 u - for (c = 0; c < 4; c++)5 a2 O9 J9 g W6 D
- {- m5 B3 n) H n( A* y9 E5 ~
- rowData[c] = pState[r + 4*c];
% [9 x) y7 e, G5 b - }
+ {" L7 k6 Y8 x0 l- a5 u% ^ -
3 e) x; ]& M6 ` - temp = bInvert ? (4 - r) : r; s7 v, M l: V' p
- for (c = 0; c < 4; c++)! M7 ~( ]" C3 G T
- {
6 I$ H$ Q- j$ r( c( d4 Z+ d - pState[r + 4*c] = rowData[(c + temp) % 4];
8 R5 ~. p" S) h* y r1 [ - }
; | Z- M2 H! g - }1 v, l1 g; S. `' } c$ q
- }
( G& v. w& S; ~. S+ n" I - ( |8 l4 I9 g t2 b- [; t
- ///
* ^2 C7 ?4 j$ q1 P w0 X4 S - // 函数名: gf_mult_by02( A6 u, d7 h; i+ c2 z
- // 描述: 在GF(28)域的 乘2 运算。4 U* d5 @/ E, ^4 w6 k d' d/ _7 p' G
- // 输入参数: num -- 乘数。% l8 D6 ?* u8 Q4 I5 |
- // 输出参数: 无。. T' M- |" h8 k4 n4 ]" _& L
- // 返回值: num乘以2的结果。
1 R) d1 w; i1 E& _0 X - ///
) Y: z8 A6 p5 Z1 n1 }. T - static unsigned char gf_mult_by02(unsigned char num)( m$ U% q9 @2 _$ o
- {
2 K9 a- n2 [( h& d1 ] - if ((num & 0x80) == 0): ]9 ? N# q; k7 r: G& Y i. @
- {
( ~4 f/ {9 M1 t) v/ [ - num = num << 1;, {" [. S1 X R$ u0 ]( V
- }* l2 w. j Q" V
- else
3 Y) G* J+ K. ^- J5 Y$ U2 I$ P7 g - {
C9 D! `( E5 { Q# j" R- C - num = (num << 1) ^ BPOLY;
5 D0 o% k- S: s- i7 d. I - }" b" R m$ Z+ n
- * j( S* P2 D" o p
- return num; J# p( V3 P$ A: \
- }& K+ H* s9 `3 n
- 8 O4 k" Z: p+ ]% h- X
- ///
, O3 J; v& q, } - // 函数名: mix_columns, j. e2 U( k4 ]7 j- U
- // 描述: 混合状态各列数据。
# l" ` U6 R/ T8 P" _4 H: ] - // 输入参数: pState -- 状态数据。
) o. r% I% ~4 f4 n+ E& l - // bInvert -- 是否反向混合(解密时使用)。: I8 r( \; L: o
- // 输出参数: pState -- 混合列后的状态数据。7 C% O# p3 j# g M1 v
- // 返回值: 无。
6 u/ Y7 O, J# F+ M; [5 Z - ///, L9 @' B3 J! y' R# g
- static void mix_columns(unsigned char *pState, BOOL bInvert)
5 e1 x8 S ~3 F4 A; S3 P2 A - {
$ e* G4 l" K" K7 v. J8 p - unsigned char i;
5 Y( Q7 D' i- u o3 i) t" A! Q9 a - unsigned char temp;6 P' ]8 ]. b) a$ I
- unsigned char a0Pa2_M4; // 4(a0 + a2)2 m" t4 G; p6 E) q9 x
- unsigned char a1Pa3_M4; // 4(a1 + a3)0 n b% k$ E5 a; d
- unsigned char result[4];
- g. v$ d% ~) k7 @0 x1 o
; b, d" Q# v( u! c! {# r7 t) ?/ Y- for (i = 0; i < 4; i++, pState += 4)- T- ?6 B3 t% F/ K2 l- @9 n% {& Q
- {
0 k: I( }+ H" h& Y( R. {4 ` - // b0 = 2a0 + 3a1 + a2 + a3
* K6 I6 i$ j" x' _8 Y - // = (a0 + a1 + a2 + a3) + 2(a0 + a1) + a0! a( H8 L3 ?# R( x' ?
- 7 }8 ~# w4 d: K
- temp = pState[0] ^ pState[1] ^ pState[2] ^ pState[3];
/ E% Y$ a" e+ P9 | - result[0] = temp ^ pState[0] ^ gf_mult_by02((unsigned char) (pState[0] ^ pState[1]));9 s l# s; i) ~ f) `) `
- result[1] = temp ^ pState[1] ^ gf_mult_by02((unsigned char) (pState[1] ^ pState[2]));
4 ]% ?% H, d- B( B5 S7 {6 D: F2 d9 | - result[2] = temp ^ pState[2] ^ gf_mult_by02((unsigned char) (pState[2] ^ pState[3]));' K, z2 d, P& [6 S
- result[3] = temp ^ pState[3] ^ gf_mult_by02((unsigned char) (pState[3] ^ pState[0]));
& I; o9 V8 y9 G8 w* K
& e! s& M3 `( l- if (bInvert)8 G F- @* v6 a. Y4 I
- {
* _3 G- Y! H K - // b0' = 14a0 + 11a1 + 13a2 + 9a3
* O7 I1 Z4 h# N - // = (a0 + a1 + a2 + a3) + 2(a0 + a1) + a0 (这部分为b0)1 K. R l: z b! u: m6 Y: I
- // + 2(4(a0 + a2) + 4(a1 + a3))
$ d' ^2 b! m$ M/ |. u - // + 4(a0 + a2)
2 W+ ^, e5 \ D2 k - ) Y/ [2 H9 Q3 }* B; i* z+ ?( Z
- a0Pa2_M4 = gf_mult_by02(gf_mult_by02((unsigned char) (pState[0] ^ pState[2])));4 U/ O! g3 y$ {8 b, k2 R; s
- a1Pa3_M4 = gf_mult_by02(gf_mult_by02((unsigned char) (pState[1] ^ pState[3])));5 y% W9 |1 R: l
- temp = gf_mult_by02((unsigned char) (a0Pa2_M4 ^ a1Pa3_M4));
& k c$ q1 H7 d. r - result[0] ^= temp ^ a0Pa2_M4;4 R6 p, A- q& l' h
- result[1] ^= temp ^ a1Pa3_M4;3 S5 x5 U$ ]" F* a- a1 s! V- M$ ?
- result[2] ^= temp ^ a0Pa2_M4;
7 A1 T: x+ V( I) k- k4 _# g - result[3] ^= temp ^ a1Pa3_M4;
& i0 E5 J' S1 K2 d- s - }. K( [0 F( O/ ]
6 Q$ `" d+ b5 p2 i$ X2 F( k- memcpy(pState, result, 4);
8 Y& q: A# D# o; }9 s/ P4 p - }5 M' Q7 }9 M, a* Z; n. F
- }
" B! T! i( D" k - * v7 H! M0 l% z! x
- ///3 c; }/ C+ r/ {, j: F x
- // 函数名: block_encrypt
. _& f4 g% N1 T$ w - // 描述: 对单块数据加密。. |6 _/ {5 X$ U2 l
- // 输入参数: pState -- 状态数据。+ f5 T2 M0 g; f# C9 q+ t- {7 U
- // 输出参数: pState -- 加密后的状态数据。+ d& `4 P# f* }
- // 返回值: 无。
" D8 }: O( F7 \& b# a( M4 R3 H# d+ [ - ///
7 A, |& x, R0 b# W) z! n9 O, Q - static void block_encrypt(unsigned char *pState)
- ]- o7 ?/ K1 f' w - {& R& G& L6 n" Y0 c
- unsigned char i;
3 K+ ^- u6 x4 ^' ^4 Q2 B -
1 \: t6 ]; Q. B* m* G - AddRoundKey(pState, g_roundKeyTable);8 m# \4 x) J- m+ b
- : j: W; f- F% D1 W5 d
- for (i = 1; i <= Nr; i++) // i = [1, Nr]
4 k! u+ z! c# J( P# q. F - {
1 A( J, z, X, M3 Q f/ V Q - sub_bytes(pState, 4*Nb, 0);
8 I/ ~6 ^' b5 Y( u5 ?( ?7 M - shift_rows(pState, 0);, p# { V, H7 F
- " f8 M5 T; `* S1 w
- if (i != Nr); k \' E" B6 G
- {) m7 ^3 H o. }
- mix_columns(pState, 0);/ e! L, v, q! L- F
- }+ k/ G( [' `. x! I: [& r5 l
- H. m8 |2 f0 Z6 ^% x
- AddRoundKey(pState, &g_roundKeyTable[4*Nb*i]);2 }. E% H) ]4 r5 Q+ j- S
- }: N9 q! [& y* B% u$ _- L
- 5 D2 g a* I1 V; g# u* u- K* l
- // 为了节省代码,合并到循化执行& q8 G, J8 J, P0 n/ V
- // sub_bytes(pState, 4*Nb);
5 c, X2 r8 r+ J" K1 } - // shift_rows(pState, 0);5 L# |; a: u3 {. D
- // AddRoundKey(pState, &g_roundKeyTable[4*Nb*Nr]);
+ B3 U4 V2 V& `+ N9 d% B8 t$ t - }
2 I! X" A5 I& ]) X' y" x. L
2 Y) B! X' Q) ~) ]- ///
; G$ p. K; N9 K5 M8 _ - // 函数名: block_decrypt
# W; Z( K9 A6 |0 L/ } - // 描述: 对单块数据解密。
" C3 w, ?/ i" S - // 输入参数: pState -- 状态数据。9 r/ c' }- W; G- R. y
- // 输出参数: pState -- 解密后的状态数据。
* M0 N1 H6 o5 }( Z) S - // 返回值: 无。
) }5 [" S. P7 R# @3 {- A - ///: I3 S/ o' I7 c2 |8 C0 Z% R6 k
- static void block_decrypt(unsigned char *pState)- ?- _* u# C, s4 ] M! h5 q
- {$ T) Z1 u: ]# J o S0 `/ J6 [6 Z
- unsigned char i;. o: J8 j% q0 ^* C
- : t r: u: m, e9 v) G* u' l
- AddRoundKey(pState, &g_roundKeyTable[4*Nb*Nr]);
( r5 h8 P: x9 K, z* G - ; m5 ~. I' Z. n( }) J. M
- for (i = Nr; i > 0; i--) // i = [Nr, 1]+ G+ ]% c- y1 _1 u, ^# E
- {
2 @1 c, a6 M3 F5 j4 n$ X% H - shift_rows(pState, 1);
4 I2 W) P, V5 t0 @8 U2 c- `* [ - sub_bytes(pState, 4*Nb, 1);) H# ]2 t5 @* m, x
- AddRoundKey(pState, &g_roundKeyTable[4*Nb*(i-1)]);8 n: o- ~0 X7 F) k0 y) J2 j
( |% Q f5 D2 j$ [4 q! T' V% m3 v- if (i != 1) y5 R: g e, m" ?: Z, t" ?! t2 V8 x0 G
- {% G0 X' W( O2 E J
- mix_columns(pState, 1);6 I. ~, k, M+ z3 ?$ E, s* a. R0 ?, T. O" L
- }
" _3 N, L" _2 T5 w - }2 U4 t0 [1 H" z9 ?
-
`$ g( Q9 Y$ q; g1 J - // 为了节省代码,合并到循化执行
4 g, K' W* C& C0 B; i0 _ - // shift_rows(pState, 1);8 [. b( o4 H8 W7 `
- // sub_bytes(pState, 4*Nb, 1);
9 V& t8 s9 \1 s/ I, D ^ - // AddRoundKey(pState, g_roundKeyTable);, G+ T* Q6 ~9 B# \1 Q
- }/ Q2 @6 W: _- V. j4 l: @
- 1 N0 Z. \% D) |1 @* E, X8 {* l/ D, k
- /*****************************************************************************
6 e- P8 w9 W9 \; K2 w4 J. X" s, M- Y - * Global Functions 全局函数% V$ o) Q. p: K' x6 Z
- ******************************************************************************/
, y6 y8 l5 j# v* Z" j0 g; z
: {( M3 N# \. o, |3 N8 K- ; o% i) N; a$ E. H4 N' k4 {; H
- ///
7 [7 `, A1 j7 s8 H - // 函数名: aes_init0 b' q, j+ f+ p3 q7 Y& Q
- // 描述: 初始化,在此执行扩展密钥操作。
# O$ q8 p0 \, }8 l - // 输入参数: pKey -- 原始密钥,其长度必须为 AES_KEY_LENGTH/8 字节。
: A" [+ S$ @6 i8 c - // 输出参数: 无。
4 ?* n& [3 n# U" _+ B. A! i - // 返回值: 无。" E& K% I. x& {7 O
- ///
9 F- x S* f( s9 W/ U4 @+ ? - void aes_init(const void *pKey)
$ |& M( q4 |0 N& Z4 T5 i - {
$ g! D1 w) s" ? - // 扩展密钥 f' k: ?/ p, G
- unsigned char i;
$ F5 v1 r* J3 Q/ ?9 F# e6 O) r0 R - unsigned char *pRoundKey;
. Z/ i: o4 L& r% T: s Z( ], D( I3 \$ q - unsigned char Rcon[4] = {0x01, 0x00, 0x00, 0x00};
5 F: w# w& O' @9 M6 `
) J% m! x- T7 h* Z- memcpy(g_roundKeyTable, pKey, 4*Nk);
$ [6 x! R+ _4 J1 Q1 U - 9 z& T) q! Q/ M( O B
- pRoundKey = &g_roundKeyTable[4*Nk];
& _; R( b, Z4 Y6 J v - # C. v4 Z3 \9 h$ g/ t; n- s
- for (i = Nk; i < Nb*(Nr+1); pRoundKey += 4, i++)% e- r% |' T1 V4 \: p" ]+ j" M) u
- {
9 V2 a: z% k0 j! s. j; i1 ` - memcpy(pRoundKey, pRoundKey - 4, 4);" M, g6 A) _" P% |$ _8 f: J& C
" `' y' {" [- ~0 ~- if (i % Nk == 0)( b2 O+ V' j' P
- {
) O: k% I9 s9 `9 B% t7 [4 p - rotation_word(pRoundKey);0 t% ^- ]' C0 m, V/ C
- sub_bytes(pRoundKey, 4, 0);" j$ p5 t0 C! |/ `8 L7 z5 I8 ?1 j
- xor_bytes(pRoundKey, Rcon, 4);
7 k- a0 V) W7 F4 F
3 b* z" p* x& [) H0 J! i, a" `" [- Rcon[0] = gf_mult_by02(Rcon[0]);
2 m3 y8 h) f4 {5 f3 p" z - }
* b% m1 ]5 y% W- t; R; C& M - else if (Nk > 6 && i % Nk == Nb)
1 E0 j- R8 P p |4 q: @/ c - {
4 y6 W8 \4 ^4 d! A( b% A9 W+ k6 f ? - sub_bytes(pRoundKey, 4, 0);; l2 | _3 G" B3 {5 p3 y) |
- }4 H8 @' \9 f9 Z
- , b/ C5 @9 P: j- d5 z# o
- xor_bytes(pRoundKey, pRoundKey - 4*Nk, 4);
; F4 ^" Q+ N( k - }
4 S! m. g h1 Q8 k9 n5 g# { - }
7 V* s1 ~. T5 S! }2 M - - X7 J* Q3 z3 t
- //
! h9 h, |1 F& S) _' b) j( [; X/ M - // 函数名: aes_encrypt6 u# e( M- ^( }2 v( i* w& |
- // 描述: 加密数据
% X6 c3 a# U9 h" x - // 输入参数: pPlainText -- 明文,即需加密的数据,其长度为nDataLen字节。( H9 v/ N3 C1 {" F8 A9 z) h( m
- // nDataLen -- 数据长度,以字节为单位,必须为AES_KEY_LENGTH/8的整倍数。
4 r) `% K4 `4 S - // pIV -- 初始化向量,如果使用ECB模式,可设为NULL。
( `! D) c; Y3 ^+ C9 E. H4 p. ` - // 输出参数: pCipherText -- 密文,即由明文加密后的数据,可以与pPlainText相同。
! H, Y& L C! f2 f/ P& r - // 返回值: 无。
. s( c( R/ Z- [ - //+ j* r1 x+ M: e
- void aes_encrypt(const unsigned char *pPlainText, unsigned char *pCipherText, - \1 P' t+ h6 H4 S
- unsigned int nDataLen, const unsigned char *pIV): T% S# @- R& |- ^7 d: W! G
- {
- \) E/ G2 Q7 d( i D - unsigned int i;
2 ^6 o& @: x+ g/ Q) \6 u8 F% s - : s7 F; b" Z/ y% H4 f
- if (pPlainText != pCipherText)
, ^% x# |9 u5 k4 q; k$ J7 } - {9 k4 p/ q7 q7 G; r1 e9 ~- [
- memcpy(pCipherText, pPlainText, nDataLen);2 p# O. K9 w2 l0 B+ O
- }% b% j. [# H8 w$ M0 F7 V0 c
- 5 x5 r7 e2 T& w N/ J
- for (i = nDataLen/(4*Nb); i > 0 ; i--, pCipherText += 4*Nb)! u1 H# s* |2 m
- {
# M9 E# y: G4 b: a' v6 } - #if AES_MODE == AES_MODE_CBC" q, V3 ]& ]4 m; ]1 e2 I! U) ~
- xor_bytes(pCipherText, pIV, 4*Nb);" s# O7 h- t( `1 J; k/ u
- #endif
( M X3 \$ e8 h) W' m1 u
& k) \/ o" I5 t# I9 q0 U5 `- block_encrypt(pCipherText);
6 W' [- m: p! }1 m$ U - pIV = pCipherText;8 P* d' c* e, Z3 j5 U- j- M
- }, h3 x' F. `( u- G3 b
- }
/ S$ l& k6 p2 c6 L# O4 d
; k. U& T0 F. V% o- //
* }( M4 ~ E) q( A8 D6 _8 V4 ^ - // 函数名: aes_decrypt7 ^( [* p# E. m, n/ K4 s
- // 描述: 解密数据: L1 }$ o( `8 a3 t% a7 B
- // 输入参数: pCipherText -- 密文,即需解密的数据,其长度为nDataLen字节。2 c/ x8 C2 j! S+ z8 ~! X, ? l
- // nDataLen -- 数据长度,以字节为单位,必须为AES_KEY_LENGTH/8的整倍数。
) P$ A0 f8 k6 d% n - // pIV -- 初始化向量,如果使用ECB模式,可设为NULL。
* X# N. A7 u6 |: ]! p7 I* F7 E - // 输出参数: pPlainText -- 明文,即由密文解密后的数据,可以与pCipherText相同。7 ~% D/ D: ?; S/ P+ S, n4 e7 k% ]
- // 返回值: 无。
+ D+ X% m/ J* D - //
# O& M9 r$ i7 T- L& b W- y - void aes_decrypt( const unsigned char *pCipherText,unsigned char *pPlainText,
* a0 H1 k& t/ S$ Z- C# o - unsigned int nDataLen, const unsigned char *pIV)
1 r& v; ^5 u7 G0 P! ^) d1 O - {
0 W; @; [. k$ c3 v; w - unsigned int i;
+ f5 O# \1 Y9 b0 i& s" }
, x! P2 c2 E* f- F, e `- if (pPlainText != pCipherText)
7 K- z- A# z5 b' R' V* h" ? - {% ?! h# c+ s ^
- memcpy(pPlainText, pCipherText, nDataLen);
; Q9 J; O. i( Q+ w0 l" U* n# V - }
+ F1 i5 a, |2 g. M8 t2 Q
9 u7 a: B9 ~# V* Q# N: P/ N- // 从最后一块数据开始解密,这样不用开辟空间来保存IV# s. n/ U1 d" w. D, J
- pPlainText += nDataLen - 4*Nb;, X/ C7 a6 U0 J% K5 C% k3 N
- for (i = nDataLen/(4*Nb); i > 0 ; i--, pPlainText -= 4*Nb)
/ O& e) u C9 A Z* L P0 L% O8 D - {' A( \! K/ o1 p/ r& S" |* t$ |
- block_decrypt(pPlainText);
- J/ h9 q7 F/ Q9 m4 e X/ S9 U
3 t) x3 K9 L( w0 h) A- #if AES_MODE == AES_MODE_CBC8 M, w# {6 |' H+ h# [8 ^) e
- if (i == 1)
$ i# A: t3 \4 \* c- Y0 T) F - {// 最后一块数据. ^! k1 {7 M+ K
- xor_bytes(pPlainText, pIV, 4*Nb);
. i. E* f" t1 v2 w, w - }
9 b4 D7 Q m2 Y" ~( Q - else7 [/ Z5 X3 q, o( A$ ~
- {
h- F! B1 [. G% z - xor_bytes(pPlainText, pPlainText - 4*Nb, 4*Nb);1 q7 R# k2 \) G1 B3 M4 Z
- }; ^9 P/ b: R8 M
- #endif# K' k3 G" }, T9 z$ N l) p3 I' a1 d
- }7 e6 G3 \' u6 _/ N
- }</i></i></i></i>
复制代码
5 d0 j7 Y! c: \三、使用
- X; ^: p. X" S4 @. g0 y使用注意点:: i& g" q4 y) n
1、AES_KEY_LENGTH取值只能是128,192 和 256
4 w2 r8 r1 D/ P& d: J; D+ y$ W+ r2、密钥和向量表长度为AES_KEY_LENGTH/8个字节
* p9 v( ^3 E' F: D9 M+ o3、加密、解密数据长度为AES_KEY_LENGTH/8的整数倍字节
# \: {+ k3 ]& U& s( [) M( o! w0 e' B* u* ~/ R2 r; o+ p. _% k
% n2 [1 s2 Z% u. T* Q4 Z, W8 H
- int main(void): A" J2 q) G, _% z; J9 T
- {
o0 D' ~: ^) `# P. e) x( S! G - u8 buf[16],saveBuf[16],descryptBuf[16];" F( U) W6 O2 G* ]+ L4 {* k
- u16 i;, s! W, v) A1 K B* u5 `% {
- unsigned char AES128key[16] = "123456789abcdefa";//秘钥6 d ~. P/ D r4 V) A8 g) Y3 C
- unsigned char AES_IV[16]= "0102030405123456";//向量表, _3 a8 k9 n# \# g% K3 i
- delay_init(168); //初始化延时函数9 N' {0 V. V$ [6 V
- LED_Init(); //初始化LED端口
% M; i0 G' B0 a! K0 E: D9 E - - n: b; U2 R1 Z" [" }9 d+ N& n
- aes_init(AES128key);//AES初始化, p+ m/ P6 i i* I( p
-
7 m1 |* @3 a8 V# A/ q0 p - for(i=0;i<sizeof(buf);i++)) X1 k) K- h8 ?8 d$ v( u1 ]1 K2 ^
- {( r2 B5 _+ r, t5 @2 t: _8 t
- buf=i;4 V6 V8 } n; p1 b
- }
: T# _% G( v5 s3 G w6 x: b - while(1)" E# |9 p7 {% }9 C$ Y
- {8 n# Y. d4 }( C
- aes_encrypt(buf,saveBuf,sizeof(buf), AES_IV);$ i* s L' G+ I! `/ ^
-
% K9 x( s& T5 F9 N. t+ @ - 9 Y' \2 p9 q) l: U2 E
- aes_decrypt(saveBuf,descryptBuf, sizeof(buf), AES_IV);
! _5 z& @+ Z) S. l - 7 B% i! @1 m- K8 L( V w; b: h
- : d+ r) Y8 Y3 n5 B4 f
- GPIO_ResetBits(GPIOF,GPIO_Pin_9); //LED0对应引脚GPIOF.9拉低,亮 等同LED0=0;/ t9 g o! H1 J) Y
- GPIO_SetBits(GPIOF,GPIO_Pin_10); //LED1对应引脚GPIOF.10拉高,灭 等同LED1=1;
5 r7 s" }0 R1 V3 _ G1 Q - delay_ms(500); //延时300ms$ e* d% q% Y4 Q" d; D! O" B
- GPIO_SetBits(GPIOF,GPIO_Pin_9); //LED0对应引脚GPIOF.0拉高,灭 等同LED0=1;9 o v$ K; S) h6 i* w3 p( X
- GPIO_ResetBits(GPIOF,GPIO_Pin_10); //LED1对应引脚GPIOF.10拉低,亮 等同LED1=0;
! {* q6 G- N- c& E- G( o4 l - delay_ms(500); //延时300ms
( f8 R0 |9 c, u4 m3 G5 h4 H - }
* T- x! N8 N- u/ n7 H7 M - }0 R. z O+ w. n) X0 P
4 I: a# g5 z* p) D- o# K% ?- M p: C- ! ^& ? [1 E5 f8 f- j0 [: \
复制代码
5 p/ y4 ^$ T9 g% k |
AES加密这么复杂?