Base64 其实不能算是真正加密解密的安全算法,因为这个东西大家都知道怎么解密,就没有意思了。不过登陆邮件服务器的时候,登陆密码要使用BASE64 加密,因此我将算法描述如下:
在这个表中0x1a,对应的是:'a'。
cPP 文件
Base64 核心算法:
明文: hello
对应的Ascii: 0x68, 0x65, 0x6c, 0x6c, 0x6f
二进制: 01101000 01100101 011001101 011001101 01101111
将明文按照每三个字节,变成4个字节的原则进行变化,首先将二进制中每次拿出6个bit 形成一个密码表索引,通过这个索引转到密文。
例如上面的:
二进制: 01101000 01100101 011001101 011001101 01101111
6bit 变化: 011010 000110 010101 1001101 0110011 010110 111100(后面不足的上两个0)
十六进制: 0x1a, 0x06, 0x15, 0x4d, 0x33, 0x16, 0x3c
那么在这个十六进制作为索引在下面的加密表中查处对应的密文,
- const unsigned char C_Base64::CodeTable[] =
- {
- 'A', 'B', 'C',
- 'D', 'E', 'F',
- 'G', 'H', 'I',
- 'J', 'K', 'L',
- 'M', 'N', 'O',
- 'P', 'Q', 'R',
- 'S', 'T', 'U',
- 'V', 'W', 'X',
- 'Y', 'Z', 'a',
- 'b', 'c', 'd',
- 'e', 'f', 'g',
- 'h', 'i', 'j',
- 'k', 'l', 'm',
- 'n', 'o', 'p',
- 'q', 'r', 's',
- 't', 'u', 'v',
- 'w', 'x', 'y',
- 'z', '0', '1',
- '2', '3', '4',
- '5', '6', '7',
- '8', '9', '+',
- '/'
- };
一次查出为aGVsbG8,很明显不够4的整数倍,那么再补一个特殊字符"=",因此密文:
aGVsbG8=
就是说在不够的情况下,可能要补一个或者二个特殊的字符"=",凑够4的整数倍。
因此C++的实现源码如下:
- // _Base64.h: interface for the C_Base64 class.
- //
- //
- #if !defined(AFX__BASE64_H__D718F826_7489_43E8_B5EF_64ED8EBBCD7E__INCLUDED_)
- #define AFX__BASE64_H__D718F826_7489_43E8_B5EF_64ED8EBBCD7E__INCLUDED_
- #if _MSC_VER > 1000
- #pragma once
- #endif // _MSC_VER > 1000
- #pragma warning(disable: 4786)
- #include <map>
- using namespace std;
- class C_Base64
- {
- public:
- C_Base64();
- virtual ~C_Base64();
- bool EncodeBase64(const unsigned char *Source, unsigned int nNum, unsigned char *Dest, unsigned int &nNumout);
- bool DecodeBase64(const unsigned char *Source, unsigned int nNum, unsigned char *Dest, unsigned int &nNumout);
- public:
- typedef unsigned char BYTE;
- typedef map<BYTE, BYTE> DECODETYPE;
- private:
- bool Initial();
- private:
- static const unsigned char CodeTable[] ;
- DECODETYPE DecodeTable;
- };
- #endif // !defined(AFX__BASE64_H__D718F826_7489_43E8_B5EF_64ED8EBBCD7E__INCLUDED_)
- // _Base64.cpp: implementation of the C_Base64 class.
- //
- //
- #include "stdafx.h"
- #include "_Base64.h"
- #include <assert.h>
- //
- // Construction/Destruction
- //
- const unsigned char C_Base64::CodeTable[] =
- {
- 'A', 'B', 'C',
- 'D', 'E', 'F',
- 'G', 'H', 'I',
- 'J', 'K', 'L',
- 'M', 'N', 'O',
- 'P', 'Q', 'R',
- 'S', 'T', 'U',
- 'V', 'W', 'X',
- 'Y', 'Z', 'a',
- 'b', 'c', 'd',
- 'e', 'f', 'g',
- 'h', 'i', 'j',
- 'k', 'l', 'm',
- 'n', 'o', 'p',
- 'q', 'r', 's',
- 't', 'u', 'v',
- 'w', 'x', 'y',
- 'z', '0', '1',
- '2', '3', '4',
- '5', '6', '7',
- '8', '9', '+',
- '/'
- };
- bool C_Base64::Initial()
- {
- BYTE nIndex = 'A';
- BYTE nCount = 0;
- // 'A' - 'Z'
- for (nIndex = 'A'; nIndex <= 'Z'; ++nIndex)
- {
- DecodeTable.insert(C_Base64::DECODETYPE::value_type(nIndex, nCount));
- ++nCount;
- }
- // 'a' - 'z'
- for (nIndex = 'a'; nIndex <= 'z'; ++nIndex)
- {
- DecodeTable.insert(C_Base64::DECODETYPE::value_type(nIndex, nCount));
- ++nCount;
- }
- // '0' - '9'
- for (nIndex = '0'; nIndex <= '9'; ++nIndex)
- {
- DecodeTable.insert(C_Base64::DECODETYPE::value_type(nIndex, nCount));
- ++nCount;
- }
- // '+'
- DecodeTable.insert(C_Base64::DECODETYPE::value_type('+', nCount));
- ++nCount;
- // '/'
- DecodeTable.insert(C_Base64::DECODETYPE::value_type('/', nCount));
- return true;
- }
- C_Base64::C_Base64()
- {
- Initial();
- }
- C_Base64::~C_Base64()
- {
- }
- bool C_Base64::EncodeBase64(const unsigned char *Source, unsigned int nNum,
- unsigned char *Dest, unsigned int &nNumout)
- {
- unsigned int nGroup = nNum / 3;
- const BYTE *pSource = Source;
- for (unsigned int nIndex = 0; nIndex < nGroup; ++nIndex)
- {
- BYTE source1 = *(pSource + nIndex * 3);
- BYTE source2 = *(pSource + nIndex * 3 + 1);
- BYTE source3 = *(pSource + nIndex * 3 + 2);
- BYTE code1 = (source1 >> 2) & 0x3f;
- BYTE code2 = ((source1 << 4) | (source2 >> 4)) & 0x3f;
- BYTE code3 = ((source2 << 2) | (source3 >> 6)) & 0x3f;
- BYTE code4 = source3 & 0x3f;
- *(Dest + nIndex * 4) = CodeTable[code1];
- *(Dest + nIndex * 4 + 1) = CodeTable[code2];
- *(Dest + nIndex * 4 + 2) = CodeTable[code3];
- *(Dest + nIndex * 4 + 3) = CodeTable[code4];
- }
- unsigned int nRest = nNum % 3;
- if ( 1 == nRest)
- {
- BYTE source1 = *(pSource + (nGroup) * 3 + 0);
- BYTE code1 = (source1 >> 2) & 0x3f;
- BYTE code2 = (source1 << 4) & 0x3f;
- BYTE code3 = '=';
- BYTE code4 = '=';
- *(Dest + nGroup * 4 + 0) = CodeTable[code1];
- *(Dest + nGroup * 4 + 1) = CodeTable[code2];
- *(Dest + nGroup * 4 + 2) = code3;
- *(Dest + nGroup * 4 + 3) = code4;
- }
- else if (2 == nRest)
- {
- BYTE source1 = *(pSource + (nGroup) * 3 + 0);
- BYTE source2 = *(pSource + (nGroup) * 3 + 1);
- BYTE code1 = (source1 >> 2) & 0x3f;
- BYTE code2 = ((source1 << 4) | (source2 >> 4)) & 0x3f;
- BYTE code3 = (source2 << 2) & 0x3f;
- BYTE code4 = '=';
- *(Dest + nGroup * 4 + 0) = CodeTable[code1];
- *(Dest + nGroup * 4 + 1) = CodeTable[code2];
- *(Dest + nGroup * 4 + 2) = CodeTable[code3];
- *(Dest + nGroup * 4 + 3) = code4;
- }
- nNumout = nGroup * 4;
- if (nRest != 0)
- {
- nNumout += 4;
- }
- return true;
- }
- bool C_Base64::DecodeBase64(const unsigned char *Source,
- unsigned int nNum, unsigned char *Dest,
- unsigned int &nNumout)
- {
- assert(nNum % 4 == 0);
- if (nNum % 4 != 0)
- {
- return false;
- }
- unsigned int nGroup = nNum / 4;
- unsigned int nIndex = 0;
- const BYTE *pSource = Source;
- for (nIndex = 0; nIndex < nGroup - 1; ++nIndex)
- {
- BYTE code1 = *(pSource + nIndex * 4 + 0);
- BYTE code2 = *(pSource + nIndex * 4 + 1);
- BYTE code3 = *(pSource + nIndex * 4 + 2);
- BYTE code4 = *(pSource + nIndex * 4 + 3);
- BYTE dcode1 = DecodeTable[code1];
- BYTE dcode2 = DecodeTable[code2];
- BYTE dcode3 = DecodeTable[code3];
- BYTE dcode4 = DecodeTable[code4];
- *(Dest + nIndex * 3 + 0) = (dcode1 << 2 | ((dcode2 >> 4) & 0x3)) & 0xff;
- *(Dest + nIndex * 3 + 1) = ((dcode2 << 4) | (dcode3 >> 2)) & 0xff;
- *(Dest + nIndex * 3 + 2) = ((dcode3 << 6) | (dcode4 & 0x3f))& 0xff;
- }
- unsigned int OutBytes = 3 * nGroup;
- // last group data
- {
- BYTE code1 = *(pSource + (nGroup - 1) * 4 + 0);
- BYTE code2 = *(pSource + (nGroup - 1) * 4 + 1);
- BYTE code3 = *(pSource + (nGroup - 1) * 4 + 2);
- BYTE code4 = *(pSource + (nGroup - 1) * 4 + 3);
- if (code3 == '=' && code4 == '=')
- {
- BYTE dcode1 = DecodeTable[code1];
- BYTE dcode2 = DecodeTable[code2];
- *(Dest + (nGroup - 1) * 3 + 0) = (dcode1 << 2 | ((dcode2 >> 4) & 0x3)) & 0xff;
- OutBytes -= 2;
- }
- else if (code4 == '=')
- {
- BYTE dcode1 = DecodeTable[code1];
- BYTE dcode2 = DecodeTable[code2];
- BYTE dcode3 = DecodeTable[code3];
- *(Dest + (nGroup - 1) * 3 + 0) = (dcode1 << 2 | ((dcode2 >> 4) & 0x3)) & 0xff;
- *(Dest + (nGroup - 1) * 3 + 1) = ((dcode2 << 4) | (dcode3 >> 2)) & 0xff;
- OutBytes -= 1;
- }
- }
- nNumout = OutBytes;
- return true;
- }