C++封装AES加密类,(ECB + BASE64 + pkcs5padding),直接操纵和返回字符串

前几天需要使用AES加密,其他语言都是现成的类库,new 个实例 + 传个参数 = 搞定!

C++的也有现成的crypto++之类的库,不过太大了,一个库就40多M,没法接受,只能自己寻找资料自力更生(我们就是原始人。。。。)

其实不复杂,算法部分到处都有,但是麻烦就在最后一公里上,怎么弄个字符串传进去再传出来一个字符串,困扰了一天!

首先需要搞清楚几个概念:

AES加密分几种方法:ECB和其他几种;

    ECB的方式不需要IV(初始向量:就是再秘钥基础上再偏移一下更难破解),只需要有秘钥就可以了;

    其他方式都需要有秘钥和IV。

其次,AES加密需要整组整组的加密,也就是说少于16个字符需要补足16个字符,正好等于16个字符需要再额外加上16个字符,这个东西叫padding,有None, pkcs5padding, pkcs7padding等等种类,具体可以看看这哥们的文章,C#和JAVA支持的方式不一样,这也会导致不同语言加的密解不开。。。。

 

最后,加密算法操作的和返回的都是unsigned char数组,而我们需要通常是string 进,string出。而且出来的都是”XDFSLDJFF==“ 这样的东西,这个东西就是BASE64编码后的东西了。

 

我就是把这些麻烦的东西汇总了一下,写个能操纵字符串的类,方便以后的同学们使用!

(我是在这个在线工具对比的结果)

 

具体的工程在我的资源里可以下载

 

感谢@yakovchang2017 @ruyi366 的反馈,我当时只做了16个字符内的,超过16字符确实是会报错,下面的改了下,把StringToHex加一个destlen就好了。

没想到还能帮到一些朋友,如果有需要的朋友直接用下面的代码覆盖aeshelper.cpp就可以了。带来误解也给大家说声抱歉!:)

 

 

#include "AesHelper.h"
#include "aes.h"
#include "zbase64.h"

CAesHelper::CAesHelper(void)
{
}


CAesHelper::~CAesHelper(void)
{
}

void CAesHelper::StringToHex(const char* pSrc, unsigned char* pDest, int nDestLen)
{
	int nSrcLen = 0;
	if( pSrc != 0 )
	{
		nSrcLen = strlen(pSrc);
		memcpy(pDest, pSrc, nSrcLen > nDestLen ? nDestLen : nSrcLen);
	}
	Padding(pDest, nSrcLen > nDestLen ? nDestLen : nSrcLen);
}

void CAesHelper::Padding( unsigned char* pSrc, int nSrcLen )
{
	if( nSrcLen < KEYCODELENGTH )
	{
		unsigned char ucPad = KEYCODELENGTH - nSrcLen;
		for( int nID = KEYCODELENGTH; nID > nSrcLen; --nID )
		{
			pSrc[nID - 1] = ucPad;
		}
	}
}

std::string CAesHelper::Encrypt( std::string strSrc, std::string strKey )
{
	ZBase64 tool;
	aes_context ctx;
	const char* pSrc = 0;
	const char* pTmpSrc = 0;
	unsigned char* pDest = 0;
	unsigned char* pTmpDest = 0;
	int nSrcLen = 0;
	int nDestLen = 0;
	unsigned char buf[KEYCODELENGTH];
	unsigned char key[KEYCODELENGTH];
	StringToHex( strKey.c_str(), key, KEYCODELENGTH );
    aes_set_key( &ctx, key, 128);
	pSrc = strSrc.c_str();
	nSrcLen = strSrc.size();
	nDestLen = (nSrcLen / KEYCODELENGTH) * KEYCODELENGTH + KEYCODELENGTH;
	pDest = new unsigned char[nDestLen];
	memset( pDest, 0, nDestLen );
	pTmpSrc = pSrc;
	pTmpDest = pDest;
	while( (pTmpSrc - pSrc) < nSrcLen )
	{
		StringToHex(pTmpSrc, buf, KEYCODELENGTH);
		aes_encrypt( &ctx, buf, buf );
		memcpy( pTmpDest, buf, KEYCODELENGTH );
		pTmpSrc += KEYCODELENGTH;
		pTmpDest += KEYCODELENGTH;
	}
	if( (pTmpDest - pDest) < nDestLen )	// if the source size % KEYCODELENGTH == 0 then need to add an extra buffer 
	{
		StringToHex(0, buf, KEYCODELENGTH);
		aes_encrypt( &ctx, buf, buf );
		memcpy( pTmpDest, buf, KEYCODELENGTH );
	}
    
	std::string strRet = tool.Encode(pDest, nDestLen);
	delete [] pDest;
	return strRet;
}

std::string CAesHelper::Decrypt( std::string strSrc, std::string strKey )
{
	ZBase64 tool;
	aes_context ctx;
	const char* pSrc = 0;
	const char* pTmpSrc = 0;
	unsigned char* pDest = 0;
	unsigned char* pTmpDest = 0;
	int nSrcLen = 0;
	int nDestLen = 0;
	unsigned char buf[KEYCODELENGTH];
	unsigned char key[KEYCODELENGTH];
	StringToHex(strKey.c_str(), key, KEYCODELENGTH);
    aes_set_key( &ctx, key, 128);
	std::string strSrcHex = tool.Decode(strSrc.c_str(), strSrc.size(), nSrcLen);
	pSrc = strSrcHex.data();
	nDestLen = nSrcLen;
	pDest = new unsigned char[nDestLen];
	memset( pDest, 0, nDestLen );
	pTmpSrc = pSrc;
	pTmpDest = pDest;
	while( (pTmpSrc - pSrc) < nSrcLen )
	{
		memcpy(buf, pTmpSrc, KEYCODELENGTH);
		aes_decrypt( &ctx, buf, buf );
		memcpy(pTmpDest, buf, KEYCODELENGTH);
		pTmpSrc += KEYCODELENGTH;
		pTmpDest += KEYCODELENGTH;
	}
	unsigned char ucTest = 0;
	while(ucTest = *(pTmpDest - 1))
	{
		if( ucTest > 0 && ucTest <= 0x10 )
			*(pTmpDest-1) = 0;
		else
			break;
		pTmpDest--;
	}
	std::string strRet = (char*)pDest;
	delete [] pDest;
	return strRet;
}

 

 

 

 

 

你可能感兴趣的:(备忘录)