如何使用 AES(openssl) 加密数据?
How to encrypt data using AES(openssl)?
我需要加密我的数据,所以我使用 AES 加密它们。我可以加密短数据 data.But 我需要加密长数据,它不能 work.What 我能做些什么来解决这个问题 problem.This 是我的代码。
#include "cooloi_aes.h"
CooloiAES::CooloiAES()
: MSG_LEN(0)
{
for(int i = 0; i < AES_BLOCK_SIZE; i++)
{
key[i] = 32 + i;
}
}
CooloiAES::~CooloiAES()
{
}
std::string CooloiAES::aes_encrypt(std::string msg)
{
int i = msg.size() / 1024;
MSG_LEN = ( i + 1 ) * 1024;
char in[MSG_LEN];
char out[MSG_LEN];
memset((char*)in,0,MSG_LEN);
memset((char*)out,0,MSG_LEN);
strncpy((char*)in,msg.c_str(),msg.size());
unsigned char iv[AES_BLOCK_SIZE];
for(int j = 0; j < AES_BLOCK_SIZE; ++j)
{
iv[j] = 0;
}
AES_KEY aes;
if(AES_set_encrypt_key((unsigned char*)key, 128, &aes) < 0)
{
return NULL;
}
int len = msg.size();
AES_cbc_encrypt((unsigned char*)in,(unsigned char*)out,len,&aes,iv,AES_ENCRYPT);
std::string encrypt_msg(&out[0],&out[MSG_LEN+16]);
std::cout << std::endl;
return encrypt_msg;
}
std::string CooloiAES::aes_decrypt(std::string msg)
{
MSG_LEN = msg.size();
char in[MSG_LEN];
char out[MSG_LEN+16];
memset((char*)in,0,MSG_LEN);
memset((char*)out,0,MSG_LEN+16);
strncpy((char*)in,msg.c_str(),msg.size());
std::cout << std::endl;
unsigned char iv[AES_BLOCK_SIZE];
for(int j = 0; j < AES_BLOCK_SIZE; ++j)
{
iv[j] = 0;
}
AES_KEY aes;
if(AES_set_decrypt_key((unsigned char*)key, 128, &aes) < 0)
{
return NULL;
}
int len = msg.size();
AES_cbc_encrypt((unsigned char*)in,(unsigned char*)out,len,&aes,iv,AES_DECRYPT);
std::string decrypt_msg = out;
return decrypt_msg;
}
当我加密具有 96 字节的数据时,它会 failed.I 得到这个错误“在抛出 'std::length_error' 的实例后终止调用
什么():basic_string::_S_create
“。但是我不认为这个字符串比最大值长 length.And 我不知道哪里错了。
AES 通常通过将数据分成 16 字节的块来加密数据。如果最后一个块的长度不是 16 字节,则将其填充为 16 字节。维基文章:
除了处理二进制文件时的填充问题和 strncpy 和 (char *) 构造函数的使用之外,您的 encryption/decryption 没有任何问题。如果它不适合所有 16 个字节,则不应加密最后一个数据块。所以你应该实现你自己的填充或者根本不加密最后一个小块,你的代码将被简化为:
string aes_encrypt/decrypt(string msg)
{
unsigned char out[msg.size()];
memcpy((char*)out,msg.data(),msg.size());
AES_cbc_encrypt((unsigned char *)msg.data(),out,msg.size()/16*16,&aes,iv,AES_ENCRYPT **or** AES_DECRYPT);
return string((char *)out, msg.size());
}
总结一下:
- 不要对二进制文件使用 strncpy()
- 不要使用
string s = binary_char_massive;
构造函数
- 如果数据的最后一部分不适合块大小或自行填充,请不要加密它
- 如果未来算法有可能发生变化,请使用 EVP_* openssl API
我需要加密我的数据,所以我使用 AES 加密它们。我可以加密短数据 data.But 我需要加密长数据,它不能 work.What 我能做些什么来解决这个问题 problem.This 是我的代码。
#include "cooloi_aes.h"
CooloiAES::CooloiAES()
: MSG_LEN(0)
{
for(int i = 0; i < AES_BLOCK_SIZE; i++)
{
key[i] = 32 + i;
}
}
CooloiAES::~CooloiAES()
{
}
std::string CooloiAES::aes_encrypt(std::string msg)
{
int i = msg.size() / 1024;
MSG_LEN = ( i + 1 ) * 1024;
char in[MSG_LEN];
char out[MSG_LEN];
memset((char*)in,0,MSG_LEN);
memset((char*)out,0,MSG_LEN);
strncpy((char*)in,msg.c_str(),msg.size());
unsigned char iv[AES_BLOCK_SIZE];
for(int j = 0; j < AES_BLOCK_SIZE; ++j)
{
iv[j] = 0;
}
AES_KEY aes;
if(AES_set_encrypt_key((unsigned char*)key, 128, &aes) < 0)
{
return NULL;
}
int len = msg.size();
AES_cbc_encrypt((unsigned char*)in,(unsigned char*)out,len,&aes,iv,AES_ENCRYPT);
std::string encrypt_msg(&out[0],&out[MSG_LEN+16]);
std::cout << std::endl;
return encrypt_msg;
}
std::string CooloiAES::aes_decrypt(std::string msg)
{
MSG_LEN = msg.size();
char in[MSG_LEN];
char out[MSG_LEN+16];
memset((char*)in,0,MSG_LEN);
memset((char*)out,0,MSG_LEN+16);
strncpy((char*)in,msg.c_str(),msg.size());
std::cout << std::endl;
unsigned char iv[AES_BLOCK_SIZE];
for(int j = 0; j < AES_BLOCK_SIZE; ++j)
{
iv[j] = 0;
}
AES_KEY aes;
if(AES_set_decrypt_key((unsigned char*)key, 128, &aes) < 0)
{
return NULL;
}
int len = msg.size();
AES_cbc_encrypt((unsigned char*)in,(unsigned char*)out,len,&aes,iv,AES_DECRYPT);
std::string decrypt_msg = out;
return decrypt_msg;
}
当我加密具有 96 字节的数据时,它会 failed.I 得到这个错误“在抛出 'std::length_error' 的实例后终止调用 什么():basic_string::_S_create “。但是我不认为这个字符串比最大值长 length.And 我不知道哪里错了。
AES 通常通过将数据分成 16 字节的块来加密数据。如果最后一个块的长度不是 16 字节,则将其填充为 16 字节。维基文章:
除了处理二进制文件时的填充问题和 strncpy 和 (char *) 构造函数的使用之外,您的 encryption/decryption 没有任何问题。如果它不适合所有 16 个字节,则不应加密最后一个数据块。所以你应该实现你自己的填充或者根本不加密最后一个小块,你的代码将被简化为:
string aes_encrypt/decrypt(string msg)
{
unsigned char out[msg.size()];
memcpy((char*)out,msg.data(),msg.size());
AES_cbc_encrypt((unsigned char *)msg.data(),out,msg.size()/16*16,&aes,iv,AES_ENCRYPT **or** AES_DECRYPT);
return string((char *)out, msg.size());
}
总结一下:
- 不要对二进制文件使用 strncpy()
- 不要使用
string s = binary_char_massive;
构造函数 - 如果数据的最后一部分不适合块大小或自行填充,请不要加密它
- 如果未来算法有可能发生变化,请使用 EVP_* openssl API