一. 编码表
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
(这里有65个字符, 其中64个用于编码, 最后一个用于补齐使用, 这里是'=')
例子: 字符串"abc"的编码过程
明文: a, b c
十六进制: 0x61, 0x62, 0x63 (ASCII值)
二进制: 0110 0001, 0110 0010, 01100011 (把这三个八位的二进制数拆分为四个六位的二进制数)
(8 * 3 = 24 = 6 * 4; 刚刚好是6的整数倍)
(24是8和6的最小公倍数)
二进制: 011000, 010110, 001001, 100011 (这4个值就是编码的索引)
十进制: 24, 22, 9, 35
对应表值: Y, W, J, j
密文: YWJj
------------------------------------------------------------------------------------------
例子: 字符串"abcd"的编码过程
明文: a, b, c, d
十六进制: 0x61, 0x62, 0x63, 0x64
二进制: 0110 0001, 0110 0010, 0110 0011, 0110 0100
二进制: 011000, 010110, 001001, 100011, 011001, 000000
十进制: 24, 22, 9, 35, 25, 0
对应表值: Y, W, J, j, Z, A
密文: YWJjZA==
(明文的长度要是3的倍数, 否则, 如果差1才是3的倍数, 就要在密文后加1个符号(这里是'=');
如果差2才是3的倍数, 就要在密文后加2个符号(这里是'=');
------------------------------------------------------------------------------------------
例子: 字符串"abcde"的编码过程
明文: a, b, c, d, e
十六进制: 0x61, 0x62, 0x63, 0x64, 0x65
二进制: 0110 0001, 0110 0010, 0110 0011, 0110 0100, 0110 0101
二进制: 011000, 010110, 001001, 100011, 011001, 000110, 0101
十进制: 24, 22, 9, 35, 25, 6, 5
对应表值: Y, W, J, j, Z, G, F
密文: YWJjZGF=
(明文的长度要是3的倍数, 否则, 如果差1才是3的倍数, 就要在密文后加1个符号(这里是'=');
如果差2才是3的倍数, 就要在密文后加2个符号(这里是'=');
解码就是其逆过程了(有编码表就好办).
二. 实现
2.1 h文件
//////////////////////////////////////////////////////////////////////////////////////////
// FileName : HYBase64.h
// Author : Cay22
// CreateTime : 2015-02-10 08:08:19
// Purpose : Base64编解码的封装
// Note : 1. 2015-02-10 08:08:19
// : 编码表可以自己定义, 不用标准的.
// Log : 1. 2015-02-10 08:08:19
// : 对Base64编解码, 结合自己的使用习惯, 实现CHYBase64类.
//////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <string>
class CHYBase64
{
public:
CHYBase64();
~CHYBase64();
char* Base64Encode(const char *pData, long lDataLen, long& lTarLen);
char* Base64Decode(const char *pData, long lDataLen, long& lTarLen);
private:
int GetTableIndex(char chCode);
void Release();
char* m_pEncode;
long m_lEncodeLen;
char* m_pDecode;
long m_lDecodeLen;
char* m_chTable;
};
2.2 cpp文件
//////////////////////////////////////////////////////////////////////////////////////////
// FileName : HYBase64.cpp
// Author : Cay22
// CreateTime : 2015-02-10 08:08:19
// Purpose : Base64编解码的封装
// Note : 1. 2015-02-10 08:08:19
// : 编码表可以自己定义, 不用标准的.
// Log : 1. 2015-02-10 08:08:19
// : 对Base64编解码, 结合自己的使用习惯, 实现CHYBase64类.
//////////////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "HYBase64.h"
CHYBase64::CHYBase64()
: m_chTable("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=")
, m_pDecode(0)
, m_lDecodeLen(0)
, m_pEncode(0)
, m_lEncodeLen(0)
{}
CHYBase64::~CHYBase64()
{
Release();
}
void CHYBase64::Release()
{
delete [] m_pEncode;
m_pEncode = 0;
m_lEncodeLen = 0;
delete [] m_pDecode;
m_pDecode = 0;
m_lDecodeLen = 0;
}
// 编码
char* CHYBase64::Base64Encode(const char *pData, long lDataLen, long& lTarLen)
{
int nMultiples = lDataLen / 3;
int nMod = lDataLen % 3;
m_lEncodeLen = nMultiples * 4;
m_lEncodeLen += (0 == nMod) ? 0 : 4;
delete [] m_pEncode;
m_pEncode = new char[m_lEncodeLen + 1];
memset(m_pEncode, 0, m_lEncodeLen + 1);
int i = 0;
lTarLen = 0;
int nTableIndex = 0;
for(i = 0; i < lDataLen; i += 3)
{
// 0
nTableIndex = pData[i] >> 2;
m_pEncode[lTarLen] = m_chTable[nTableIndex];
++lTarLen;
// 1
if(i + 1 < lDataLen)
{
nTableIndex = ((pData[i] & 0x03) << 4) + (pData[i + 1] >> 4);
m_pEncode[lTarLen] = m_chTable[nTableIndex];
++lTarLen;
}
else
{
nTableIndex = ((pData[i + 1] & 0x03) << 4);
m_pEncode[lTarLen] = m_chTable[nTableIndex];
++lTarLen;
m_pEncode[lTarLen] = m_chTable[64];
++lTarLen;
m_pEncode[lTarLen] = m_chTable[64];
++lTarLen;
break;
}
// 2
if(i + 2 < lDataLen)
{
nTableIndex = ((pData[i + 1] & 0x0F) << 2) + (pData[i + 2] >> 6);
m_pEncode[lTarLen] = m_chTable[nTableIndex];
++lTarLen;
}
else
{
nTableIndex = ((pData[i + 1] & 0x0F) << 2);
m_pEncode[lTarLen] = m_chTable[nTableIndex];
++lTarLen;
m_pEncode[lTarLen] = m_chTable[64];
++lTarLen;
break;
}
// 3
nTableIndex = (pData[i + 2] & 0x3F);
m_pEncode[lTarLen] = m_chTable[nTableIndex];
++lTarLen;
}
return m_pEncode;
}
// 当编码表确定以后, 编码的索引也就确定了(这种关系其实是静态的)
// 而在上面的编码表除了静态以外, 还是有规律的.
// A-Z : 0-25
// a-z : 26-51
// 0-9 : 52-61
// +/= : 62, 63, 64
int CHYBase64::GetTableIndex(char chCode)
{
if('+' == chCode)
{
return 62;
}
else if('/' == chCode)
{
return 63;
}
else if('=' == chCode)
{
return 64;
}
else if('9' >= chCode)
{
return chCode - '0' + 52;
}
else if('Z' >= chCode)
{
return chCode - 'A' + 0;
}
else if('z' >= chCode)
{
return chCode - 'a' + 26;
}
return 65;
}
// 解码
char* CHYBase64::Base64Decode(const char *pData, long lDataLen, long& lTarLen)
{
lTarLen = 0;
if(0 != (lDataLen % 4))
{
return 0;
}
int nMultiples = lDataLen / 4;
m_lDecodeLen = nMultiples * 3 + 1;
delete [] m_pDecode;
m_pDecode = new char[m_lDecodeLen];
memset(m_pDecode, 0, m_lDecodeLen);
int i = 0;
int nTableIndex[4];
int nDataLenTemp = nMultiples * 3;
for(i = 0; i < lDataLen; i += 4)
{
nTableIndex[0] = GetTableIndex(pData[i]);
nTableIndex[1] = GetTableIndex(pData[i + 1]);
nTableIndex[2] = GetTableIndex(pData[i + 2]);
nTableIndex[3] = GetTableIndex(pData[i + 3]);
// 0
m_pDecode[lTarLen] = (nTableIndex[0] << 2) + (nTableIndex[1] >> 4);
++lTarLen;
// 1
if(64 != nTableIndex[2])
{
m_pDecode[lTarLen] = ((nTableIndex[1] & 0x0F) << 4) + (nTableIndex[2] >> 2);
++lTarLen;
}
// 2
if(64 != nTableIndex[3])
{
m_pDecode[lTarLen] = ((nTableIndex[2] & 0x03) << 6) + nTableIndex[3];
++lTarLen;
}
}
return m_pDecode;
}
2.3 使用
long lTarLen = 0;
CHYBase64 hyBase64;
std::string strEncodeData = "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.";
hyBase64.Base64Encode("abc", 3, lTarLen);
hyBase64.Base64Encode("abcd", 4, lTarLen);
hyBase64.Base64Encode("abcde", 5, lTarLen);
std::string strDecodeData = hyBase64.Base64Encode(strEncodeData.c_str(), strEncodeData.length(), lTarLen);
std::string strData = hyBase64.Base64Decode(strDecodeData.c_str(), strDecodeData.length(), lTarLen);
参考: http://zh.wikipedia.org/wiki/Base64
三. 扩展
1. 这里的Base64编码就是基于编码表ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789的, 这里都是可视字符. 如果我换一个编码是不是也可以.
2. 这里的Base64编码每6位作为一个编码, 那么我每7位是不是也可以. 7位的话需要2的7次方这么多个编码(128个, 可视的字符没有128个, 我也可以用不可视的编码).
所以我这样实现
1. 随机产生一个位数, 作为编码位数, 例如6位就是64编码了, 7位就是128编码, ...
2. 根据位数, 产生对应长度的随机编码表, 同时产生编码与编码索引的映射.(这里编码表的内容不一定是可视字符).
四. 小结
1. 很明显的一点, Base64编码不是用来加密使用的.
2. 通过Base64编码, 你可以使用可视字符来传递数据.(个人认为这个很好用)
3. 扩展中有一点加密的用处(这里只能是作为简单加密使用), 但是前提是你不能被别人知道你的位数和编码表.
本文详细介绍了Base64编码原理,通过实例展示了编码过程,并探讨了编码表的使用和扩展,包括自定义编码位数和编码表的可能性。同时,提到了Base64编码在数据传递中的应用和其非加密特性。
1193

被折叠的 条评论
为什么被折叠?



