说明:本文提供基于C代码的 AES 加密、解密代码,并附带测试案例。
简介:AES加密是一种对称加密算法,全称为Advanced Encryption Standard,是美国联邦政府采用的一种区块加密标准。这种算法使用相同的秘钥进行加密和解密,加密和解密的速度非常快,适用于大量数据的加密。
AES加密使用128位、192位或256位密钥,对数据进行加密。这些密钥长度提供了不同的安全级别和性能特性。AES加密支持多种块大小,最常见的是128位块大小。
AES加密基于分组加密的工作原理,将明文分成固定大小的块,然后使用相同的密钥和算法对每个块进行加密。每个块独立进行加密,因此加密和解密操作可以并行进行,提高了加密和解密的速度。
AES加密的算法非常复杂,包括一系列的数学运算,如模加、字节替换、行移位、列混淆等。这些操作使用特定的参数和算法实现,保证了加密的安全性和强度。
总之,AES加密是一种高效、安全、可靠的对称加密算法,广泛应用于数据存储、传输和保护等领域。
#include <stdio.h>
#include <stdint.h>
#include <string.h>
//----------------------------------------------------------------------------------------------------------------------------------------
// "0123456789ABCDEF" /* 长度参考 */
#define TEST_TINY_AES_IV "0123456789ABCDEF" /* 初始向量IV,定长 */
// "0123456789ABCDEF0123456789ABCDEF" /* 长度参考 */
#define TEST_TINY_AES_KEY "0123456789ABCDEF0123456789ABCDEF" /* AES key,定长 */
#define AES_DATA_LEN (16) /* KEY 加密后的数据长度 */
#define AES_DEC_LEN (16) /* AES 数据解密后长度 */
#define AES_ENCRYPT 1
#define AES_DECRYPT 0
typedef struct
{
int nr; /*!< number of rounds */
uint32_t *rk; /*!< AES round keys */
uint32_t buf[68]; /*!< unaligned data */
} tiny_aes_context;
/* aes.h ---------------------------------------------------------------- */
void tiny_aes_setkey_enc(tiny_aes_context * ctx, uint8_t *key, int keysize);
void tiny_aes_setkey_dec(tiny_aes_context * ctx, uint8_t *key, int keysize);
void tiny_aes_crypt_ecb(tiny_aes_context * ctx,int mode,uint8_t input[16], uint8_t output[16]);
void tiny_aes_crypt_cbc(tiny_aes_context * ctx,int mode,int length,uint8_t iv[16],uint8_t *input, uint8_t *output);
void tiny_aes_crypt_cfb128(tiny_aes_context * ctx,int mode,int length,int *iv_off,uint8_t iv[16],uint8_t *input, uint8_t *output);
/* aes.c ---------------------------------------------------------------- */
//#include <string.h>
#define TINY_CRYPT_AES
#if 0
#define AES_ENCRYPT 1
#define AES_DECRYPT 0
typedef struct {
int nr; /*!< number of rounds */
uint32_t *rk; /*!< AES round keys */
uint32_t buf[68]; /*!< unaligned data */
} tiny_aes_context;
#endif
#if defined(TINY_CRYPT_AES)
/*
* 32-bit integer manipulation macros (little endian)
*/
#ifndef GET_ULONG_LE
#define GET_ULONG_LE(n,b,i) \
{ \
(n) = ( (uint32_t) (b)[(i) ] ) \
| ( (uint32_t) (b)[(i) + 1] << 8 ) \
| ( (uint32_t) (b)[(i) + 2] << 16 ) \
| ( (uint32_t) (b)[(i) + 3] << 24 ); \
}
#endif
#ifndef PUT_ULONG_LE
#define PUT_ULONG_LE(n,b,i) \
{ \
(b)[(i) ] = (uint8_t) ( (n) ); \
(b)[(i) + 1] = (uint8_t) ( (n) >> 8 ); \
(b)[(i) + 2] = (uint8_t) ( (n) >> 16 ); \
(b)[(i) + 3] = (uint8_t) ( (n) >> 24 ); \
}
#endif
#if defined(TINY_CRYPT_AES_ROM_TABLES)
#else
/*
* Forward S-box & tables
*/
static uint8_t FSb[256];
static uint32_t FT0[256];
static uint32_t FT1[256];
static uint32_t FT2[256];
static uint32_t FT3[256];
/*
* Reverse S-box & tables
*/
static uint8_t RSb[256];
static uint32_t RT0[256];
static uint32_t RT1[256];
static uint32_t RT2[256];
static uint32_t RT3[256];
/*
* Round constants
*/
static uint32_t RCON[10];
/*
* Tables generation code
*/
#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 )
#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 )
static int aes_init_done = 0;
static void aes_gen_tables(void)
{
int i, x, y, z;
int pow[256];
int log[256];
/*
* compute pow and log tables over GF(2^8)
*/
for (i = 0, x = 1; i < 256; i++) {
pow[i] = x;
log[x] = i;
x = (x ^ XTIME(x)) & 0xFF;
}
/*
* calculate the round constants
*/
for (i = 0, x = 1; i < 10; i++) {
RCON[i] = (uint32_t)x;
x = XTIME(x) & 0xFF;
}
/*
* generate the forward and reverse S-boxes
*/
FSb[0x00] = 0x63;
RSb[0x63] = 0x00;
for (i = 1; i < 256; i++) {
x = pow[255 - log[i]];
y = x;
y = ((y << 1) | (y >> 7)) & 0xFF;
x ^= y;
y = ((y << 1) | (y >> 7)) & 0xFF;
x ^= y;
y = ((y << 1) | (y >> 7)) & 0xFF;
x ^= y;
y = ((y << 1) | (y >> 7)) & 0xFF;
x ^= y ^ 0x63;
FSb[i] = (uint8_t)x;
RSb[x] = (uint8_t)i;
}
/*
* generate the forward and reverse tables
*/
for (i = 0; i < 256; i++) {
x = FSb[i];
y = XTIME(x) & 0xFF;
z = (y ^ x) & 0xFF;
FT0[i] = ((uint32_t)y) ^
((uint32_t)x << 8) ^
((uint32_t)x << 16) ^ ((uint32_t)z << 24);
FT1[i] = ROTL8(FT0[i]);
FT2[i] = ROTL8(FT1[i]);
FT3[i] = ROTL8(FT2[i]);
x = RSb[i];
RT0[i] = ((uint32_t)MUL(0x0E, x)) ^
((uint32_t)MUL(0x09, x) << 8) ^
((uint32_t)MUL(0x0D, x) << 16) ^
((uint32_t)MUL(0x0B, x) << 24);
RT1[i] = ROTL8(RT0[i]);
RT2[i] = ROTL8(RT1[i]);
RT3[i] = ROTL8(RT2[i]);
}
}
#endif
/*
* AES key schedule (encryption)
*/
void tiny_aes_setkey_enc(tiny_aes_context * ctx, uint8_t *key, int keysize)
{
int i;
uint32_t *RK;
#if !defined(TINY_CRYPT_AES_ROM_TABLES)
if (aes_init_done == 0) {
aes_gen_tables();
aes_init_done = 1;
}
#endif
switch (keysize) {
case 128:
ctx->nr = 10;
break;
case 192:
ctx->nr = 12;
break;
case 256:
ctx->nr = 14;
break;
default:
return;
}
ctx->rk = RK = ctx->buf;
for (i = 0; i < (keysize >> 5); i++) {
GET_ULONG_LE(RK[i], key, i << 2);
}
switch (ctx->nr) {
case 10:
for (i = 0; i < 10; i++, RK += 4) {
RK[4] = RK[0] ^ RCON[i] ^
((uint32_t)FSb[(RK[3] >> 8) & 0xFF]) ^
((uint32_t)FSb[(RK[3] >> 16) & 0xFF] << 8) ^
((uint32_t)FSb[(RK[3] >> 24) & 0xFF] << 16) ^
((uint32_t)FSb[(RK[3]) & 0xFF] << 24);
RK[5] = RK[1] ^ RK[4];
RK[6] = RK[2] ^ RK[5];
RK[7] = RK[3] ^ RK[6];
}
break;
case 12:
for (i = 0; i < 8; i++, RK += 6) {
RK[6] = RK[0] ^ RCON[i] ^
((uint32_t)FSb[(RK[5] >> 8) & 0xFF]) ^
((uint32_t)FSb[(RK[5] >> 16) & 0xFF] << 8) ^
((uint32_t)FSb[(RK[5] >> 24) & 0xFF] << 16) ^
((uint32_t)FSb[(RK[5]) & 0xFF] << 24);
RK[7] = RK[1] ^ RK[6];
RK[8] = RK[2] ^ RK[7];
RK[9] = RK[3] ^ RK[8];
RK[10] = RK[4] ^ RK[9];
RK[11] = RK[5] ^ RK[10];
}
break;
case 14:
for (i = 0; i < 7; i++, RK += 8) {
RK[8] = RK[0] ^ RCON[i] ^
((uint32_t)FSb[(RK[7] >> 8) & 0xFF]) ^
((uint32_t)FSb[(RK[7] >> 16) & 0xFF] << 8) ^
((uint32_t)FSb[(RK[7] >> 24) & 0xFF] << 16) ^
((uint32_t)FSb[(RK[7]) & 0xFF] << 24);
RK[9] = RK[1] ^ RK[8];
RK[10] = RK[2] ^ RK[9];
RK[11] = RK[3] ^ RK[10];
RK[12] = RK[4] ^
((uint32_t)FSb[(RK[11]) & 0xFF]) ^
((uint32_t)FSb[(RK[11] >> 8) & 0xFF] << 8) ^
((uint32_t)FSb[(RK[11] >> 16) & 0xFF] << 16) ^
((uint32_t)FSb[(RK[11] >> 24) & 0xFF] << 24);
RK[13] = RK[5] ^ RK[12];
RK[14] = RK[6] ^ RK[13];
RK[15] = RK[7] ^ RK[14];
}
break;
default:
break;
}
}
/*
* AES key schedule (decryption)
*/
void tiny_aes_setkey_dec(tiny_aes_context * ctx, uint8_t *key, int keysize)
{
int i, j;
tiny_aes_context cty;
uint32_t *RK;
uint32_t *SK;
switch (keysize) {
case 128:
ctx->nr = 10;
break;
case 192:
ctx->nr = 12;
break;
case 256:
ctx->nr = 14;
break;
default:
return;
}
ctx->rk = RK = ctx->buf;
tiny_aes_setkey_enc(&cty, key, keysize);
SK = cty.rk + cty.nr * 4;
*RK++ = *SK++;
*RK++ = *SK++;
*RK++ = *SK++;
*RK++ = *SK++;
for (i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8) {
for (j = 0; j < 4; j++, SK++) {
*RK++ = RT0[FSb[(*SK) & 0xFF]] ^
RT1[FSb[(*SK >> 8) & 0xFF]] ^
RT2[FSb[(*SK >> 16) & 0xFF]] ^
RT3[FSb[(*SK >> 24) & 0xFF]];
}
}
*RK++ = *SK++;
*RK++ = *SK++;
*RK++ = *SK++;
*RK++ = *SK++;
memset(&cty, 0, sizeof(tiny_aes_context));
}
#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
{ \
X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \
FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
FT3[ ( Y3 >> 24 ) & 0xFF ]; \
\
X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \
FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
FT3[ ( Y0 >> 24 ) & 0xFF ]; \
\
X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \
FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
FT3[ ( Y1 >> 24 ) & 0xFF ]; \
\
X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \
FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
FT3[ ( Y2 >> 24 ) & 0xFF ]; \
}
#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
{ \
X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \
RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
RT3[ ( Y1 >> 24 ) & 0xFF ]; \
\
X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \
RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
RT3[ ( Y2 >> 24 ) & 0xFF ]; \
\
X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \
RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
RT3[ ( Y3 >> 24 ) & 0xFF ]; \
\
X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \
RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
RT3[ ( Y0 >> 24 ) & 0xFF ]; \
}
/*
* AES-ECB block encryption/decryption
*/
void tiny_aes_crypt_ecb(tiny_aes_context * ctx,
int mode, uint8_t input[16], uint8_t output[16])
{
int i;
uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
RK = ctx->rk;
GET_ULONG_LE(X0, input, 0);
X0 ^= *RK++;
GET_ULONG_LE(X1, input, 4);
X1 ^= *RK++;
GET_ULONG_LE(X2, input, 8);
X2 ^= *RK++;
GET_ULONG_LE(X3, input, 12);
X3 ^= *RK++;
if (mode == AES_DECRYPT) {
for (i = (ctx->nr >> 1) - 1; i > 0; i--) {
AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3);
AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3);
}
AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3);
X0 = *RK++ ^
((uint32_t)RSb[(Y0) & 0xFF]) ^
((uint32_t)RSb[(Y3 >> 8) & 0xFF] << 8) ^
((uint32_t)RSb[(Y2 >> 16) & 0xFF] << 16) ^
((uint32_t)RSb[(Y1 >> 24) & 0xFF] << 24);
X1 = *RK++ ^
((uint32_t)RSb[(Y1) & 0xFF]) ^
((uint32_t)RSb[(Y0 >> 8) & 0xFF] << 8) ^
((uint32_t)RSb[(Y3 >> 16) & 0xFF] << 16) ^
((uint32_t)RSb[(Y2 >> 24) & 0xFF] << 24);
X2 = *RK++ ^
((uint32_t)RSb[(Y2) & 0xFF]) ^
((uint32_t)RSb[(Y1 >> 8) & 0xFF] << 8) ^
((uint32_t)RSb[(Y0 >> 16) & 0xFF] << 16) ^
((uint32_t)RSb[(Y3 >> 24) & 0xFF] << 24);
X3 = *RK++ ^
((uint32_t)RSb[(Y3) & 0xFF]) ^
((uint32_t)RSb[(Y2 >> 8) & 0xFF] << 8) ^
((uint32_t)RSb[(Y1 >> 16) & 0xFF] << 16) ^
((uint32_t)RSb[(Y0 >> 24) & 0xFF] << 24);
} else { /* AES_ENCRYPT */
for (i = (ctx->nr >> 1) - 1; i > 0; i--) {
AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3);
AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3);
}
AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3);
X0 = *RK++ ^
((uint32_t)FSb[(Y0) & 0xFF]) ^
((uint32_t)FSb[(Y1 >> 8) & 0xFF] << 8) ^
((uint32_t)FSb[(Y2 >> 16) & 0xFF] << 16) ^
((uint32_t)FSb[(Y3 >> 24) & 0xFF] << 24);
X1 = *RK++ ^
((uint32_t)FSb[(Y1) & 0xFF]) ^
((uint32_t)FSb[(Y2 >> 8) & 0xFF] << 8) ^
((uint32_t)FSb[(Y3 >> 16) & 0xFF] << 16) ^
((uint32_t)FSb[(Y0 >> 24) & 0xFF] << 24);
X2 = *RK++ ^
((uint32_t)FSb[(Y2) & 0xFF]) ^
((uint32_t)FSb[(Y3 >> 8) & 0xFF] << 8) ^
((uint32_t)FSb[(Y0 >> 16) & 0xFF] << 16) ^
((uint32_t)FSb[(Y1 >> 24) & 0xFF] << 24);
X3 = *RK++ ^
((uint32_t)FSb[(Y3) & 0xFF]) ^
((uint32_t)FSb[(Y0 >> 8) & 0xFF] << 8) ^
((uint32_t)FSb[(Y1 >> 16) & 0xFF] << 16) ^
((uint32_t)FSb[(Y2 >> 24) & 0xFF] << 24);
}
PUT_ULONG_LE(X0, output, 0);
PUT_ULONG_LE(X1, output, 4);
PUT_ULONG_LE(X2, output, 8);
PUT_ULONG_LE(X3, output, 12);
}
/*
* AES-CBC buffer encryption/decryption
*/
void tiny_aes_crypt_cbc(tiny_aes_context * ctx,
int mode,
int length,
uint8_t iv[16],
uint8_t *input, uint8_t *output)
{
int i;
uint8_t temp[16];
if (mode == AES_DECRYPT) {
while (length > 0) {
memcpy(temp, input, 16);
tiny_aes_crypt_ecb(ctx, mode, input, output);
for (i = 0; i < 16; i++)
output[i] = (uint8_t)(output[i] ^ iv[i]);
memcpy(iv, temp, 16);
input += 16;
output += 16;
length -= 16;
}
} else {
while (length > 0) {
for (i = 0; i < 16; i++)
output[i] = (uint8_t)(input[i] ^ iv[i]);
tiny_aes_crypt_ecb(ctx, mode, output, output);
memcpy(iv, output, 16);
input += 16;
output += 16;
length -= 16;
}
}
}
/*
* AES-CFB128 buffer encryption/decryption
*/
void tiny_aes_crypt_cfb128(tiny_aes_context * ctx,
int mode,
int length,
int *iv_off,
uint8_t iv[16],
uint8_t *input, uint8_t *output)
{
int c, n = *iv_off;
if (mode == AES_DECRYPT) {
while (length--) {
if (n == 0)
tiny_aes_crypt_ecb(ctx, AES_ENCRYPT, iv, iv);
c = *input++;
*output++ = (uint8_t)(c ^ iv[n]);
iv[n] = (uint8_t)c;
n = (n + 1) & 0x0F;
}
} else {
while (length--) {
if (n == 0)
tiny_aes_crypt_ecb(ctx, AES_ENCRYPT, iv, iv);
iv[n] = *output++ = (uint8_t)(iv[n] ^ *input++);
n = (n + 1) & 0x0F;
}
}
*iv_off = n;
}
#endif
/* mode: 0 dec 解密, 1 enc 加密
* k_check_t *cd :输入数据
* uint8_t *enc_db :输出数据
* */
uint8_t key_aes_enc_dec(uint8_t mode,uint8_t *cd,uint8_t *enc_db)
{
tiny_aes_context ctx;
uint8_t iv[16 + 1];
uint8_t private_key[32 + 1];
#if 1
if ((mode == 1)&&(enc_db != NULL))
{
/* encrypt */
memcpy(iv, TEST_TINY_AES_IV, strlen(TEST_TINY_AES_IV));
iv[sizeof(iv) - 1] = '\0';
memcpy(private_key, TEST_TINY_AES_KEY, strlen(TEST_TINY_AES_KEY));
private_key[sizeof(private_key) - 1] = '\0';
memset(enc_db, 0x0, sizeof(AES_DATA_LEN));
tiny_aes_setkey_enc(&ctx, (uint8_t *) private_key, 256);
tiny_aes_crypt_cbc(&ctx, AES_ENCRYPT, AES_DEC_LEN, iv, (uint8_t *)cd, enc_db);
}
#endif
if ((mode == 0)&&(enc_db != NULL))
{
/* decrypt */
memcpy(iv, TEST_TINY_AES_IV, strlen(TEST_TINY_AES_IV));
iv[sizeof(iv) - 1] = '\0';
memcpy(private_key, TEST_TINY_AES_KEY, strlen(TEST_TINY_AES_KEY));
private_key[sizeof(private_key) - 1] = '\0';
tiny_aes_setkey_dec(&ctx, (uint8_t *) private_key, 256);
tiny_aes_crypt_cbc(&ctx, AES_DECRYPT, AES_DEC_LEN, iv,(uint8_t *)cd ,(uint8_t *)enc_db);
}
return 1;
}
//测试
int main()
{
uint8_t data[] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F};
uint8_t output_enc[16]; // 加密数据
uint8_t output_dec[16]; // 解密数据
key_aes_enc_dec(1,data,output_enc); //加密
printf("enc:");
for (uint8_t var = 0; var < 16; ++var)
{
printf("%02X",output_enc[var]);
}
printf("\n");
key_aes_enc_dec(0,output_enc,output_dec); //解密
printf("dec:");
for (uint8_t var = 0; var < 16; ++var)
{
printf("%02X",output_dec[var]);
}
printf("\n");
return 0;
}
//计算结果
//enc:7A34715E1C18847155B58997C76E3ECC
//dec:000102030405060708090A0B0C0D0E0F