假装异步加载中...
11 Apr 2013

Base64加密解密算法的C/C++代码实现

今天再次用到了base64编解码,以前看过,现在又有点陌生了,上网查了下,然后用c++实现了下,在此记录下,以备将来查用。

介绍

百度百科维基百科说的很清楚,我就不罗嗦了

用途

Base64算法不是为了防止内容被人破解而使用的算法, 因为破解Base64太容易了, 就是简单的字符替换。 Base64还有个不好的地方,就是加密后, 长度会变成。 那我们为何还要使用Base64 呢?因为Base64可以把乱七八糟的二进制转化为字符串,这个特性在很多地方很有用。

实现(c++)

// Base64.h
#ifndef __BASE64_H__
#define __BASE64_H__

#include <string>
using std::string;

class CBase64
{
public:
	static bool Encode(const string& strIn,string& strOut);
	static bool Decode(const string& strIn,string& strOut,bool fCheckInputValid = false);
};

#endif
// Base64.cpp
#include "base64.h"

static const char encode_map[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static char decode_map[256];
static void initBase64DecodeMap()
{
	memset(decode_map,-1,sizeof(decode_map));
	for (int i = 'A'; i <= 'Z'; ++i) decode_map[i] = 0 + (i - 'A');
	for (int i = 'a'; i <= 'z'; ++i) decode_map[i] = 26 + (i - 'a');
	for (int i = '0'; i <= '9'; ++i) decode_map[i] = 52 + (i - '0');
	decode_map[(unsigned char)'+'] = 62;
	decode_map[(unsigned char)'/'] = 63;
	decode_map[(unsigned char)'='] = 0;
}

bool CBase64::Encode(const string& strIn,string& strOut)
{
	size_t nInLen = strIn.length();
	size_t numOrig24BitValues = nInLen/3;
	bool havePadding = (nInLen != numOrig24BitValues*3);
	bool havePadding2 = (nInLen == numOrig24BitValues*3 + 1);
	size_t numResultBytes = 4*(numOrig24BitValues + havePadding);
	strOut.clear();
	for (size_t i = 0; i < numOrig24BitValues; ++i) 
	{
		strOut.append(1,encode_map[(strIn[3*i] >> 2) & 0x3F]);
		strOut.append(1,encode_map[((strIn[3*i] << 4) & 0x30) | ((strIn[3*i+1] >> 4) & 0x0F)]);
		strOut.append(1,encode_map[((strIn[3*i+1] << 2) & 0x3C) | ((strIn[3*i+2] >> 6) & 0x03)]);
		strOut.append(1,encode_map[strIn[3*i+2] & 0x3F]);

	}

	if (havePadding) 
	{
		size_t i = numOrig24BitValues;
		strOut.append(1,encode_map[(strIn[3*i] >> 2) & 0x3F]);
		if (havePadding2)
		{
			strOut.append(1,encode_map[((strIn[3*i] << 4) & 0x30) | ((strIn[3*i+1] >> 4) & 0x0F)]);
			strOut.append(1,'=');
		} 
		else 
		{
			strOut.append(1,encode_map[((strIn[3*i] << 4) & 0x30) | ((strIn[3*i+1] >> 4) & 0x0F)]);
			strOut.append(1,encode_map[((strIn[3*i+1] << 2) & 0x3C) | ((strIn[3*i+2] >> 6) & 0x03)]);
		}
		strOut.append(1,'=');
	}

	return true;
}

bool CBase64::Decode(const string& strIn,string& strOut,bool fCheckInputValid/* = false*/)
{
	size_t nInlen = strIn.length();
	if (nInlen < 4 || (nInlen % 4) != 0)
	{
		return false;
	}

	static bool bInit = false;
	if (!bInit)
	{
		initBase64DecodeMap();
		bInit = true;
	}

	if (fCheckInputValid)
	{
		for (size_t i = 0; i < nInlen; ++i)
		{
			if (decode_map[(unsigned char)strIn[i]] == -1)
			{
				return false;
			}
		}
	}
	size_t nOutLen = (nInlen * 3) / 4;
	string strTmpOut;
	strTmpOut.resize(nOutLen);
	size_t nLoopLen = nOutLen / 3;
	for (size_t i = 0; i < nLoopLen;++i)
	{
		strTmpOut[i*3] = ((decode_map[strIn[i*4]] << 2) & 0xFC) | ((decode_map[strIn[i*4+1]] >> 4) & 0x03);
		strTmpOut[i*3+1] = ((decode_map[strIn[i*4+1]] << 4) & 0xF0) | ((decode_map[strIn[i*4+2]] >> 2) & 0x0F);
		strTmpOut[i*3+2] = ((decode_map[strIn[i*4+2]] << 6) & 0xC0) | (decode_map[strIn[i*4+3]] & 0x3F);
	}

	if (strIn[nInlen - 1] == '=')
	{
		nOutLen--;
		if (strIn[nInlen - 2] == '=')
		{
			nOutLen--;
		}
	}
	const char* pData = strTmpOut.data();
	strOut.clear();
	strOut.append(pData,pData + nOutLen);
	return true;
}

获取

获取文件及更新:Github

PS: 在电子邮件中,根据RFC 822规定,每76个字符,还需要加上一个回车换行。这个是MIME中的规定,base64只是一种编码格式,并不是所有的应用都需要遵守这个原则。