跳到主要内容

AES-256加密 (aes256)

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

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

常量

#define AES256_KEY_SIZE (32)
#define AES256_BLOCK_SIZE (16)

数据结构

struct aes256_ctx_t {
uint8_t xkey[4 * 8 * (14 + 1)];
};

xkey 存储 AES-256 的扩展密钥(14 轮 + 初始轮密钥,共 15 组,每组 8 个 32 位字,即 480 字节)。

API

void aes256_set_key(struct aes256_ctx_t * ctx, uint8_t * key);

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

void aes256_ecb_encrypt(struct aes256_ctx_t * ctx, uint8_t * in, uint8_t * out, int blks);
void aes256_ecb_decrypt(struct aes256_ctx_t * ctx, uint8_t * in, uint8_t * out, int blks);

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

void aes256_cbc_encrypt(struct aes256_ctx_t * ctx, uint8_t * iv, uint8_t * in, uint8_t * out, int blks);
void aes256_cbc_decrypt(struct aes256_ctx_t * ctx, uint8_t * iv, uint8_t * in, uint8_t * out, int blks);

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

void aes256_ctr_encrypt(struct aes256_ctx_t * ctx, uint64_t offset, uint8_t * in, uint8_t * out, int bytes);
void aes256_ctr_decrypt(struct aes256_ctx_t * ctx, uint64_t offset, uint8_t * in, uint8_t * out, int bytes);

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

使用示例

ECB 模式(NIST 测试向量)

struct aes256_ctx_t ctx;
uint8_t key[32] = {
0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
};
uint8_t in[16] = {
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a
};
uint8_t out[16];

aes256_set_key(&ctx, key);
aes256_ecb_encrypt(&ctx, in, out, 1);
/* out = 0xf3,0xee,0xd1,0xbd,0xb5,0xd2,0xa0,0x3c,
0x06,0x4b,0x5a,0x7e,0x3d,0xb1,0x81,0xf8 */

CBC 模式(NIST 测试向量)

struct aes256_ctx_t ctx;
uint8_t key[32] = {
0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
};
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];

aes256_set_key(&ctx, key);
aes256_cbc_encrypt(&ctx, iv, in, out, 1);
/* out = 0xf5,0x8c,0x4c,0x04,0xd6,0xe5,0xf1,0xba,
0x77,0x9e,0xab,0xfb,0x5f,0x7b,0xfb,0xd6 */

CTR 模式

struct aes256_ctx_t ctx;
uint8_t key[32] = { ... };
uint8_t in[100] = { ... };
uint8_t enc[100];
uint8_t dec[100];

aes256_set_key(&ctx, key);
aes256_ctr_encrypt(&ctx, 0, in, enc, 100);
aes256_ctr_decrypt(&ctx, 0, enc, dec, 100);
/* dec 与 in 相同 */

加密→解密往返验证

struct aes256_ctx_t ctx;
uint8_t key[AES256_KEY_SIZE] = { ... };
uint8_t iv[AES256_BLOCK_SIZE] = { ... };
uint8_t in[AES256_BLOCK_SIZE * 10];
uint8_t enc[AES256_BLOCK_SIZE * 10];
uint8_t dec[AES256_BLOCK_SIZE * 10];

aes256_set_key(&ctx, key);

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

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