body, table tr { background-color: rgba(255, 255, 255, 1) }
table tr td, table tr th { border: 1px solid rgba(204, 204, 204, 1); text-align: left; padding: 6px 13px; margin: 0 }
pre code, table, table tr { padding: 0 }
hr, pre code { background: left top }
body { font: 16px / 1.4 Helvetica, Arial, sans-serif; color: rgba(51, 51, 51, 1); word-wrap: break-word; padding: 10px 15px }
strong, table tr th { font-weight: 700 }
h1 { font-size: 2em; margin: 0.67em 0; text-align: center }
h2 { font-size: 1.75em }
h3 { font-size: 1.5em }
h4 { font-size: 1.25em }
h1, h2, h3, h4, h5, h6 { font-weight: 700; position: relative; margin-top: 15px; margin-bottom: 15px; line-height: 1.1 }
h1, h2 { border-bottom: 1px solid rgba(238, 238, 238, 1) }
hr { height: 0; margin: 15px 0; overflow: hidden; border-top: 0; border-right: 0; border-bottom: 1px solid rgba(221, 221, 221, 1); border-left: 0 }
a { color: rgba(65, 131, 196, 1) }
a.absent { color: rgba(204, 0, 0, 1) }
ol, ul { padding-left: 15px; margin-left: 5px }
ol { list-style-type: lower-roman }
table tr { border-top: 1px solid rgba(204, 204, 204, 1); margin: 0 }
table tr:nth-child(2n) { background-color: rgba(170, 170, 170, 1) }
table tr td :first-child, table tr th :first-child { margin-top: 0 }
table tr td:last-child, table tr th :last-child { margin-bottom: 0 }
img { max-width: 100% }
blockquote { padding: 0 15px; border-left: 4px solid rgba(204, 204, 204, 1) }
code, tt { margin: 0 2px; padding: 0 5px; white-space: nowrap; border: 1px solid rgba(234, 234, 234, 1); background-color: rgba(248, 248, 248, 1); border-radius: 3px }
pre code { margin: 0; white-space: pre; border: none }
.highlight pre, pre { background-color: rgba(248, 248, 248, 1); border: 1px solid rgba(204, 204, 204, 1); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-radius: 3px }

aes-cbc模式加密——密码分组链接模式(Cipher Block Chaining (CBC))

aes-cbc模式加密在加密和解密是需要一个初始化向量(Initialization Vector, IV),在每次加密之前或者解密之后,使用初始化向量与明文或密文异或。

1. 加密


加密时,明文首先与IV异或,然后将结果进行块加密,得到的输出就是密文,同时本次的输出密文作为下一个块加密的IV。

加密过程代码:

 1 cypher_t* aes_cbc_encrypt(uint8_t* key, cypher_t* data_in)
 2 {
 3     //pad last block with 0
 4     cypher_t* data_in_padding = block_padding(data_in);
 5     cypher_t* cypher_out = (cypher_t*)malloc(sizeof(uint8_t) + data_in->len_data);
 6     cypher_out->len_data = data_in_padding->len_data;
 7 
 8     uint8_t iv[16] = {0};
 9     memcpy(iv, IV, 16);
10     uint8_t temp_out[16] = {0};
11     for (uint8_t index = 0; index < data_in_padding->len_data/16 ; ++index){
12         array_xor(16, temp_out, data_in_padding->data + (index * 16), iv);      //明文与iv异或
13         _aes128_encryption(key, cypher_out->data + index * 16, temp_out);       //进行块加密得到密文,同时密文是下次加密的iv
14         memcpy(iv, cypher_out->data + index * 16, 16);                          //本次的密文是下次加密的iv
15     }
16     free(data_in_padding);
17     return cypher_out;
18 }

2. 解密


解密时,先将密文的第一个块进行块解密,然后将结果与IV异或,就能得到明文,同时,本次解密的输入密文作为下一个块解密的IV。

解密过程代码:

 1 cypher_t* aes_cbc_decrypt(uint8_t* key, cypher_t* data_in)
 2 {
 3     cypher_t* cypher_padding = block_padding(data_in);
 4     cypher_t* plain = (cypher_t*)malloc(data_in->len_data);
 5     plain->len_data = cypher_padding->len_data;
 6     uint8_t iv[16] = {0};
 7     memcpy(iv, IV, 16);
 8     uint8_t temp_out[16] = {0};
 9     for (uint8_t index = 0; index < cypher_padding->len_data/16 ; ++index){
10         _aes128_decryption(key, temp_out, cypher_padding->data + (index*16));   //密文块解密
11         array_xor(16, plain->data + (index*16), temp_out, iv);                  //与iv异或得到明文
12         memcpy(iv, cypher_padding->data + (index*16), 16);                      //设置下次解密用到的iv
13     }
14     free(cypher_padding);
15     return plain;
16 }

测试程序:

 1 int main()
 2 {
 3     uint8_t key[16] = {
 4         0x01, 0x02, 0x03, 0x04, 0x0a, 0x0b, 0x0c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff
 5     };
 6     uint8_t iv[16] = {
 7         0xa, 0xb, 0xc, 0xd, 0x1, 0x2, 0x3, 0x3, 0xa, 0xa, 0xa, 0xa, 0xf, 0xf, 0xf, 0xf
 8     };
 9     uint8_t* text = "hello aes_cbc encryption!";
10 
11     printf("密钥:");
12     for (int i = 0; i < 16; ++i){
13         if (i%4 == 0 && i != 0)
14             printf(" ");
15         if (i % 16 == 0 && i != 0)
16             printf("\n");
17         printf("%02x ", key[i]);
18     }
19     printf("\n");
20     printf("明文:%s\n\n", text);
21 
22     set_iv(iv);
23     //--------------------------aes cbc encrypt--------------------------------------
24     cypher_t* plain = (cypher_t*)malloc(sizeof(uint8_t) + strlen(text));
25     plain->len_data = strlen(text);
26     memcpy(plain->data, text, plain->len_data);
27     cypher_t* cypher = aes_cbc_encrypt(key, plain);
28     puts("密文:");
29     for (int i = 0; i < cypher->len_data; ++i){
30         if (i%4 == 0 && i != 0)
31             printf(" ");
32         if (i % 16 == 0 && i != 0)
33             printf("\n");
34         printf("%02x ", cypher->data[i]);
35 
36     }
37     printf("\n\n");
38     free(plain);
39     //--------------------------aes cbc decrypt--------------------------------------
40     cypher_t* decrypted_plain = aes_cbc_decrypt(key, cypher);
41     puts("解密之后:");
42     for (int i = 0; i < decrypted_plain->len_data; ++i){
43         if (i%4 == 0 && i != 0)
44             printf(" ");
45         if (i % 16 == 0 && i != 0)
46             printf("\n");
47         printf("%02x ", decrypted_plain->data[i]);
48     }
49     printf("\n\n");
50     printf("解密之后的明文字符串输出:\n%s", decrypted_plain);
51     printf("\n\n");
52     free(decrypted_plain);
53     return 0;
54 }

 

输出:

密钥: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!

完整代码在 https://github.com/FANCY0047/aes-cbc.git

注:aes加密解密函数来源于互联网

 

版权声明:本文为eleven-elv原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/eleven-elv/p/7289579.html