跳到主要内容

AES-128加密 (aes128)

AES-128 对称加密/解密,支持 ECB、CBC、CTR 三种分组密码模式。

  • 密钥长度:16 字节
  • 分块大小:16 字节
  • 轮数:10 轮

常量

#define AES128_KEY_SIZE (16)
#define AES128_BLOCK_SIZE (16)

数据结构

struct aes128_ctx_t {
uint8_t xkey[4 * 4 * (10 + 1)];
};

xkey 存储 AES-128 的扩展密钥(10 轮 + 初始轮密钥,共 11 组,每组 4 个 32 位字,即 176 字节)。

API

void aes128_set_key(struct aes128_ctx_t * ctx, uint8_t * key);

设置 16 字节密钥,初始化加密上下文,完成密钥扩展。

void aes128_ecb_encrypt(struct aes128_ctx_t * ctx, uint8_t * in, uint8_t * out, int blks);
void aes128_ecb_decrypt(struct aes128_ctx_t * ctx, uint8_t * in, uint8_t * out, int blks);

ECB 模式加密/解密。inout 必须为 blks * 16 字节,即输入必须是 16 字节的整数倍。

void aes128_cbc_encrypt(struct aes128_ctx_t * ctx, uint8_t * iv, uint8_t * in, uint8_t * out, int blks);
void aes128_cbc_decrypt(struct aes128_ctx_t * ctx, uint8_t * iv, uint8_t * in, uint8_t * out, int blks);

CBC 模式加密/解密。iv 为 16 字节初始向量,inout 必须为 blks * 16 字节。加密时 iv 会被修改,如需保留原始 iv 请提前备份。

void aes128_ctr_encrypt(struct aes128_ctx_t * ctx, uint64_t offset, uint8_t * in, uint8_t * out, int bytes);
void aes128_ctr_decrypt(struct aes128_ctx_t * ctx, uint64_t offset, uint8_t * in, uint8_t * out, int bytes);

CTR 模式加密/解密。offset 为计数器偏移(块为单位),bytes 为处理的字节数。CTR 模式不要求输入为 16 字节的整数倍,且加密和解密使用相同操作。

使用示例

ECB 模式(NIST 测试向量)

struct aes128_ctx_t ctx;
uint8_t key[16] = {
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
};
uint8_t in[16] = {
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a
};
uint8_t out[16];

aes128_set_key(&ctx, key);
aes128_ecb_encrypt(&ctx, in, out, 1);
/* out = 0x3a,0xd7,0x7b,0xb4,0x0d,0x7a,0x36,0x60,
0xa8,0x9e,0xca,0xf3,0x24,0x66,0xef,0x97 */

CBC 模式(NIST 测试向量)

struct aes128_ctx_t ctx;
uint8_t key[16] = {
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
};
uint8_t iv[16] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
};
uint8_t in[16] = {
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a
};
uint8_t out[16];

aes128_set_key(&ctx, key);
aes128_cbc_encrypt(&ctx, iv, in, out, 1);
/* out = 0x76,0x49,0xab,0xac,0x81,0x19,0xb2,0x46,
0xce,0xe9,0x8e,0x9b,0x12,0xe9,0x19,0x7d */

CTR 模式

struct aes128_ctx_t ctx;
uint8_t key[16] = { ... };
uint8_t in[100] = { ... };
uint8_t enc[100];
uint8_t dec[100];

aes128_set_key(&ctx, key);
aes128_ctr_encrypt(&ctx, 0, in, enc, 100);
aes128_ctr_decrypt(&ctx, 0, enc, dec, 100);
/* dec 与 in 相同 */

加密→解密往返验证

struct aes128_ctx_t ctx;
uint8_t key[AES128_KEY_SIZE] = { ... };
uint8_t iv[AES128_BLOCK_SIZE] = { ... };
uint8_t in[AES128_BLOCK_SIZE * 10];
uint8_t enc[AES128_BLOCK_SIZE * 10];
uint8_t dec[AES128_BLOCK_SIZE * 10];

aes128_set_key(&ctx, key);

/* ECB 往返 */
aes128_ecb_encrypt(&ctx, in, enc, 10);
aes128_ecb_decrypt(&ctx, enc, dec, 10);
/* memcmp(in, dec, sizeof(in)) == 0 */

/* CBC 往返(注意 iv 会被加密修改,需重新设置) */
aes128_cbc_encrypt(&ctx, iv, in, enc, 10);
aes128_cbc_decrypt(&ctx, iv, enc, dec, 10);
/* memcmp(in, dec, sizeof(in)) == 0 */