C++使用OpenSSL实现AES-256-CBC加密解密实例----亲测OK
摘自:https://blog.csdn.net/GerZhouGengCheng/article/details/106103039
// 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