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