C++实现AES对称加密算法-CBC
一、可选参数
编写一个新的协议或者算法,首先要了解它的参数
了解一个协议或算法所需要的参数,最快的方法就是借用别人已经写好的第三方工具使用一次,查看所需要的参数。

由上图可以得知,需要的参数:
- 填充模式 : None、PKCS7、Zeros、ANSIX923、ISO10126
- 密钥长度 : 128bit、192bit、256bit
- 密钥:TEXT、Hex
- 偏移(IV值):16bit
- 输出格式:Base64、Hex
二、基于openssl库实现AES256解密
2.1 接口函数
| 接口函数 | 作用 |
|---|---|
| AES_KEY 结构体 | 存储 AES 加密 / 解密的密钥信息,包含经过 “密钥扩展” 算法生成的轮密钥 |
| AES_set_encrypt_key | 将原始密钥(userKey)转换为 AES 加密所需的轮密钥,并存储到AES_KEY结构体中 |
| AES_cbc_encrypt | 执行 AES-CBC 模式的加密或解密操作 |
2.2 加密函数
/*
* @brief AES-256-CBC模式加密函数
* @param plain 待加密的明文
* encrypt 存储加密后密文的缓冲区
* data_len 明文数据的长度(单位:字节,必须是AES_BLOCK_SIZE的整数倍,即16字节的倍数)
* key 指向原始密钥缓冲区(32字节,AES-256要求)
* iv 初始向量IV(16字节,AES_BLOCK_SIZE固定为16)
* @return int 成功返回加密后的数据长度(与data_len相同),失败返回-1
*/
int aes256_encrypt(unsigned char* plain, unsigned char* encrypt, int data_len, unsigned char* key, unsigned char* iv)
{
AES_KEY enc_key; // 存储AES加密密钥信息(包含轮密钥)
unsigned char* client_key = key; // 指向实际使用的密钥缓冲区
// 用明文数据覆盖密钥(前16字节 + 接下来的16字节,共32字节)
memcpy(client_key, plain, 16);
memcpy(client_key + 16, plain, 16);
// 初始化256位AES加密密钥,失败返回-1
if(AES_set_encrypt_key(client_key, 256, &enc_key) < 0)
{
return -1;
}
// 创建IV副本(CBC模式加密会修改IV,需保护原始IV)
unsigned char iv_copy[AES_BLOCK_SIZE];
memcpy(iv_copy, iv, AES_BLOCK_SIZE);
// 执行CBC模式加密(AES_ENCRYPT表示加密操作)
AES_cbc_encrypt(plain, encrypt, data_len, &enc_key, iv_copy, AES_ENCRYPT);
return data_len; // 返回加密后的数据长度
}
2.3 解码函数
/*
* @brief AES-256-CBC模式解密函数
* @param encrypt 待解密的密文
* decrypt 存储解密后明文
* data_len 明文数据的长度(单位:字节,必须是AES_BLOCK_SIZE的整数倍,即16字节的倍数)
* key 指向原始密钥缓冲区(32字节,AES-256要求)
* iv 初始向量IV(16字节,AES_BLOCK_SIZE固定为16)
* @return int 成功返回加密后的数据长度(与data_len相同),失败返回-1
*/
int aes256_decrypt(unsigned char* encrypt,unsigned char* decrypt,int data_len, unsigned char* key,unsigned char* iv)
{
AES_KEY enc_key;
unsigned char* client_key = key;
memcpy(client_key, plain_data , 16);
memcpy(client_key + 16, plain_data , 16);
if(AES_set_encrypt_key(client_key, 256, &enc_key) < 0)
{
return -1;
}
//创建IV副本,避免被修改
unsigned char iv_copy[AES_BLOCK_SIZE];
memcpy(iv_copy, iv, AES_BLOCK_SIZE);
//# define AES_ENCRYPT 1 //加密
//# define AES_DECRYPT 0 //解密
AES_cbc_encrypt(encrypt, decrypt, data_len, &enc_key, iv_copy, AES_DECRYPT);
return data_len;
}
2.4 PKCS#7 填充函数
此次不展示填充函数与解填充函数
//brief PKCS#7填充函数
unsigned char* pkcs7_pad(unsigned char* data, int data_len, int block_size, int* out_len)
//brief PKCS#7去填充函数
unsigned char* pkcs7_unpad(unsigned char* data, int data_len, int* out_len)
三、主函数
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/aes.h>
int main ()
{
unsigned char plaintext [] = "开心猪扒" ;
int plaintext_len = strlen((char*) plaintext);
unsigned cahr key [] = "开心猪扒00000000000000000000" ;//一个汉字占3个字节
unsigned char iv [] = "开心猪扒0000" ; //偏移:16字节
int padded_len;
unsigned char* padded_plain = pkcs7_pad(plaintext, plaintext_len, AES_BLOCK_SIZE, &padded_len);
unsigned char* ciphertext = (unsigned char*)malloc(padded_len);//分配空间
int encrypt_len = aes256_encrypt(padded_plain, ciphertext, padded_len, key, iv);
//打印密文 (十六进制);打印字符串会乱码,需要用base64编码后再打印字符串才不会乱码
printf("加密后的密文: ");
for (int i = 0; i < encrypt_len; i++)
{
printf("%02x", ciphertext[i]);
}
printf("\n");
unsigned char* decryptedtext = (unsigned char*)malloc(padded_len);
int decrypt_len = aes256_decrypt(ciphertext, decryptedtext, padded_len, key, iv);
//去填充
int unpadded_len;
unsigned char* unpadded_text = pkcs7_unpad(decryptedtext, decrypt_len, &unpadded_len);
// 打印解密结果
printf("解密后的明文: %s\n", unpadded_text);
printf("解密后长度: %d 字节\n", unpadded_len);
// 释放内存
free(padded_plain);
free(ciphertext);
free(decryptedtext);
free(unpadded_text);
}

浙公网安备 33010602011771号