// AesUtil.h
#ifndef __AES_UTIL_H__
#define __AES_UTIL_H__
#ifdef __cplusplus //告诉编译器,这部分代码按C语言的格式进行编译,而不是C++的
extern "C"{
#endif
string UTIL_aes_cbc_encrypt(const unsigned char *password, unsigned int password_byte_len, const unsigned char *iv, unsigned int iv_byte_len, const unsigned char *data, unsigned int data_len);
int UTIL_aes_cbc_decrypt(const unsigned char *password, unsigned int password_byte_len, const unsigned char *iv, unsigned int iv_byte_len, string encrypted_base64str, unsigned char **out_data, unsigned int *out_data_len);
#ifdef __cplusplus //告诉编译器,这部分代码按C语言的格式进行编译,而不是C++的
}
#endif
#endif /* __AES_UTIL_H__ */
// AesUtil.cpp
#include<string>
using namespace std;
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<openssl/aes.h>
#include<openssl/rsa.h>
#include<openssl/pem.h>
#include<openssl/err.h>
//#include "xxxx_platform_common.h"
//#include "liblicense_log.h"
#include "Base64Util.h"
#include "AesUtil.h"
#define DEBUG_AESUTIL (1)
#define print_ln(log_level, fmt, ...) do {printf("(%s|%d)" fmt "\r\n", __func__, __LINE__, ##__VA_ARGS__); fflush(stdout);} while(0)
#define xxxx_free(a) do {if(a) {free((void *)a); (a) = NULL;}} while(0)
/*****************************************************************
aes加密(cbc模式)
注: password_byte_len 为16字节表示 aes128
password_byte_len 为32字节表示 aes256
参数 : password, 输入参数, 密码
password_byte_len, 输入参数, 密码字节个数
iv, 输入参数, 向量
iv_byte_len, 输入参数, 向量字节个数
data, 输入参数, 待加密数据
data_len, 输入参数, 待加密数据字节个数
out_encrypted, 输出参数, 加密后的密文
out_encrypted_len, 输出参数, 加密后的密文字节个数
return : 0, 成功
-1, 失败
*****************************************************************/
static int _aes_cbc_encrypt(const unsigned char *password, unsigned int password_byte_len, const unsigned char *iv, unsigned int iv_byte_len, const unsigned char *data, unsigned int data_len, unsigned char **out_encrypted, unsigned int *out_encrypted_len)
{
unsigned char tmp_iv[AES_BLOCK_SIZE] = {'\0'};
unsigned char *data_encrypted = NULL;
unsigned char *data_bak = NULL;
unsigned int data_bak_len = 0;
int padding = 0;
AES_KEY aes_key;
if (NULL == password || 0 >= password_byte_len
|| NULL == iv || AES_BLOCK_SIZE != iv_byte_len
|| NULL == data || 0 >= data_len
|| NULL == out_encrypted || NULL == out_encrypted_len
)
{
xxxx_print_ln(xxxx_ERROR, "wrong parameter.");
return -1;
}
if (AES_set_encrypt_key(password, password_byte_len * 8, &aes_key) < 0) {
xxxx_print_ln(xxxx_ERROR, "AES_set_encrypt_key Failed.");
return -1;
}
// PKCS7Padding
if (data_len % (AES_BLOCK_SIZE) > 0) {
padding = AES_BLOCK_SIZE - data_len % (AES_BLOCK_SIZE);
} else {
padding = AES_BLOCK_SIZE;
}
#if DEBUG_AESUTIL
xxxx_print_ln(xxxx_DEBUG, "padding=%d\r\n", padding);
#endif
data_bak_len = data_len + padding;
data_bak = (unsigned char *)calloc(1, data_bak_len);
data_encrypted = (unsigned char *)calloc(1, data_bak_len);
if (NULL == data_bak || NULL == data_encrypted) {
xxxx_print_ln(xxxx_ERROR, "malloc Failed(size=%u).", data_bak_len);
goto __Failed;
}
memcpy((void *)data_bak, (void *)data, data_len);
memcpy((void *)tmp_iv, (void *)iv, AES_BLOCK_SIZE);
for (unsigned int index = 0; index < (unsigned int)padding; index++) {
data_bak[data_len + index] = (char)padding;
}
// AES_cbc_encrypt() 在加密的过程中会修改 iv 的内容,因此 iv 参数不能是一个常量, 而且不能在传递给加密函数后再立马传递给解密函数,必须重新赋值之后再传递给解密函数。
for (unsigned int index = 0; index < data_bak_len / (AES_BLOCK_SIZE); index++) {
AES_cbc_encrypt((const unsigned char*)(data_bak + index * AES_BLOCK_SIZE),
data_encrypted + index * AES_BLOCK_SIZE, AES_BLOCK_SIZE,
&aes_key,
tmp_iv,
AES_ENCRYPT);
}
*out_encrypted = data_encrypted;
*out_encrypted_len = data_bak_len;
//__Success:
xxxx_free(data_bak);
return 0;
__Failed:
xxxx_free(data_bak);
xxxx_free(data_encrypted);
return -1;
}
/*****************************************************************
aes解密(cbc模式)
注: password_byte_len 为16字节表示 aes128
password_byte_len 为32字节表示 aes256
参数 : password, 输入参数, 密码
password_byte_len, 输入参数, 密码字节个数
iv, 输入参数, 向量
iv_byte_len, 输入参数, 向量字节个数
encrypted, 输入参数, 密文
encrypted_len, 输入参数, 密文字节个数
out_data, 输出参数, 原文
out_data_len, 输出参数, 原文字节个数
return : 0, 成功
-1, 失败
*****************************************************************/
static int _aes_cbc_decrypt(const unsigned char *password, unsigned int password_byte_len, const unsigned char *iv, unsigned int iv_byte_len, const unsigned char *encrypted, unsigned int encrypted_len, unsigned char **out_data, unsigned int *out_data_len)
{
unsigned char tmp_iv[AES_BLOCK_SIZE] = {'\0'};;
unsigned char *data_bak = NULL;
char padding = '\0';
AES_KEY aes_key;
if (NULL == password || 0 >= password_byte_len
|| NULL == iv || AES_BLOCK_SIZE != iv_byte_len
|| NULL == encrypted || 0 >= encrypted_len || 0 != encrypted_len % (AES_BLOCK_SIZE)
|| NULL == out_data || NULL == out_data_len
)
{
xxxx_print_ln(xxxx_ERROR, "wrong parameter.");
return -1;
}
if (AES_set_decrypt_key(password, password_byte_len * 8, &aes_key) < 0) {
xxxx_print_ln(xxxx_ERROR, "AES_set_decrypt_key Failed.");
return -1;
}
data_bak = (unsigned char *)calloc(1, encrypted_len);
if (NULL == data_bak) {
xxxx_print_ln(xxxx_ERROR, "malloc Failed(size=%u).", encrypted_len);
goto __Failed;
}
memcpy((void *)tmp_iv, (void *)iv, AES_BLOCK_SIZE);
for (unsigned int index = 0; index < encrypted_len / AES_BLOCK_SIZE; index++) {
AES_cbc_encrypt((const unsigned char*)(encrypted + index * AES_BLOCK_SIZE),
data_bak + index * AES_BLOCK_SIZE, AES_BLOCK_SIZE,
&aes_key,
tmp_iv,
AES_DECRYPT);
}
// 去除 PKCS7Padding
padding = data_bak[encrypted_len - 1];
if (0 >= padding || 16 < padding) {
xxxx_print_ln(xxxx_ERROR, "wrong padding227(padding=0x%02x).", padding);
goto __Failed;
}
for (unsigned int index = 0; index < (unsigned int)padding; index++) {
if (data_bak[encrypted_len - padding + index] != padding) {
xxxx_print_ln(xxxx_ERROR, "wrong padding233(padding=%02X).", padding);
goto __Failed;
} else {
data_bak[encrypted_len - padding + index] = '\0';
}
}
*out_data = data_bak;
*out_data_len = encrypted_len - padding;
//__Success:
return 0;
__Failed:
xxxx_free(data_bak);
return -1;
}
/*****************************************************************
aes加密(cbc模式)
注: password_byte_len 为16字节表示 aes128
password_byte_len 为32字节表示 aes256
参数 : password, 输入参数, 密码
password_byte_len, 输入参数, 密码字节个数
iv, 输入参数, 向量
iv_byte_len, 输入参数, 向量字节个数
data, 输入参数, 待加密数据
data_len, 输入参数, 待加密数据字节个数
return : 长度>0, 成功, 返回加密后的密文的 base64 字符串
长度=0, 失败
*****************************************************************/
string UTIL_aes_cbc_encrypt(const unsigned char *password, unsigned int password_byte_len, const unsigned char *iv, unsigned int iv_byte_len, const unsigned char *data, unsigned int data_len)
{
unsigned char *encrypted_out = NULL;
unsigned int encrypted_len = 0;
int ret = 0;
string encrypted_base64 = "";
if (NULL == password || 0 >= password_byte_len
|| NULL == iv || AES_BLOCK_SIZE != iv_byte_len
|| NULL == data || 0 >= data_len
)
{
xxxx_print_ln(xxxx_ERROR, "wrong parameter.");
return "";
}
ret = _aes_cbc_encrypt(password, password_byte_len, iv, iv_byte_len, data, data_len, &encrypted_out, &encrypted_len);
if (0 != ret) {
return "";
}
string hex = hex_2_string(encrypted_out, encrypted_len);
#if DEBUG_AESUTIL
xxxx_print_ln(xxxx_DEBUG, "UTIL_aes_cbc_encrypt encrypted_len=%u|%lu|%s|", encrypted_len, hex.length(), hex.c_str());
#endif
encrypted_base64 = UTIL_base64_encode((const unsigned char *)encrypted_out, encrypted_len);
xxxx_free(encrypted_out);
return encrypted_base64;
}
/*****************************************************************
aes解密(cbc模式)
注: password_byte_len 为16字节表示 aes128
password_byte_len 为32字节表示 aes256
参数 : password, 输入参数, 密码
password_byte_len, 输入参数, 密码字节个数
iv, 输入参数, 向量
iv_byte_len, 输入参数, 向量字节个数
encrypted_base64str, 输入参数, 密文的 base64 字符串
out_data, 输出参数, 原文
out_data_len, 输出参数, 原文字节个数
return : 0, 成功
-1, 失败
*****************************************************************/
int UTIL_aes_cbc_decrypt(const unsigned char *password, unsigned int password_byte_len, const unsigned char *iv, unsigned int iv_byte_len, string encrypted_base64str, unsigned char **out_data, unsigned int *out_data_len)
{
unsigned char *encrypted = NULL;
unsigned int encrypted_len = 0;
int ret = 0;
if (NULL == password || 0 >= password_byte_len
|| NULL == iv || AES_BLOCK_SIZE != iv_byte_len
|| 0 >= encrypted_base64str.length()
|| NULL == out_data || NULL == out_data_len
)
{
xxxx_print_ln(xxxx_ERROR, "wrong parameter.");
return -1;
}
ret = UTIL_base64_decode(encrypted_base64str, &encrypted, &encrypted_len);
if (0 != ret) {
xxxx_print_ln(xxxx_ERROR, "base64_decode() failed.");
return -1;
}
string hex = hex_2_string(encrypted, encrypted_len);
#if DEBUG_AESUTIL
xxxx_print_ln(xxxx_DEBUG, "UTIL_aes_cbc_encrypt encrypted_len=%u|%lu|%s|", encrypted_len, hex.length(), hex.c_str());
#endif
ret = _aes_cbc_decrypt(password, password_byte_len, iv, iv_byte_len, encrypted, encrypted_len, out_data, out_data_len);
xxxx_free(encrypted);
return ret;
}
#if DEBUG_AESUTIL
int test1()
{
unsigned char *out_data = NULL;
unsigned int out_data_len = 0;
string str = "1234567812345678sunday i CommING, I wanna dry my 卡, thanks";
const char *key = "12345678123456781234567812345678";
const char *iv = "1234567812345678";
xxxx_print_ln(xxxx_DEBUG, "str(origin):%lu|%s|", str.length(), str.c_str());
string encrypted_base64 = UTIL_aes_cbc_encrypt((const unsigned char *)key, strlen(key), (const unsigned char *)iv, strlen(iv), (const unsigned char *)str.c_str(), str.length());
xxxx_print_ln(xxxx_DEBUG, "encrypted_base64=%s|", encrypted_base64.c_str());
if (0 >= encrypted_base64.length()) {
xxxx_print_ln(xxxx_ERROR, "Encrypt Failed.");
return -1;
}
if (0 == UTIL_aes_cbc_decrypt((const unsigned char *)key, strlen(key), (const unsigned char *)iv, strlen(iv), encrypted_base64, &out_data, &out_data_len)) {
//解密后的结果
xxxx_print_ln(xxxx_INFO, "Decrypt Success: %d|%s|", out_data_len, out_data);
} else {
xxxx_print_ln(xxxx_ERROR, "Decrypt Failed.");
}
xxxx_free(out_data);
return 0;
}
int main()
{
test1();
return 0;
}
#endif
g++ Base64Util.cpp AesUtil.cpp -lcrypto