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