用openssl里带的AES加密函数对txt文件进行加密出现的问题

先来说下出现的问题:

我直接复制的cpp里面的文件内容保存成1.txt,然后出来的最终的decrypt.txt文件的内存缺只有
“// Cons ”

下面是测试代码:

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "stdafx.h"
#include <openssl/ssl.h>
#include <openssl/aes.h>
#include <openssl/rsa.h>
#include <openssl/rc4.h>
#pragma comment(lib,"libeay32.lib")
#pragma comment(lib,"ssleay32.lib")
#include "iostream"
using namespace std;
#include "string"
#include "fstream"

#define AES_KEY_BUF_LENGTH 128

#define TEST_KEY "123456789"

#define RELESE(P) if (P) \
{ \
delete P; \
P = NULL; \
}

#define RELESE_ARRAY(P) if (P) \
{ \
delete[] P; \
P = NULL; \
}


// 测试使用aes加密文件算法的例子
int TestAesEncryptTxtFile(std::string in_file_path, std::string out_file_path,
const char *aes_encrypt_key, int in_data_chunk_size = 16)
{
ifstream fin(in_file_path.c_str(), ios::in);
ofstream fout(out_file_path.c_str(), ios::out);

if(!fin)
{
cout << "Can not open fin file." << endl;
return 1;
}
if(!fout)
{
cout << "Can not open fout file." << endl;
return 1;
}

// 得到文件长度
int file_length;
fin.seekg(0, ios::end);
file_length = fin.tellg();
fin.seekg(0, ios::beg);

//用指定密钥对一段内存进行加密,结果放在outbuffer中
unsigned char aes_keybuf[AES_KEY_BUF_LENGTH];
memset(aes_keybuf,0,sizeof(aes_keybuf));
strcpy((char *)aes_keybuf, aes_encrypt_key);
AES_KEY aeskey;
AES_set_encrypt_key(aes_keybuf, 256, &aeskey);

file_length += 1;;
char *in_data = new char[file_length];
memset(in_data, 0, file_length);
char *out_data = new char[file_length];
memset(out_data, 0, file_length);
// while(!fin.eof())
{
fin.read(in_data, file_length);
int test = fin.gcount();
AES_encrypt((const unsigned char *)in_data, (unsigned char *)out_data, &aeskey);
fout.write(out_data, fin.gcount());
};

fout.close();
fin.close();

RELESE_ARRAY(in_data);
RELESE_ARRAY(out_data);

return 0;
}


// 测试使用aes解密文件算法的例子
int TestAesDecryptTxtFile(std::string in_file_path, std::string out_file_path,
const char *rc4_dencrypt_key, int in_data_chunk_size = 16)
{
ifstream fin(in_file_path.c_str(), ios::in);
ofstream fout(out_file_path.c_str(), ios::out);

if(!fin)
{
cout << "Can not open fin file." << endl;
return 1;
}
if(!fout)
{
cout << "Can not open fout file." << endl;
return 1;
}

// 得到文件长度
int file_length;
fin.seekg(0, ios::end);
file_length = fin.tellg();
fin.seekg(0, ios::beg);

//用指定密钥对一段内存进行加密,结果放在outbuffer中
unsigned char aes_keybuf[AES_KEY_BUF_LENGTH];
memset(aes_keybuf,0,sizeof(aes_keybuf));
strcpy((char *)aes_keybuf, rc4_dencrypt_key);
AES_KEY aeskey;
AES_set_decrypt_key(aes_keybuf, 256, &aeskey);

file_length += 1;;
char *in_data = new char[file_length];
memset(in_data, 0, file_length);
char *out_data = new char[file_length];
memset(out_data, 0, file_length);
// while( ! fin.eof() )
{
fin.read(in_data, file_length);
AES_decrypt((unsigned char *)in_data, (unsigned char *)out_data, &aeskey);
fout.write(out_data, fin.gcount());
};

fout.close();
fin.close();

RELESE_ARRAY(in_data);
RELESE_ARRAY(out_data);

return 0;
}



int _tmain(int argc, _TCHAR* argv[])
{
TestAesEncryptTxtFile("1.txt", "2.txt", TEST_KEY);

TestAesDecryptTxtFile("2.txt", "decrypt.txt", TEST_KEY);

return 0;
}
...全文
467 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
引用 1 楼 derekrose 的回复:
调试看看在哪一段字符串丢失了
版主啊,其实是这样的: 其实分析了问题,原来多余出来的符号是txt末尾,比如read读取文件最后剩下5个byte,但是openssl填充到16个bytes在进行的加密。导致最后的乱码。 其实这个问题,也很好解决,到了最后read读取数据,并不能读出满足16byte的时候,直接和加密过的一块写出来就行,而且不用担心,因为前面的数据经过加密后乱码了,你后面再写正常的数据,也是乱码的! 同样的解密部分也一样,这么处理 就Ok了!
  • 打赏
  • 举报
回复
引用 5 楼 u010599631 的回复:
使用AES_encrypt每次只能加密16个字节,可以使用AES_cbc_encrypt进行加密,这个就没有长度限制。
int aes_encrypt(char* in, char* key, char* out)//, int olen)可能会设置buf长度
{
    if(!in || !key || !out) return 0;
    unsigned char iv[AES_BLOCK_SIZE];//加密的初始化向量
    for(int i=0; i<AES_BLOCK_SIZE; ++i)//iv一般设置为全0,可以设置其他,但是加密解密要一样就行
    	iv[i]=0;
    AES_KEY aes;
    if(AES_set_encrypt_key((unsigned char*)key, 128, &aes) < 0)
    {
        return 0;
    }
    int len=strlen(in);
    AES_cbc_encrypt((unsigned char*)in, (unsigned char*)out, len, &aes, iv, AES_ENCRYPT);
    return 1;
}
int aes_decrypt(char* in, char* key, char* out)
{
    if(!in || !key || !out) return 0;
    unsigned char iv[AES_BLOCK_SIZE];//加密的初始化向量
    for(int i=0; i<AES_BLOCK_SIZE; ++i)//iv一般设置为全0,可以设置其他,但是加密解密要一样就行
    	iv[i]=0;
    AES_KEY aes;
    if(AES_set_decrypt_key((unsigned char*)key, 128, &aes) < 0)
    {
        return 0;
    }
    int len=strlen(in);
    AES_cbc_encrypt((unsigned char*)in, (unsigned char*)out, len, &aes, iv, AES_DECRYPT);
    return 1;
}
如果你真的要用AES_encrypt这个加密的话,看下面的代码
int aes_encrypt(char* in, char* key, char* out)//, int olen)
{
    if(!in || !key || !out) return 0;
    AES_KEY aes;
    if(AES_set_encrypt_key((unsigned char*)key, 128, &aes) < 0)
    {
        return 0;
    }
    int len=strlen(in), en_len=0;
    while(en_len<len)//输入输出字符串够长,并且是AES_BLOCK_SIZE的整数倍,需要严格限制
    {
    	AES_encrypt((unsigned char*)in, (unsigned char*)out, &aes);
    	in+=AES_BLOCK_SIZE;
    	out+=AES_BLOCK_SIZE;
    	en_len+=AES_BLOCK_SIZE;
    }
    return 1;
}
int aes_decrypt(char* in, char* key, char* out)
{
    if(!in || !key || !out) return 0;
    AES_KEY aes;
    if(AES_set_decrypt_key((unsigned char*)key, 128, &aes) < 0)
    {
        return 0;
    }
    int len=strlen(in), en_len=0;
    while(en_len<len)
    {
    	AES_decrypt((unsigned char*)in, (unsigned char*)out, &aes);
    	in+=AES_BLOCK_SIZE;
    	out+=AES_BLOCK_SIZE;
    	en_len+=AES_BLOCK_SIZE;
    }
    return 1;
}
建议你看看下面两个链接 http://yuanshuilee.blog.163.com/blog/static/21769727520140942826137/ http://yuanshuilee.blog.163.com/blog/static/217697275201311314185639/
太好了,前几天没人回复,我都不能写出解决方案了! 谢谢! 其实分析了问题,原来多余出来的符号是txt末尾,比如read读取文件最后剩下5个byte,但是openssl填充到16个bytes在进行的加密。导致最后的乱码。 其实这个问题,也很好解决,到了最后read读取数据,并不能读出满足16byte的时候,直接和加密过的一块写出来就行,而且不用担心,因为前面的数据经过加密后乱码了,你后面再写正常的数据,也是乱码的! 同样的解密部分也一样,这么处理 就Ok了!
  • 打赏
  • 举报
回复
引用 6 楼 u010599631 的回复:
AES_encrypt进行加密的时候,你必须保证保证,保存密文的buf,必须是 比原文长度大,同时必须是16的整数倍,当然更大都没问题。因为他是16个字节一组进行加密。 http://www.cnblogs.com/adylee/archive/2007/09/14/893438.html
太好了,前几天没人回复,我都不能写出解决方案了! 谢谢! 其实分析了问题,原来多余出来的符号是txt末尾,比如read读取文件最后剩下5个byte,但是openssl填充到16个bytes在进行的加密。导致最后的乱码。 其实这个问题,也很好解决,到了最后read读取数据,并不能读出满足16byte的时候,直接和加密过的一块写出来就行,而且不用担心,因为前面的数据经过加密后乱码了,你后面再写正常的数据,也是乱码的! 同样的解密部分也一样,这么处理 就Ok了!
u010599631 2014-01-14
  • 打赏
  • 举报
回复
AES_encrypt进行加密的时候,你必须保证保证,保存密文的buf,必须是 比原文长度大,同时必须是16的整数倍,当然更大都没问题。因为他是16个字节一组进行加密。 http://www.cnblogs.com/adylee/archive/2007/09/14/893438.html
u010599631 2014-01-14
  • 打赏
  • 举报
回复
使用AES_encrypt每次只能加密16个字节,可以使用AES_cbc_encrypt进行加密,这个就没有长度限制。
int aes_encrypt(char* in, char* key, char* out)//, int olen)可能会设置buf长度
{
    if(!in || !key || !out) return 0;
    unsigned char iv[AES_BLOCK_SIZE];//加密的初始化向量
    for(int i=0; i<AES_BLOCK_SIZE; ++i)//iv一般设置为全0,可以设置其他,但是加密解密要一样就行
    	iv[i]=0;
    AES_KEY aes;
    if(AES_set_encrypt_key((unsigned char*)key, 128, &aes) < 0)
    {
        return 0;
    }
    int len=strlen(in);
    AES_cbc_encrypt((unsigned char*)in, (unsigned char*)out, len, &aes, iv, AES_ENCRYPT);
    return 1;
}
int aes_decrypt(char* in, char* key, char* out)
{
    if(!in || !key || !out) return 0;
    unsigned char iv[AES_BLOCK_SIZE];//加密的初始化向量
    for(int i=0; i<AES_BLOCK_SIZE; ++i)//iv一般设置为全0,可以设置其他,但是加密解密要一样就行
    	iv[i]=0;
    AES_KEY aes;
    if(AES_set_decrypt_key((unsigned char*)key, 128, &aes) < 0)
    {
        return 0;
    }
    int len=strlen(in);
    AES_cbc_encrypt((unsigned char*)in, (unsigned char*)out, len, &aes, iv, AES_DECRYPT);
    return 1;
}
如果你真的要用AES_encrypt这个加密的话,看下面的代码
int aes_encrypt(char* in, char* key, char* out)//, int olen)
{
    if(!in || !key || !out) return 0;
    AES_KEY aes;
    if(AES_set_encrypt_key((unsigned char*)key, 128, &aes) < 0)
    {
        return 0;
    }
    int len=strlen(in), en_len=0;
    while(en_len<len)//输入输出字符串够长,并且是AES_BLOCK_SIZE的整数倍,需要严格限制
    {
    	AES_encrypt((unsigned char*)in, (unsigned char*)out, &aes);
    	in+=AES_BLOCK_SIZE;
    	out+=AES_BLOCK_SIZE;
    	en_len+=AES_BLOCK_SIZE;
    }
    return 1;
}
int aes_decrypt(char* in, char* key, char* out)
{
    if(!in || !key || !out) return 0;
    AES_KEY aes;
    if(AES_set_decrypt_key((unsigned char*)key, 128, &aes) < 0)
    {
        return 0;
    }
    int len=strlen(in), en_len=0;
    while(en_len<len)
    {
    	AES_decrypt((unsigned char*)in, (unsigned char*)out, &aes);
    	in+=AES_BLOCK_SIZE;
    	out+=AES_BLOCK_SIZE;
    	en_len+=AES_BLOCK_SIZE;
    }
    return 1;
}
建议你看看下面两个链接 http://yuanshuilee.blog.163.com/blog/static/21769727520140942826137/ http://yuanshuilee.blog.163.com/blog/static/217697275201311314185639/
u010599631 2014-01-14
  • 打赏
  • 举报
回复
引用
其实这个问题,也很好解决,到了最后read读取数据,并不能读出满足16byte的时候,直接和加密过的一块写出来就行,而且不用担心,因为前面的数据经过加密后乱码了,你后面再写正常的数据,也是乱码的! 同样的解密部分也一样,这么处理 就Ok了!
个人认为不要这样处理,如果最后的长度不是16的整数倍,那么你填充0给他。 比如我读到2045个字符,那么我申请2048的空间大小,并且清0,然后密文是2048个,解密之后,还原回来的仍然是2045个字符,只要2045后面的字符为0 ,那么我一样可以知道边界。
  • 打赏
  • 举报
回复
引用 1 楼 derekrose 的回复:
调试看看在哪一段字符串丢失了
并没丢失,不进行AES_encrypt,直接写到输出文件,数据是正确的 目前只能怀疑AES_encrypt这个函数,一次性只能处理16个byte。。 不过我上面试了,最后的末尾不好处理。。会有乱码出来
  • 打赏
  • 举报
回复
如果使用每隔16字节做处理,那么很多时候,末尾是这样的:


但是有的时候是正确的

这是测试代码:

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "stdafx.h"
#include <openssl/ssl.h>
#include <openssl/aes.h>
#include <openssl/rsa.h>
#include <openssl/rc4.h>
#pragma comment(lib,"libeay32.lib")
#pragma comment(lib,"ssleay32.lib")
#include "iostream"
using namespace std;
#include "string"
#include "fstream"

#define AES_KEY_BUF_LENGTH 128

#define TEST_KEY "123456789"

#define RELESE(P) if (P) \
{ \
delete P; \
P = NULL; \
}

#define RELESE_ARRAY(P) if (P) \
{ \
delete[] P; \
P = NULL; \
}


// 测试使用aes加密文件算法的例子
int TestAesEncryptTxtFile(std::string in_file_path, std::string out_file_path,
const char *aes_encrypt_key, int in_data_chunk_size = 16)
{
ifstream fin(in_file_path.c_str(), ios::binary | ios::in);
ofstream fout(out_file_path.c_str(), ios::binary | ios::out);

if(!fin)
{
cout << "Can not open fin file." << endl;
return 1;
}
if(!fout)
{
cout << "Can not open fout file." << endl;
return 1;
}

// 得到文件长度
// int file_length;
// fin.seekg(0, ios::end);
// file_length = fin.tellg();
// fin.seekg(0, ios::beg);

//用指定密钥对一段内存进行加密,结果放在outbuffer中
unsigned char aes_keybuf[AES_KEY_BUF_LENGTH];
memset(aes_keybuf,0,sizeof(aes_keybuf));
strcpy((char *)aes_keybuf, aes_encrypt_key);
AES_KEY aeskey;
AES_set_encrypt_key(aes_keybuf, 256, &aeskey);

// file_length += 1;;
char *in_data = new char[in_data_chunk_size + 1];
memset(in_data, 0, in_data_chunk_size + 1);
char *out_data = new char[in_data_chunk_size + 1];
memset(out_data, 0, in_data_chunk_size + 1);
while(!fin.eof())
{
fin.read(in_data, in_data_chunk_size);
int test = fin.gcount();
AES_encrypt((const unsigned char *)in_data, (unsigned char *)out_data, &aeskey);
fout.write(out_data, fin.gcount());
};

fout.close();
fin.close();

RELESE_ARRAY(in_data);
RELESE_ARRAY(out_data);

return 0;
}


// 测试使用aes解密文件算法的例子
int TestAesDecryptTxtFile(std::string in_file_path, std::string out_file_path,
const char *rc4_dencrypt_key, int in_data_chunk_size = 16)
{
ifstream fin(in_file_path.c_str(), ios::binary | ios::in);
ofstream fout(out_file_path.c_str(), ios::binary | ios::out);

if(!fin)
{
cout << "Can not open fin file." << endl;
return 1;
}
if(!fout)
{
cout << "Can not open fout file." << endl;
return 1;
}

// 得到文件长度
// int file_length;
// fin.seekg(0, ios::end);
// file_length = fin.tellg();
// fin.seekg(0, ios::beg);

//用指定密钥对一段内存进行加密,结果放在outbuffer中
unsigned char aes_keybuf[AES_KEY_BUF_LENGTH];
memset(aes_keybuf,0,sizeof(aes_keybuf));
strcpy((char *)aes_keybuf, rc4_dencrypt_key);
AES_KEY aeskey;
AES_set_decrypt_key(aes_keybuf, 256, &aeskey);

// file_length += 1;;
char *in_data = new char[in_data_chunk_size + 1];
memset(in_data, 0, in_data_chunk_size + 1);
char *out_data = new char[in_data_chunk_size + 1];
memset(out_data, 0, in_data_chunk_size + 1);
while(!fin.eof())
{
fin.read(in_data, in_data_chunk_size);
AES_decrypt((unsigned char *)in_data, (unsigned char *)out_data, &aeskey);
fout.write(out_data, fin.gcount());
};

fout.close();
fin.close();

RELESE_ARRAY(in_data);
RELESE_ARRAY(out_data);

return 0;
}



int _tmain(int argc, _TCHAR* argv[])
{
TestAesEncryptTxtFile("1.txt", "2.txt", TEST_KEY);

TestAesDecryptTxtFile("2.txt", "decrypt.txt", TEST_KEY);

return 0;
}
  • 打赏
  • 举报
回复
补上一个设置成binary读取的测试(一样的问题):

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "stdafx.h"
#include <openssl/ssl.h>
#include <openssl/aes.h>
#include <openssl/rsa.h>
#include <openssl/rc4.h>
#pragma comment(lib,"libeay32.lib")
#pragma comment(lib,"ssleay32.lib")
#include "iostream"
using namespace std;
#include "string"
#include "fstream"

#define AES_KEY_BUF_LENGTH 128

#define TEST_KEY "123456789"

#define RELESE(P) if (P)		\
{								\
	delete P;					\
	P = NULL;					\
}

#define RELESE_ARRAY(P) if (P)  \
{								\
	delete[] P;					\
	P = NULL;					\
}


// 测试使用aes加密文件算法的例子
int TestAesEncryptTxtFile(std::string in_file_path, std::string out_file_path, 
						  const char *aes_encrypt_key, int in_data_chunk_size = 16)
{
	ifstream fin(in_file_path.c_str(), ios::binary | ios::in);
	ofstream fout(out_file_path.c_str(), ios::binary | ios::out);

	if(!fin)
	{
		cout << "Can not open fin file." << endl;
		return 1;
	}
	if(!fout)
	{
		cout << "Can not open fout file." << endl;
		return 1;
	}

	// 得到文件长度
	int file_length;
	fin.seekg(0, ios::end);
	file_length = fin.tellg();
	fin.seekg(0, ios::beg);

	//用指定密钥对一段内存进行加密,结果放在outbuffer中
	unsigned char aes_keybuf[AES_KEY_BUF_LENGTH];
	memset(aes_keybuf,0,sizeof(aes_keybuf));
	strcpy((char *)aes_keybuf, aes_encrypt_key);
	AES_KEY aeskey;
	AES_set_encrypt_key(aes_keybuf, 256, &aeskey);

	file_length += 1;;
	char *in_data  = new char[file_length];
	memset(in_data, 0, file_length);
	char *out_data = new char[file_length];
	memset(out_data, 0, file_length);
	//	while(!fin.eof())
	{
		fin.read(in_data, file_length);
		int test = fin.gcount();
		AES_encrypt((const unsigned char *)in_data, (unsigned char *)out_data, &aeskey);
		fout.write(out_data, fin.gcount());
	};

	fout.close();
	fin.close();

	RELESE_ARRAY(in_data);
	RELESE_ARRAY(out_data);

	return 0;
}


// 测试使用aes解密文件算法的例子
int TestAesDecryptTxtFile(std::string in_file_path, std::string out_file_path, 
						  const char *rc4_dencrypt_key, int in_data_chunk_size = 16)
{
	ifstream fin(in_file_path.c_str(), ios::binary | ios::in);
	ofstream fout(out_file_path.c_str(), ios::binary | ios::out);

	if(!fin)
	{
		cout << "Can not open fin file." << endl;
		return 1;
	}
	if(!fout)
	{
		cout << "Can not open fout file." << endl;
		return 1;
	}

	// 得到文件长度
	int file_length;
	fin.seekg(0, ios::end);
	file_length = fin.tellg();
	fin.seekg(0, ios::beg);

	//用指定密钥对一段内存进行加密,结果放在outbuffer中
	unsigned char aes_keybuf[AES_KEY_BUF_LENGTH];
	memset(aes_keybuf,0,sizeof(aes_keybuf));
	strcpy((char *)aes_keybuf, rc4_dencrypt_key);
	AES_KEY aeskey;
	AES_set_decrypt_key(aes_keybuf, 256, &aeskey);

	file_length += 1;;
	char *in_data  = new char[file_length];
	memset(in_data, 0, file_length);
	char *out_data = new char[file_length];
	memset(out_data, 0, file_length);
	//	while( ! fin.eof() )
	{
		fin.read(in_data, file_length);
		AES_decrypt((unsigned char *)in_data, (unsigned char *)out_data, &aeskey);
		fout.write(out_data, fin.gcount());
	};

	fout.close();
	fin.close();

	RELESE_ARRAY(in_data);
	RELESE_ARRAY(out_data);

	return 0;
}



int _tmain(int argc, _TCHAR* argv[])
{
	TestAesEncryptTxtFile("1.txt", "2.txt", TEST_KEY);

	TestAesDecryptTxtFile("2.txt", "decrypt.txt", TEST_KEY);

	return 0;
}
derekrose 2014-01-09
  • 打赏
  • 举报
回复
调试看看在哪一段字符串丢失了

65,187

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧