base 64 编解码器

base 64 编解码

1. base64的编码都是按字符串长度,以每3个8bit的字符为一组,

2. 然后针对每组。首先获取每一个字符的ASCII编码。

3. 然后将ASCII编码转换成8bit的二进制,得到一组3*8=24bit的字节

4. 然后再将这24bit划分为4个6bit的字节,并在每一个6bit的字节前面都填两个高位0。得到4个8bit的字节

5. 然后将这4个8bit的字节转换成10进制。对比Base64编码表 (下表)。得到相应编码后的字符。



实现:

//////////////////////////////////////////////////////////////////////
//
// base64 Encoding/Decoding:
//	 Encoding: String2Base64: unsigned char *  to base64;
//	 Decoding: Base642TString: base64 to unsigned char * .
//
// xuhh
// Dec 11, 2014
//
//////////////////////////////////////////////////////////////////////

#if !defined(_MIME_CODING_H)
#define _MIME_CODING_H

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <utility>
#include <string>
#include <list>
using namespace std;

#if !defined(ASSERT)
#if defined(_DEBUG)
	#include <assert.h>
	#define ASSERT(exp)	assert(exp)
#else
	#define ASSERT(exp)	((void)0)
#endif
#endif

#if defined(_DEBUG) && !defined(DEBUG_NEW)
#define DEBUG_NEW new
#endif

// maximum length of an encoded line (RFC 2045)
#define MAX_MIME_LINE_LEN	76
#define MAX_ENCODEDWORD_LEN	75


//////////////////////////////////////////////////////////////////////
// string to base64

extern unsigned char * String2Base64(const char* str);

//////////////////////////////////////////////////////////////////////
// base64 to string

extern unsigned char * Base642TString(const char* str);

//////////////////////////////////////////////////////////////////////
// CMimeEnvironment - global environment to manage encoding/decoding

class CMimeCodeBase;

#define DECLARE_MIMECODER(class_name) 
	public: static CMimeCodeBase* CreateObject() { return new class_name; }


//////////////////////////////////////////////////////////////////////
// CMimeCodeBase

class CMimeCodeBase
{
public:
	CMimeCodeBase() :
		m_pbInput(NULL),
		m_nInputSize(0),
		m_bIsEncoding(false) {}

public:
	void SetInput(const char* pbInput, int nInputSize, bool bEncoding)
	{
		m_pbInput = (const unsigned char*) pbInput;
		m_nInputSize = nInputSize;
		m_bIsEncoding = bEncoding;
	}
	int GetOutputLength() const
	{
		return m_bIsEncoding ?

GetEncodeLength() : GetDecodeLength(); } int GetOutput(unsigned char* pbOutput, int nMaxSize) { return m_bIsEncoding ?

Encode(pbOutput, nMaxSize) : Decode(pbOutput, nMaxSize); } protected: // overrides virtual int GetEncodeLength() const { return m_nInputSize; } virtual int GetDecodeLength() const { return m_nInputSize; } virtual int Encode(unsigned char* pbOutput, int nMaxSize) const { int nSize = min(nMaxSize, m_nInputSize); ::memcpy(pbOutput, m_pbInput, nSize); return nSize; } virtual int Decode(unsigned char* pbOutput, int nMaxSize) { return CMimeCodeBase::Encode(pbOutput, nMaxSize); } protected: const unsigned char* m_pbInput; int m_nInputSize; bool m_bIsEncoding; }; ////////////////////////////////////////////////////////////////////// // CMimeCodeBase64 - for base64 encoding mechanism class CMimeCodeBase64 : public CMimeCodeBase { public: CMimeCodeBase64() : m_bAddLineBreak(true) {} public: DECLARE_MIMECODER(CMimeCodeBase64) void AddLineBreak(bool bAdd=true) { m_bAddLineBreak = bAdd; } protected: virtual int GetEncodeLength() const; virtual int GetDecodeLength() const; virtual int Encode(unsigned char* pbOutput, int nMaxSize) const; virtual int Decode(unsigned char* pbOutput, int nMaxSize); private: bool m_bAddLineBreak; private: static inline int DecodeBase64Char(unsigned int nCode) { if (nCode >= 'A' && nCode <= 'Z') return nCode - 'A'; if (nCode >= 'a' && nCode <= 'z') return nCode - 'a' + 26; if (nCode >= '0' && nCode <= '9') return nCode - '0' + 52; if (nCode == '+') return 62; if (nCode == '/') return 63; return 64; } }; #endif // !defined(_MIME_CODING_H)




实现文件:



//////////////////////////////////////////////////////////////////////
//
// base64 Encoding/Decoding:
//	 Encoding: String2Base64: unsigned char *  to base64;
//	 Decoding: Base642TString: base64 to unsigned char * .
//
// xuhh
// Dec 11, 2014
//
//////////////////////////////////////////////////////////////////////
#include "MimeCode.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


//////////////////////////////////////////////////////////////////////////
// string to base64
unsigned char* String2Base64(const char * szStr)
{
	CMimeCodeBase64 base64;
	base64.SetInput(szStr, strlen(szStr), true);
	int nLen = base64.GetOutputLength()+1;
	unsigned char* pOutput = new unsigned char[nLen];
	nLen = base64.GetOutput(pOutput, nLen);
	pOutput[nLen] = 0;
	return pOutput;
}


//////////////////////////////////////////////////////////////////////////
// base64 to string

unsigned char *  Base642TString(const char* str)
{
	CMimeCodeBase64 base64;
	base64.SetInput(str, strlen(str), false);
	int len = base64.GetOutputLength()+1;
	unsigned char* pOutput = new unsigned char[len];
	len = base64.GetOutput(pOutput, len);
	pOutput[len] = 0;
	return pOutput;
}

//////////////////////////////////////////////////////////////////////
// CMimeCodeBase64

int CMimeCodeBase64::GetEncodeLength() const
{
	int nLength = (m_nInputSize + 2) / 3 * 4;
	if (m_bAddLineBreak)
		nLength += (nLength / MAX_MIME_LINE_LEN + 1) * 2;
	return nLength;
}

int CMimeCodeBase64::GetDecodeLength() const
{
	return m_nInputSize * 3 / 4 + 2;
}

int CMimeCodeBase64::Encode(unsigned char* pbOutput, int nMaxSize) const
{
	static const char* s_Base64Table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

	unsigned char* pbOutStart = pbOutput;
	unsigned char* pbOutEnd = pbOutput + nMaxSize;
	int nFrom, nLineLen = 0;
	unsigned char chHigh4bits = 0;

	for (nFrom=0; nFrom<m_nInputSize; nFrom++)
	{
		if (pbOutput >= pbOutEnd)
			break;

		unsigned char ch = m_pbInput[nFrom];
		switch (nFrom % 3)
		{
		case 0:
			*pbOutput++ = s_Base64Table[ch >> 2];
			chHigh4bits = (ch << 4) & 0x30;
			break;

		case 1:
			*pbOutput++ = s_Base64Table[chHigh4bits | (ch >> 4)];
			chHigh4bits = (ch << 2) & 0x3c;
			break;

		default:
			*pbOutput++ = s_Base64Table[chHigh4bits | (ch >> 6)];
			if (pbOutput < pbOutEnd)
			{
				*pbOutput++ = s_Base64Table[ch & 0x3f];
				nLineLen++;
			}
		}

		nLineLen++;
		if (m_bAddLineBreak && nLineLen >= MAX_MIME_LINE_LEN && pbOutput+2 <= pbOutEnd)
		{
			*pbOutput++ = '
';
			*pbOutput++ = '
';
			nLineLen = 0;
		}
	}

	if (nFrom % 3 != 0 && pbOutput < pbOutEnd)	// 不足三位。= 补足
	{
		*pbOutput++ = s_Base64Table[chHigh4bits];
		int nPad = 4 - (nFrom % 3) - 1;
		if (pbOutput+nPad <= pbOutEnd)
		{
			::memset(pbOutput, '=', nPad);
			pbOutput += nPad;
		}
	}
	if (m_bAddLineBreak && nLineLen != 0 && pbOutput+2 <= pbOutEnd)
	{
		*pbOutput++ = '
';
		*pbOutput++ = '
';
	}
	return (int)(pbOutput - pbOutStart);
}

int CMimeCodeBase64::Decode(unsigned char* pbOutput, int nMaxSize)
{
	const unsigned char* pbData = m_pbInput;
	const unsigned char* pbEnd = m_pbInput + m_nInputSize;
	unsigned char* pbOutStart = pbOutput;
	unsigned char* pbOutEnd = pbOutput + nMaxSize;

	int nFrom = 0;
	unsigned char chHighBits = 0;

	while (pbData < pbEnd)
	{
		if (pbOutput >= pbOutEnd)
			break;

		unsigned char ch = *pbData++;
		if (ch == '
' || ch == '
')
			continue;
		ch = (unsigned char) DecodeBase64Char(ch);
		if (ch >= 64)				// invalid encoding, or trailing pad '='
			break;

		switch ((nFrom++) % 4)
		{
		case 0:
			chHighBits = ch << 2;
			break;

		case 1:
			*pbOutput++ = chHighBits | (ch >> 4);
			chHighBits = ch << 4;
			break;

		case 2:
			*pbOutput++ = chHighBits | (ch >> 2);
			chHighBits = ch << 6;
			break;

		default:
			*pbOutput++ = chHighBits | ch;
		}
	}

	return (int)(pbOutput - pbOutStart);
}


原文地址:https://www.cnblogs.com/bhlsheji/p/5045194.html