Base64的根本实质是将8位2进制码转换成6位2进制码,也就是由8bits转换为6bits。
其原理如下:
1、base64编解码原理
将数据编码成BASE64编码时,以3字节数据为一组,转换为24bit的二进制数,将24bit的二进制数分成四组,每组6bit。对于每一组,得到一个数字:0-63。然后根据这个数字查表即得到结果。表如下:
Value | Char | Value | Char | Value | Char | Value | Char |
0 | A | 16 | Q | 32 | g | 48 | w |
1 | B | 17 | R | 33 | h | 49 | x |
2 | C | 18 | S | 34 | i | 50 | y |
3 | D | 19 | T | 35 | j | 51 | z |
4 | E | 20 | U | 36 | k | 52 | 0 |
5 | F | 21 | V | 37 | l | 53 | 1 |
6 | G | 22 | W | 38 | m | 54 | 2 |
7 | H | 23 | X | 39 | n | 55 | 3 |
8 | I | 24 | Y | 40 | o | 56 | 4 |
9 | J | 25 | Z | 41 | p | 57 | 5 |
10 | K | 26 | a | 42 | q | 58 | 6 |
11 | L | 27 | b | 43 | r | 59 | 7 |
12 | M | 28 | c | 44 | s | 60 | 8 |
13 | N | 29 | d | 45 | t | 61 | 9 |
14 | O | 30 | e | 46 | u | 62 | + |
15 | P | 31 | f | 47 | v | 63 | / |
这里面每个字符都有自己的值,而这些值都是6位2进制转换而来的10进制数。
编码的时候,通过获取每6位2进制并转换成10进制数,取得表中的所对应的字符。
解码的时候同样的,也是通过将上表的对应的字符的Value值对应的写入ASCII表结构、顺序相同字符数组中,并且在字符数组中,不是在上表中的字符用-1值代替。
BASE64填充:在不够的情况下在右边加0。
编码过程如下:
1)得到16进制数据: 30 82 02
2)得到二进制数据: 00110000 10000010 00000010
3)每6bit分组: 001100 001000 001000 000010
4)得到数字: 12 8 8 2
5)根据查表得到结果 : M I I C
BASE64填充:在不够的情况下在右边加0。
有三种情况:
1) 输入数据比特数是24的整数倍(输入字节为3字节整数倍),则无填充;
2) 输入数据最后编码的是1个字节(输入数据字节数除3余1),即8比特,则需要填充2个"==",因为要补齐6比特,需要加2个00;
3)输入数据最后编码是2个字节(输入数据字节数除3余2),则需要填充1个"=",因为补齐6比特,需要加一个00。
base64解码是其编码过程的逆过程。解码时,将base64编码根据表展开,根据有几个等号去掉结尾的几个00,然后每8比特恢复即可。
2.代码实现:
编码代码:
string Base64Encode(const string &s)
{
int lenString = s.length();
string StrSource = s;
const char *chKey = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
for(int i =0; i != lenString ; ++i)
if( StrSource[i] < 0 || StrSource[i] > 127 )
{
cout<<"ERROR!"<<endl;
exit(0);
}
int nLoop=0;
if( lenString % 3 == 0 )
nLoop=lenString;
else
nLoop=lenString-3;
cout<<StrSource<<endl;
string EnCodeStr(lenString*4/3+4,'\0');
int n=0,i=0;
int b[3]={0};
for( i = 0 ; i < nLoop; i += 3 )
{
//用int类型存储char类型的ASCII码值
b[0]=StrSource[i];
b[1]=StrSource[i+1];
b[2]=StrSource[i+2];
EnCodeStr[n]=chKey[(b[0] & 0xfc)>>2];
EnCodeStr[n+1]=chKey[(b[0] & 0x03)<<4 | (b[1]&0xf0)>>4];
EnCodeStr[n+2]=chKey[(b[1] & 0x0f)<<2 | (b[2]&0xc0)>>6];
EnCodeStr[n+3]=chKey[(b[2] & 0x3f)];
n+=4;
}
int j = lenString % 3;
switch(j)
{
case 0:
EnCodeStr[n]='\0';
break;
case 1:
b[0]=StrSource[i];
EnCodeStr[n]=chKey[(b[0] & 0xfc)>>2];
EnCodeStr[n+1]=chKey[(b[0] & 0x03)<<4 | ((0 & 0xf0)>>4)];
EnCodeStr[n+2]='=';
EnCodeStr[n+3]='=';
EnCodeStr[n+4]='\0';
break;
case 2:
b[0]=StrSource[i];
b[1]=StrSource[i+1];
EnCodeStr[n]=chKey[(b[0] & 0xfc)>>2];
EnCodeStr[n+1]=chKey[(b[0] & 0x03)<<4 | (b[1] & 0xf0)>>4];
EnCodeStr[n+2]=chKey[(b[1] & 0x0f)<<4 | ((0 & 0xc0)>>6)];
EnCodeStr[n+3]='=';
EnCodeStr[n+4]='\0';
break;
}
return EnCodeStr.c_str();
};
未完待续...