aes-cbc模式加密在加密和解密是需要一个初始化向量(Initialization Vector, IV),在每次加密之前或者解密之后,使用初始化向量与明文或密文异或。
加密时,明文首先与IV异或,然后将结果进行块加密,得到的输出就是密文,同时本次的输出密文作为下一个块加密的IV。
加密过程代码:
cypher_t* aes_cbc_encrypt(uint8_t* key, cypher_t* data_in)
{
//pad last block with 0
cypher_t* data_in_padding = block_padding(data_in);
cypher_t* cypher_out = (cypher_t*)malloc(sizeof(uint8_t) + data_in->len_data);
cypher_out->len_data = data_in_padding->len_data;
uint8_t iv[16] = {0};
memcpy(iv, IV, 16);
uint8_t temp_out[16] = {0};
for (uint8_t index = 0; index < data_in_padding->len_data/16 ; ++index){
array_xor(16, temp_out, data_in_padding->data + (index * 16), iv); //明文与iv异或
_aes128_encryption(key, cypher_out->data + index * 16, temp_out); //进行块加密得到密文,同时密文是下次加密的iv
memcpy(iv, cypher_out->data + index * 16, 16); //本次的密文是下次加密的iv
}
free(data_in_padding);
return cypher_out;
}
解密时,先将密文的第一个块进行块解密,然后将结果与IV异或,就能得到明文,同时,本次解密的输入密文作为下一个块解密的IV。
解密过程代码:
cypher_t* aes_cbc_decrypt(uint8_t* key, cypher_t* data_in)
{
cypher_t* cypher_padding = block_padding(data_in);
cypher_t* plain = (cypher_t*)malloc(data_in->len_data);
plain->len_data = cypher_padding->len_data;
uint8_t iv[16] = {0};
memcpy(iv, IV, 16);
uint8_t temp_out[16] = {0};
for (uint8_t index = 0; index < cypher_padding->len_data/16 ; ++index){
_aes128_decryption(key, temp_out, cypher_padding->data + (index*16)); //密文块解密
array_xor(16, plain->data + (index*16), temp_out, iv); //与iv异或得到明文
memcpy(iv, cypher_padding->data + (index*16), 16); //设置下次解密用到的iv
}
free(cypher_padding);
return plain;
}
测试程序:
int main()
{
uint8_t key[16] = {
0x01, 0x02, 0x03, 0x04, 0x0a, 0x0b, 0x0c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff
};
uint8_t iv[16] = {
0xa, 0xb, 0xc, 0xd, 0x1, 0x2, 0x3, 0x3, 0xa, 0xa, 0xa, 0xa, 0xf, 0xf, 0xf, 0xf
};
uint8_t* text = "hello aes_cbc encryption!";
printf("密钥:");
for (int i = 0; i < 16; ++i){
if (i%4 == 0 && i != 0)
printf(" ");
if (i % 16 == 0 && i != 0)
printf("\n");
printf("%02x ", key[i]);
}
printf("\n");
printf("明文:%s\n\n", text);
set_iv(iv);
//--------------------------aes cbc encrypt--------------------------------------
cypher_t* plain = (cypher_t*)malloc(sizeof(uint8_t) + strlen(text));
plain->len_data = strlen(text);
memcpy(plain->data, text, plain->len_data);
cypher_t* cypher = aes_cbc_encrypt(key, plain);
puts("密文:");
for (int i = 0; i < cypher->len_data; ++i){
if (i%4 == 0 && i != 0)
printf(" ");
if (i % 16 == 0 && i != 0)
printf("\n");
printf("%02x ", cypher->data[i]);
}
printf("\n\n");
free(plain);
//--------------------------aes cbc decrypt--------------------------------------
cypher_t* decrypted_plain = aes_cbc_decrypt(key, cypher);
puts("解密之后:");
for (int i = 0; i < decrypted_plain->len_data; ++i){
if (i%4 == 0 && i != 0)
printf(" ");
if (i % 16 == 0 && i != 0)
printf("\n");
printf("%02x ", decrypted_plain->data[i]);
}
printf("\n\n");
printf("解密之后的明文字符串输出:\n%s", decrypted_plain);
printf("\n\n");
free(decrypted_plain);
return 0;
}
输出:
密钥:01 02 03 04 0a 0b 0c 0d 00 00 00 00 ff ff ff ff
明文:hello aes_cbc encryption!
密文:
76 ae bb ed d2 c3 a6 16 00 4a 4b 3b 33 67 96 07
85 7c 70 c5 0b 7e f2 b6 75 ff fc 67 f4 99 c0 8a
解密之后:
68 65 6c 6c 6f 20 61 65 73 5f 63 62 63 20 65 6e
63 72 79 70 74 69 6f 6e 21 00 00 00 00 00 00 00
解密之后的明文字符串输出:
hello aes_cbc encryption!