用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;
}
...全文
453 11 打赏 收藏 转发到动态 举报
写回复
用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
  • 打赏
  • 举报
回复
调试看看在哪一段字符串丢失了
我将领大家全面分析HLS(M3U8),包括直播、点播、多码流、AES加密、切片、等。您将亲自动手来操练,搭建环境、学习理论,分析总结:m3u8+Nginx+OpenSSL+FFmpeg具体包括包括如下:HLS直播协议详解FFmpeg+Nginx+VLC打造M3U8点播FFmpeg+Nginx+VLC打造M3U8直播FFmpeg:M3U8的多码流自适应Win10快速安装OpenSSL(不用编译源码)FFmpeg:M3U8的AES加密 -------------------------------------------------------------------音视频是一门很复杂的技术,涉及的概念、原理、理论非常多,很多初学者不学基础理论,而是直接做项目,往往会看到c/c++的代码时一头雾水,不知道代码到底是什么意思,这是为什么呢? 因为没有学习音视频的基础理论,就比如学习英语,不学习基本单词,而是天天听英语新闻,总也听不懂。所以呢,一定要认真学习基础理论,然后再学习播放器、转码器、非编、流媒体直播、视频监控、等等。 梅老师从事音视频与流媒体行业18年;曾在永新视博、中科大洋、百度、美国Harris广播事业部等公司就职,经验丰富;曾亲手主导广电直播全套项目,精通h.264/h.265/aac,曾亲自参与百度app上的网页播放器等实战产品。 目前全身心自主创业,主要聚焦音视频+流媒体行业,精通音视频加密、流媒体在线转码快编等热门产品。
0、此例程调试环境 运行uname -a的结果如下: Linux freescale 3.0.35-2666-gbdde708-g6f31253 #1 SMP PREEMPT Thu Nov 30 15:45:33 CST 2017 armv7l GNU/Linux 简称2017 armv7l GNU/Linux 1、openssl 直接处理AES的API 在openssl/aes.h定义。是基本的AES库函数接口,可以直接调用,但是那个接口是没有填充的。而如果要与Java通信,必须要有填充模式。所以看第2条。 2、利用openssl EVP接口 在openssl/evp.h中定义。在这个接口中提供的AES是默认是pkcs5padding方式填充方案。 3、注意openssl新老版本的区别 看如下这段 One of the primary differences between master (OpenSSL 1.1.0) and the 1.0.2 version is that many types have been made opaque, i.e. applications are no longer allowed to look inside the internals of the structures. The biggest impact on applications is that: 1)You cannot instantiate these structures directly on the stack. So instead of: EVP_CIPHER_CTX ctx; you must instead do: EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); .... EVP_CIPHER_CTX_free(ctx); 2)You must only use the provided accessor functions to access the internals of the structure. 4、注意加密的内容是数据不限制是否为字符串 openssl接口加密的是数据,不限制是否为字符串,我看到有些人在加密时使用strlen(),来获取要加密的长度,如果是对字符串加密的话没有问题,如果不是字符串的话,用它获取的长度是到第一个0处,因为这个函数获取的是字符串长度,字符串是以零为终止的。 5、在调用EVP_EncryptFinal_ex时不要画蛇添足 正常加解密处理过程,引用网友的代码如下,经测试正确。 int kk_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, unsigned char *iv, unsigned char *ciphertext) { EVP_CIPHER_CTX *ctx; int len; int ciphertext_len; ctx = EVP_CIPHER_CTX_new(); EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv); //EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, iv); EVP_EncryptUpdate(ctx, ciphertext, &len;, plaintext, plaintext_len); ciphertext_len = len; EVP_EncryptFinal_ex(ctx, ciphertext + len, &len;); ciphertext_len += len; EVP_CIPHER_CTX_free(ctx); return ciphertext_len; } int kk_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, unsigned char *iv, unsigned char *plaintext) { EVP_CIPHER_CTX *ctx; int len; int plaintext_len; ctx = EVP_CIPHER_CTX_new(); EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv); //EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, iv); EVP_DecryptUpdate(ctx, plaintext, &len;, ciphertext, ciphertext_len); plaintext_len = len; EVP_DecryptFinal_ex(ctx, plaintext + len, &len;); plaintext_len += len; EVP_CIPHER_CTX_free(ctx); return plaintext_len; } 我看到有人提供的代码在加密长度正好是16字节的整数倍时特意不去调用EVP_EncryptFinal_ex,这实在是画蛇添足啊,不论什么情况下,最后一定要调用EVP_EncryptFinal_ex一次,然后结束加密过程。 6、Base64陷阱 如果用到了base64,要注意如下: 1)base64算法是将3个字节变成4个可显示字符。所以在如果数据长度不是3字节对齐时,会补0凑齐。 2)在解密时先要解base64,再解AES。在解base64后,要减掉补上的0。算法就去查看base64后的字符串尾处有几个=号,最多是2个,如果正好要加密的数据是3的倍数,不需要补0,那么base64后的数据尾处就没有=,如果补了1个0,就有一个=号。 算法如下: int encode_str_size = EVP_EncodeBlock(base64, en, el); int length = EVP_DecodeBlock(base64_out, base64, encode_str_size ); //EVP_DecodeBlock内部同样调用EVP_DecodeInit + EVP_DecodeUpdate + Evp_DecodeFinal实现,但是并未处理尾部的'='字符,因此结果字符串长度总是为3的倍数 while(base64[--encode_str_size] == '=') length--; 算法网友提供,测试正确。

64,682

社区成员

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

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