使用AES加密-复用前人的智慧
一. 头文件如下所示:
uint32_t encrypt_get_size(uint32_t size);
int32_t encrypt(uint8_t* data,
uint32_t data_size,
uint8_t* enc_data,
uint32_t* enc_data_size);
int32_t decrypt(uint8_t* enc_data,
uint32_t enc_data_size,
uint8_t** data,
uint32_t* data_size);
二. 加密代码:
AES算法以16个字节对齐,如果不是16个字节,需要补齐,
在这里AES_BLOCK_SIZE就是16,在openssl/aes.h里面有定义
typedef struct
{
uint32_t data_size;
uint32_t key[AES_BLOCK_SIZE];
uint32_t iv[AES_BLOCK_SIZE];
uint8_t data[AES_BLOCK_SIZE];
}
uint32_t encrypt_get_size(uint32_t size)
{
uint32_t block_num = 0;
uint32_t en_data_size = 0;
if ((size % AES_BLOCK_SIZE) != 0)
{
block_num = size / AES_BLOCK_SIZE + 1;
en_data_size = block_num * AES_BLOCK_SIZE;
}
else
{
en_data_size = size;
}
}
int32_t encrypt(uint8_t* data,
uint32_t data_size,
uint8_t* enc_data,
uint32_t* enc_data_size)
{
AES_KEY key;
int ret = 0;
uint32_t length = 0;
uint32_t block_num = 0;
enc_data_t* obj = NULL;
obj = (enc_data_t*) enc_data;
obj->data_len = data_size;
memcpy(obj->data, data, data_size);
ret = AES_set_encrypt_key(obj->key, 128, &key);
if (ret != 0)
{
printf("AES_set_encrypt_key failed %d \n", ret);
return ret;
}
if ((data_size % AES_BLOCK_SIZE) != 0)
{
block_num = data_size / AES_BLOCK_SIZE + 1;
length = block_num * AES_BLOCK_SIZE;
}
else
{
length = data_size;
}
AES_cbc_encrypt(obj->data, obj->data, length, &key, obj->iv, AES_ENCRYPT);
*enc_data_size = sizeof(enc_data_t) + length;
return ret;
}
三. 解密代码:
int decrypt(uint8_t* enc_data,
uint32_t enc_data_size,
uint8_t** data,
uint32_t* data_size)
{
AES_KEY key;
int ret = 0;
enc_data_t* obj = NULL;
uint8_t* tmp_data = NULL;
obj = (enc_data_t*) enc_data;
const uint32_t total_size = obj->data_len + sizeof(enc_data_t);
ret = AES_set_decrypt_key(obj->key, 128, &key);
if (ret != 0)
{
printf("AES_set_encrypt_key failed %d \n", ret);
return ret;
}
AES_cbc_encrypt(obj->data,
obj->data,
(enc_data_size - sizeof(enc_data_t)),
&key,
obj->iv,
AES_DECRYPT);
tmp_data = (uint8_t*) malloc(obj->data_len);
if (NULL == tmp_data)
{
printf("allocate failed \n");
return -1;
}
memset(tmp_data, 0, obj->data_len);
memcpy(tmp_data, obj->data, obj->data_len);
if (NULL == *data)
{
*data = tmp_data;
}
*data_size = obj->data_len;
return 0;
}
四.代码的智慧分析:
在这里有一个问题,如果加密解密在不同的场景,就是说需要把加密数据保存成一个文件,
然后,从这个秘文文件中,把数据解密出来;但是这里存在的问题就是,你需要知道加密前
数据的大小,有人说,这个可以保存在一个全局的变量里面;但是会有这样的场景,你可能在
开机的时候就需要加载这个密文的数据取解密,这个时候怎么办呢?一般人的结局方法如下:
保存加密数据的时候,以数组追加的形式保存两段数据,第一段数据是用一个固定长度的数据(4个字节),来存储原始数据的长度,第二段数据就是加密的秘文数据;载读取解析加密数据的时候也是这样分为两个步骤,第一步是读取一个固定长度(4个字节)的数据,就是原始数据的大小,即解密后数据的大小,第二步,就是读取保存的秘文。这种方法也是可行的,就是比较麻烦。其实好的方案就是采用上面的方法,内部定义一段数据结构,通过解析固定的数据结构来做