当前位置:   article > 正文

c++调用openssl对文件加解密_c++文件加密库

c++文件加密库

1.OpenSSL简介

OpenSSL库是由C语言实现,整个软件包大概可以分成三个主要的功能部分:密码算法库、SSL协议库以及应用程序。OpenSSL是目前主流的基于密码学的安全开发包,提供的功能相当强大和全面,包括了主要的密码算法、常用的密钥和证书封装管理功能以及SSL协议,并提供了丰富的应用程序供测试或其它目的使用。
  OpenSSL库具有以下优点:1.功能全面,支持大部分主流密码算法、相关标准协议和SSL协议;2.开放源代码,可信任,能根据自己需要进行修改,对技术人员有借鉴和研究的价值;3.具备应用程序,既能直接使用,也可方便地进行二次开发;4.免费,也可用作非商业用途;5.应用广泛且持续更新

openssl库的下载和环境配置这里就不描述了。。。

2.使用 EVP 库实现 DES 和 AES 加密

Openssl EVP(high-level cryptographic functions) 提供了丰富的密码学中的各种函数,包括各种对称算法、摘要算法以及签名/验签算法。下面重点学习使用 DES 和 AES 两种对称加密算法。
  在使用 EVP 库进行对称加密时,通常需要创建一个EVP_CIPHER_CTX 结构体对象,并通过一系列函数对其进行初始化、配置,最终进行加密操作。常用的 EVP_CIPHER_CTX 结构体初始化函数为 EVP_CIPHER_CTX_new() 和 EVP_CIPHER_CTX_init()。
  EVP_CIPHER_CTX_new() 函数在堆上为 EVP_CIPHER_CTX 结构体分配内存空间,并将其所有成员变量初始化为 0;EVP_CIPHER_CTX_init() 函数则用于初始化 EVP_CIPHER_CTX结构体对象的成员变量。
  在加密操作完成后,需要通过调用 EVP_CIPHER_CTX_cleanup 函数释放 EVP_CIPHER_CTX结构体对象的内存空间,以免内存泄漏。下面为EVP库的初始化代码:

  1. EVP_CIPHER_CTX∗ ctx = EVP_CIPHER_CTX_new() ; //结构体对象ctx分配内存空间
  2. EVP_CIPHER_CTX_init( ctx ) ; //初始化结构体对象ctx
  3. EVP_CIPHER_CTX_cleanup( ctx ) ; //释放结构体对象空间

EVP_EncryptUpdate 函数参数详解

在 DES 加密中,常见的 EVP_CIPHER 对象的类型有 EVP_des_ecb(),进行一次 des 的 ecb 模式加密;EVP_des_cbc()、EVP_des_ede3_cbc()。

在 AES 加密中,常见的 EVP_CIPHER 对象类型有:

EVP_aes_128_cbc、EVP_aes_192_cbc、EVP_aes_256_cbc:分别表示使用 AES 算法和 CBC 模式进行加密和解密,密钥长度分别为
128、192 和 256 位。
EVP_aes_128_ecb、EVP_aes_192_ecb、EVP_aes_256_ecb:分别表示使用 AES 算法和 ECB 模式进行加密和解密,密钥长度分别为 128、192 和 256 位。
EVP_aes_128_gcm、EVP_aes_256_gcm:分别表示使用 AES 算法和 GCM 模式进行加密和解密,密钥长度分别为 128 和 256 位。

下面列出两种加密方式

EVP 库的AES 算法的cbc模式

加密:将test.jpg加密另存为test.enc

#include <iostream>
#include <fstream>
#include <string>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>

using namespace std;

#define READ_BUFF 1024
int main()
{
	const unsigned char key[32] = "0123456789abcdef";
	const unsigned char iv[16] = "edcba9876543210";

	//创建一个 EVP_CIPHER_CTX 对象
	EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();

	//选择加密算法
	const EVP_CIPHER *cipher = EVP_aes_256_cbc();

	//初始化加密上下文
	EVP_CIPHER_CTX_init(ctx);

	//设置密钥和偏移量
	EVP_EncryptInit_ex(ctx, cipher, NULL, key, iv);

	std::ifstream in("test.jpg", ifstream::in | ios::binary);
	if (!in.is_open()) {
		std::cerr << "Failed to open file." << std::endl;
		return 1;
	}

	ofstream out("test.enc", ios::binary);
	if (!out) {
		perror("fopen");
		return 1;
	}

	//加密文件内容并写入新文件
	int out_len = 0;
	char inbuf[READ_BUFF];
	char outbuf[READ_BUFF + 520];
	while (!in.eof())
	{
		in.read(inbuf, READ_BUFF);
		int read_len = in.gcount();
		if (!EVP_EncryptUpdate(ctx, (unsigned char*)outbuf, &out_len, (unsigned char*)inbuf, read_len))
		{
			cerr << "EVP_EncryptUpdate failed" << endl;
			return -1;
		}
		out.write(outbuf, out_len);
	}
	in.close();

	if (!EVP_EncryptFinal_ex(ctx, (unsigned char*)outbuf, &out_len))
	{
		cerr << "EVP_EncryptFinal_ex failed" << endl;
		return -1;
	}

	out.write(outbuf, out_len);
	out.close();

	//销毁加密上下文
	EVP_CIPHER_CTX_cleanup(ctx);
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69

解密:将test.enc解密另存为test2.jpg,解密用到的keyiv需同加密一致

#include <iostream>
#include <fstream>
#include <string>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>

using namespace std;

#define READ_BUFF 1024
int main()
{
	const unsigned char key[32] = "0123456789abcdef";
	const unsigned char iv[16] = "edcba9876543210";

	EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
	const EVP_CIPHER *cipher = EVP_aes_256_cbc();

	EVP_CIPHER_CTX_init(ctx);

	EVP_DecryptInit_ex(ctx, cipher, NULL, key, iv);

	// 读取加密文件内容
	std::ifstream in("test.enc", ifstream::in | ios::binary);
	if (!in.is_open()) {
		std::cerr << "failed to open encode file." << std::endl;
		return 1;
	}

	ofstream out("test2.jpg", ios::binary);
	if (!out) {
		cerr << "failed to create decode file!" << endl;
		return -1;
	}


	//解密文件内容并写入
	int out_len = 0;
	char inbuf[READ_BUFF];
	char outbuf[READ_BUFF + 520];
	while (!in.eof())
	{
		in.read(inbuf, READ_BUFF);
		int read_len = in.gcount();
		if (!EVP_DecryptUpdate(ctx, (unsigned char*)outbuf, &out_len, (unsigned char*)inbuf, read_len))
		{
			cerr << "EVP_DecryptUpdate failed" << endl;
			return 1;
		}
		out.write(outbuf, out_len);
	}
	in.close();

	if (!EVP_DecryptFinal_ex(ctx, (unsigned char*)outbuf, &out_len))
	{
		cerr << "EVP_DecryptFinal_ex failed" << endl;
		return 1;
	}
	out.write(outbuf, out_len);
	out.close();

	//销毁解密上下文
	EVP_CIPHER_CTX_cleanup(ctx);
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65

3.DEC加密的ecb模式 (没有EVP方式效率高)

加密封装

/* 
*DES加密 ecb模式
*in_buffer:输入的明文
*in_length:明文长度
*key:密匙
*/
std::string des_encrypt(const char* in_buffer, int in_length,const std::string &key)
{
	std::string cipherText; // 密文

	DES_cblock keyEncrypt;
	memset(keyEncrypt, 0, 8);

	// 构造补齐后的密钥  
	if (key.length() <= 8)
		memcpy(keyEncrypt, key.c_str(), key.length());
	else
		memcpy(keyEncrypt, key.c_str(), 8);

	// 密钥置换  
	DES_key_schedule keySchedule;
	DES_set_key_unchecked(&keyEncrypt, &keySchedule);

	// 循环加密,每8字节一次  
	const_DES_cblock inputText;
	DES_cblock outputText;
	std::vector<unsigned char> vecCiphertext;
	unsigned char tmp[8];

	for (int i = 0; i < in_length / 8; i++)
	{
		memcpy(inputText, in_buffer + i * 8, 8);
		DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_ENCRYPT);
		memcpy(tmp, outputText, 8);

		vecCiphertext.insert(vecCiphertext.end(), tmp, tmp + 8);
	}

	if (in_length % 8 != 0)
	{
		int tmp1 = in_length / 8 * 8;
		int tmp2 = in_length - tmp1;
		memset(inputText, 0, 8);
		memcpy(inputText, in_buffer + tmp1, tmp2);
		DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_ENCRYPT);
		memcpy(tmp, outputText, tmp2);

		vecCiphertext.insert(vecCiphertext.end(), tmp, tmp + tmp2);
	}

	cipherText.clear();
	cipherText.assign(vecCiphertext.begin(), vecCiphertext.end());
	return cipherText;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

解密封装

/*
*DES解密 ecb模式
*in_buffer:输入的密文
*in_length:密文长度
*key:密匙
*/
std::string des_decrypt(const char* in_buffer, int in_length, const std::string &key)
{
	std::string clearText; // 明文  

	DES_cblock keyEncrypt;
	memset(keyEncrypt, 0, 8);

	if (key.length() <= 8)
		memcpy(keyEncrypt, key.c_str(), key.length());
	else
		memcpy(keyEncrypt, key.c_str(), 8);

	DES_key_schedule keySchedule;
	DES_set_key_unchecked(&keyEncrypt, &keySchedule);

	const_DES_cblock inputText;
	DES_cblock outputText;
	std::vector<unsigned char> vecCleartext;
	unsigned char tmp[8];

	for (int i = 0; i < in_length / 8; i++)
	{
		memcpy(inputText, in_buffer + i * 8, 8);
		DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_DECRYPT);
		memcpy(tmp, outputText, 8);

		vecCleartext.insert(vecCleartext.end(), tmp, tmp + 8);
	}

	if (in_length % 8 != 0)
	{
		int tmp1 = in_length / 8 * 8;
		int tmp2 = in_length - tmp1;
		memset(inputText, 0, 8);
		memcpy(inputText, in_buffer + tmp1, tmp2);
		DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_DECRYPT);
		memcpy(tmp, outputText, tmp2);

		vecCleartext.insert(vecCleartext.end(), tmp, tmp + tmp2);
	}

	clearText.clear();
	clearText.assign(vecCleartext.begin(), vecCleartext.end());
	return clearText;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

调用方式

int main(int argc, char **argv)
{
	//加密
	{
		std::ifstream file("test.jpg", ifstream::in | ios::binary);

		if (!file.is_open()) {
			std::cerr << "Failed to open file." << std::endl;
			return 1;
		}

		std::string srcText;
		while (!file.eof()) {
			char buffer[1024];
			file.read(buffer, 1024);
			srcText.append(buffer, file.gcount());
		}
		file.close();

		std::string encryptText;
		std::string encryptHexText;
		std::string decryptText;

		std::string desKey = "12345";
		encryptText = des_encrypt(srcText.data(), srcText.length(), desKey);

		ofstream out("test.enc", ios::binary);
		if (!out) {
			perror("fopen");
			return 1;
		}
		out.write(encryptText.data(), encryptText.length());
		out.close();
	}

	//解密
	{
		// 打开加密文件
		std::ifstream file_out("test.enc", ios::binary);
		if (!file_out.is_open()) {
			std::cerr << "Failed to open file." << std::endl;
			return 1;
		}

		std::string content;
		while (!file_out.eof())
		{
			char buffer[1024];
			file_out.read(buffer, 1024);
			content.append(buffer, file_out.gcount());
		}
		file_out.close();

		decryptText = des_decrypt(content.data(), content.length(), desKey);
		ofstream out2("test2.jpg", ios::binary);
		if (!out) {
			perror("fopen2");
			return 1;
		}
		out2.write(decryptText.data(), decryptText.length());
		out2.close();
	}
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/990902
推荐阅读
  

闽ICP备14008679号