openssl - EVP之对称加密篇



该部分主要用到了EVP_CIPHER和EVP_CIPHER_CTX两个数据结构。其中,EVP_CIPHER包含了用到的加密算法标识、
密钥长度、IV长度和算法的函数指针等信息;EVP_CIPHER_CTX则包含了一个EVP_CIPHER指针、使用的ENGINE以及
需要操作的数据等信息。

用到的主要函数则包括以下一些(如果返回值为int类型,则返回1表示成功,返回0表示失败):
// 初始化及释放相应数据结构

// 初始化EVP_CIPHER_CTX结构体
void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a);
// 清除EVP_CIPHER_CTX结构体
int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a);

// 分配空间,并初始化EVP_CIPHER_CTX结构体
EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
// 释放EVP_CIPHER_CTX结构体
void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *a);

// 执行加解密操作的函数

// 初始化一个加解密操作
// enc为1表示加密,0表示解密,-1表示保持不变
int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx,
                      const EVP_CIPHER *cipher,
                      ENGINE *impl,
                      const unsigned char *key,
                      const unsigned char *iv,
                      int enc);

// 添加并加密
int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl);

// 完成块填充(经过测试,解密需要用EVP_CipherFinal,用EVP_CipherFinal_ex得不到正确的值,不知道什么原因。)
int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);

对于其他的辅助函数,也不再一一介绍。且看下面的例子。

#include "stdafx.h"

#include <openssl/evp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char** argv)
{
	const EVP_CIPHER* evp_cipher = NULL;
	EVP_CIPHER_CTX evp_cipher_ctx;
	char buffer[1024];
	int len = 0;
	int i = 0;

	if (4 != argc)
	{
		printf("usage: cipher \n");
		exit(EXIT_FAILURE);
	}

	// 将加密函数添加到内部表
	OpenSSL_add_all_ciphers();

	// 根据名称获取加密算法,如AES-192-OFB等
	evp_cipher = EVP_get_cipherbyname(argv[1]);
	if (NULL == evp_cipher)
	{
		printf("no such algorithm: %s\n", argv[1]);
		exit(EXIT_FAILURE);
	}

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

	// 初始化加密算法
	if (0 == EVP_CipherInit_ex(&evp_cipher_ctx, evp_cipher, NULL, (const unsigned char *)argv[2], NULL, 1))
	{
		printf("EVP_CipherInit_ex() failed!\n");
		exit(EXIT_FAILURE);
	}

	// 加密
	if (0 == EVP_CipherUpdate(&evp_cipher_ctx, (unsigned char *)buffer, &len, (const unsigned char *)argv[3], strlen(argv[3])))
	{
		printf("EVP_CipherUpdate() failed!\n");
		exit(EXIT_FAILURE);
	}

	//这边还需要EVP_CipherFinal_ex,原作者忽视了.可以参考我的另外一篇<< 利用OpenSSL中EVP封装调用对称加密算法的通用代码>>
	// 显示加密结果
	// int nLastBufLen = 0;
	// EVP_CipherFinal(&evp_cipher_ctx,buffer+len,&nLastBufLen);
	// len += nLastBufLen;


	// 清除加密上下文
	EVP_CIPHER_CTX_cleanup(&evp_cipher_ctx);

	EVP_cleanup();

	return EXIT_SUCCESS;
}


解密的示例:

SymmetricalAlgorithm.h

class CSymmetricalAlgorithm
{
public:
	CSymmetricalAlgorithm();
	virtual ~CSymmetricalAlgorithm();

	/*
	unsigned char* lpszCipehrContent = new unsigned char[nCipherSize];
	unsigned char* lpszOutBuf = new unsigned char[nCipherSize];
	int nRealSize = CSymmetricalAlgorithm::OpensslAes256Ecb(lpszOutBuf,lpszCipehrContent,nCipherSize,(unsigned char*)strKey.c_str());
	//调整数据
	memset(lpszOutBuf + nRealSize, 0, nCipherSize - nRealSize);
	*/

	static int OpensslAes256Ecb(unsigned char* lpuszOutbuf,
								unsigned char* lpuszInbuf,
								unsigned int unBufLen,
								unsigned char* lpuszKey);

	static int DecryptByAes128Ecb(unsigned char* lpuszOutbuf,
								unsigned char* lpuszInbuf,
								unsigned int unBufLen,
								unsigned char* lpuszKey);

	static int OpensslAes256Cbc(unsigned char* lpuszOutbuf,
								unsigned char* lpuszInbuf,
								unsigned int unBufLen,
								unsigned char* lpuszKey,
								unsigned char* lpuszIV);

	static int OpensslAes128Cbc(unsigned char* lpuszOutbuf,
		unsigned char* lpuszInbuf,
		unsigned int unBufLen,
		unsigned char* lpuszKey,
		unsigned char* lpuszIV);

	static int Openssl3DesEcb(unsigned char* lpuszOutbuf,
								unsigned char* lpuszInbuf,
								unsigned int unBufLen,
								unsigned char* lpuszKey);

	static int OpensslDesEcb(unsigned char* lpuszOutbuf,
							unsigned char* lpuszInbuf,
							unsigned int unBufLen,
							unsigned char* lpuszKey);
	
private:
	static int DecryptByOpensslEvpSymmetry(const int nType,
											unsigned char* lpuszOutbuf,
											unsigned char* lpuszInbuf,
											unsigned int unBufLen,
											unsigned char* lpuszKey,
											unsigned char* lpuszIV,
											bool bDiscardDecryptPadding = false
											);

	enum
	{
		AES_256_ECB = 1,
		AES_128_ECB = 2,
		AES_256_CBC = 3,
		AES_128_CBC = 4,
		DES_ECB = 5,
		_3DES_ECB = 6,
	};
};

SymmetricalAlgorithm.cpp

#include "stdafx.h"

#include <openssl/evp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SymmetricalAlgorithm.h"

CSymmetricalAlgorithm::CSymmetricalAlgorithm()
{

}

CSymmetricalAlgorithm::~CSymmetricalAlgorithm()
{
}


int CSymmetricalAlgorithm::OpensslAes256Ecb(unsigned char* lpuszOutbuf,
											unsigned char* lpuszInbuf,
											unsigned int unBufLen,
											unsigned char* lpuszKey)
{
	return DecryptByOpensslEvpSymmetry(AES_256_ECB,
									lpuszOutbuf,
									lpuszInbuf,
									unBufLen,
									lpuszKey,
									NULL,
									true);
}

int CSymmetricalAlgorithm::OpensslAes256Cbc(unsigned char* lpuszOutbuf,
	unsigned char* lpuszInbuf,
	unsigned int unBufLen,
	unsigned char* lpuszKey,
	unsigned char* lpuszIV)
{
	return DecryptByOpensslEvpSymmetry(AES_256_CBC, lpuszOutbuf, lpuszInbuf, unBufLen, lpuszKey, lpuszIV, true);
}

int CSymmetricalAlgorithm::OpensslAes128Cbc(unsigned char* lpuszOutbuf,
											unsigned char* lpuszInbuf,
											unsigned int unBufLen,
											unsigned char* lpuszKey,
											unsigned char* lpuszIV)
{
	return DecryptByOpensslEvpSymmetry(AES_128_CBC, lpuszOutbuf, lpuszInbuf, unBufLen, lpuszKey, lpuszIV, true);
}

int CSymmetricalAlgorithm::Openssl3DesEcb(unsigned char* lpuszOutbuf,
										unsigned char* lpuszInbuf,
										unsigned int unBufLen,
										unsigned char* lpuszKey)
{
	return DecryptByOpensslEvpSymmetry(_3DES_ECB, lpuszOutbuf, lpuszInbuf, unBufLen, lpuszKey, NULL, true);
}


int CSymmetricalAlgorithm::OpensslDesEcb(unsigned char* lpuszOutbuf,
										unsigned char* lpuszInbuf,
										unsigned int unBufLen,
										unsigned char* lpuszKey)
{
	return DecryptByOpensslEvpSymmetry(DES_ECB, lpuszOutbuf, lpuszInbuf, unBufLen, lpuszKey, NULL, true);
}

int CSymmetricalAlgorithm::DecryptByAes128Ecb(unsigned char* lpuszOutbuf,
											unsigned char* lpuszInbuf,
											unsigned int unBufLen,
											unsigned char* lpuszKey)
{
	return DecryptByOpensslEvpSymmetry(AES_128_ECB, lpuszOutbuf, lpuszInbuf, unBufLen, lpuszKey, NULL, true);
}

int CSymmetricalAlgorithm::DecryptByOpensslEvpSymmetry(const int nType,
														unsigned char* lpuszOutbuf,
														unsigned char* lpuszInbuf,
														unsigned int unBufLen,
														unsigned char* lpuszKey,
														unsigned char* lpuszIV,
														bool bDiscardDecryptPadding)
{
	int iOutSize = unBufLen;

	// 将加密函数添加到内部表
	OpenSSL_add_all_ciphers();
	const EVP_CIPHER * cipher = NULL;
	EVP_CIPHER_CTX ctx;
	switch (nType)
	{
	case AES_256_ECB:
	{
		cipher = EVP_aes_256_ecb();
	}
		break;

	case AES_128_ECB:
	{
		cipher = EVP_aes_128_ecb();
	}
		break;

	case AES_256_CBC:
	{
		cipher = EVP_aes_256_cbc();
	}
		break;

	case AES_128_CBC:
	{
		cipher = EVP_aes_128_cbc();
	}
		break;

	case _3DES_ECB:
	{
		cipher = EVP_des_ede3_ecb();
	}
		break;
	case DES_ECB:
	{
		cipher = EVP_des_ecb();
	}
		break;
	}


	// 初始化EVP_CIPHER_CTX结构体
	EVP_CIPHER_CTX_init(&ctx);

	// 初始化一个解密操作
	EVP_CipherInit_ex(&ctx, cipher, NULL, lpuszKey, lpuszIV, false);

	//解密
	EVP_CipherUpdate(&ctx, lpuszOutbuf, &iOutSize, lpuszInbuf, unBufLen);

	//处理最后块填充部分
	int unLastBufLen = 0;

	//这个返回0xC
	EVP_CipherFinal(&ctx, lpuszOutbuf + iOutSize, &unLastBufLen);

	//这个返回0x10
	//EVP_EncryptFinal_ex(&ctx, lpuszOutbuf + iOutSize,&unLastBufLen);
	iOutSize += unLastBufLen;

	EVP_CIPHER_CTX_cleanup(&ctx);
	EVP_cleanup();

	//对称解密,加解密缓冲区大小是一样的.
	if (true == bDiscardDecryptPadding)
	{
		memset(lpuszOutbuf + iOutSize, 0, unBufLen - iOutSize);
	}
	return iOutSize;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值