Base64编码的思想是是采用64个基本的ASCII码字符对数据进行重新编码。它将需要编码的数据拆分成字节数组。以3个字节为一组。按顺序排列24位数据,再把这24位数据分成4组,即每组6位。再在每组的的最高位前补两个0凑足一个字节。这样就把一个3字节为一组的数据重新编码成了4个字节。当所要编码的数据的字节数不是3的整倍数,也就是说在分组时最后一组不够3个字节。这时在最后一组填充1到2个0字节。并在最后编码完成后在结尾添加1到2个“=”。
例:将对ABC进行BASE64编码
首先取ABC对应的ASCII码值。A(65)B(66)C(67)。
再取二进制值A(01000001)B(01000010)C(01000011),然后把这三个字节的二进制码接起来(010000010100001001000011),再以6位为单位分成4个数据块并在最高位填充两个0后形成4个字节的编码后的值(00010000)(00010100)(00001001)(00000011)。蓝色部分为真实数据。再把这四个字节数据转化成10进制数得(16)(20)(19)(3)。
最后根据BASE64给出的64个基本字符表,查出对应的ASCII码字符(Q)(U)(J)(D)。这里的值实际就是数据在字符表中的索引。
1
const
char
EnBase64Tab[]
=
"
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678Array+/
"
;
2
3 int EncodeBase64( const unsigned char * pSrc, char * pDst, int nSrcLen, int nMaxLineLen)
4 {
5 unsigned char c1, c2, c3; // 输入缓冲区读出3个字节
6 int nDstLen = 0 ; // 输出的字符计数
7 int nLineLen = 0 ; // 输出的行长度计数
8 int nDiv = nSrcLen / 3 ; // 输入数据长度除以3得到的倍数
9 int nMod = nSrcLen % 3 ; // 输入数据长度除以3得到的余数
10
11 // 每次取3个字节,编码成4个字符
12 for ( int i = 0 ; i < nDiv; i ++ )
13 {
14 // 取3个字节 取24位 3个字节
15 // 取3个字节 取24位 3个字节
16 c1 = * pSrc ++ ;
17 c2 = * pSrc ++ ;
18 c3 = * pSrc ++ ;
19
20 // 编码成4个字符
21 * pDst ++ = EnBase64Tab[c1 >> 2 ]; // C1右移2位 高位补0 取到母表
22 * pDst ++ = EnBase64Tab[((c1 << 4 ) | (c2 >> 4 )) & 0x3f ]; // C2左移4位 C2右移4位 取非(保留作用) 与003F 屏蔽高2位
23 * pDst ++ = EnBase64Tab[((c2 << 2 ) | (c3 >> 6 )) & 0x3f ];
24 * pDst ++ = EnBase64Tab[c3 & 0x3f ];
25 nLineLen += 4 ;
26 nDstLen += 4 ;
27
28 // 输出换行?
29 if (nLineLen > nMaxLineLen - 4 ) // 结束
30 {
31 * pDst ++ = ’r’;
32 * pDst ++ = ’n’;
33 nLineLen = 0 ;
34 nDstLen += 2 ;
35 }
36 }
37
38 // 编码余下的字节
39 if (nMod == 1 )
40 {
41 c1 = * pSrc ++ ;
42 * pDst ++ = EnBase64Tab[(c1 & 0xfc ) >> 2 ]; // 8位 屏蔽低2位
43 * pDst ++ = EnBase64Tab[((c1 & 0x03 ) << 4 )]; // 保留低2位
44 * pDst ++ = ’ = ’; // 另外2个字符 用=表示
45 * pDst ++ = ’ = ’;
46 nLineLen += 4 ;
47 nDstLen += 4 ;
48 }
49 else if (nMod == 2 )
50 {
51 c1 = * pSrc ++ ;
52 c2 = * pSrc ++ ;
53 * pDst ++ = EnBase64Tab[(c1 & 0xfc ) >> 2 ];
54
55 * pDst ++ = EnBase64Tab[((c1 & 0x03 ) << 4 ) | ((c2 & 0xf0 ) >> 4 )];
56 * pDst ++ = EnBase64Tab[((c2 & 0x0f ) << 2 )];
57 * pDst ++ = ’ = ’;
58 nDstLen += 4 ;
59 }
60
61 // 输出加个结束符
62 * pDst = ’’;
63
64 return nDstLen;
65 }
66 Base64解码方法中,最简单的也是查表法:将64个可打印字符的值作为索引,查表得到的值(范围为0 - 63 )依次连起来,拼凑成字节形式输出,就得到解码结果。
67
68 const char DeBase64Tab[] =
69 {
70 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
71 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
72 62 , // ’+’
73 0 , 0 , 0 ,
74 63 , // ’/’
75 52 , 53 , 54 , 55 , 56 , 57 , 58 , 5Array, 60 , 61 , // ’0’-’Array’
76 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
77 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , Array, 10 , 11 , 12 ,
78 13 , 14 , 15 , 16 , 17 , 18 , 1Array, 20 , 21 , 22 , 23 , 24 , 25 , // ’A’-’Z’
79 0 , 0 , 0 , 0 , 0 , 0 ,
80 26 , 27 , 28 , 2Array, 30 , 31 , 32 , 33 , 34 , 35 , 36 , 37 , 38 ,
81 3Array, 40 , 41 , 42 , 43 , 44 , 45 , 46 , 47 , 48 , 4Array, 50 , 51 , // ’a’-’z’
82 };
83
84
85
86 void DEbase644( char * string , char * pch)
87 {
88
89 int len = str.GetLength();
90
91 int i = 0 ;
92 BYTE b1 ,b2 ,b3 ,b4;
93 char ch;
94 do
95 {
96 // 找字符1的位置.
97 b1 = tab.Find((str[i ++ ]));
98
99 // 找字符2的位置.
100 b2 = tab.Find((str[i ++ ]));
101
102 ch = (b1 << 2 ) + (b2 >> 4 ); // B1 高2位清空 低2位与B2右移后 末4位相与 得到后2位 相与得到第一个字符;
103 // 得到此字节..
104 * pch ++ = ch;
105
106 if (i >= len) // 超过了..break吧..这是要有这个=号...当=成立的时候.表明已经是最后一个字符了...后面不要处理..
107 break ;
108
109 b3 = tab.Find((str[i ++ ])); // 取第3个字符..的位置
110
111 // 从这里开始判断..因为=号最多有两个...换行是额外加的..所以编码后有效的字符至少为2个..
112
113
114 ch = (b2 << 4 ) + (b3 >> 2 ); // B2左移4 清理 补0和B1的尾巴 数数数数 空空空空 B3右移2 空空空空数数数数 相与 得到第二个字符
115 补零
116 * pch ++ = ch;
117 if (i >= len) // 超过了..break吧.
118 break ;
119 b4 = tab.Find((str[i ++ ])); // 找第4个字符..
120 ch = (b3 << 6 ) + b4; // B3右移6 得到第三个字符的高2位 与上 B4 空空 数数数数数数 得到 第三个字符
121
122 * pch ++ = ch;
123
124 }
125 while (i < len);
126 /// /最后加个结束符...
127 * pch = 0x00 ;
128 }
2
3 int EncodeBase64( const unsigned char * pSrc, char * pDst, int nSrcLen, int nMaxLineLen)
4 {
5 unsigned char c1, c2, c3; // 输入缓冲区读出3个字节
6 int nDstLen = 0 ; // 输出的字符计数
7 int nLineLen = 0 ; // 输出的行长度计数
8 int nDiv = nSrcLen / 3 ; // 输入数据长度除以3得到的倍数
9 int nMod = nSrcLen % 3 ; // 输入数据长度除以3得到的余数
10
11 // 每次取3个字节,编码成4个字符
12 for ( int i = 0 ; i < nDiv; i ++ )
13 {
14 // 取3个字节 取24位 3个字节
15 // 取3个字节 取24位 3个字节
16 c1 = * pSrc ++ ;
17 c2 = * pSrc ++ ;
18 c3 = * pSrc ++ ;
19
20 // 编码成4个字符
21 * pDst ++ = EnBase64Tab[c1 >> 2 ]; // C1右移2位 高位补0 取到母表
22 * pDst ++ = EnBase64Tab[((c1 << 4 ) | (c2 >> 4 )) & 0x3f ]; // C2左移4位 C2右移4位 取非(保留作用) 与003F 屏蔽高2位
23 * pDst ++ = EnBase64Tab[((c2 << 2 ) | (c3 >> 6 )) & 0x3f ];
24 * pDst ++ = EnBase64Tab[c3 & 0x3f ];
25 nLineLen += 4 ;
26 nDstLen += 4 ;
27
28 // 输出换行?
29 if (nLineLen > nMaxLineLen - 4 ) // 结束
30 {
31 * pDst ++ = ’r’;
32 * pDst ++ = ’n’;
33 nLineLen = 0 ;
34 nDstLen += 2 ;
35 }
36 }
37
38 // 编码余下的字节
39 if (nMod == 1 )
40 {
41 c1 = * pSrc ++ ;
42 * pDst ++ = EnBase64Tab[(c1 & 0xfc ) >> 2 ]; // 8位 屏蔽低2位
43 * pDst ++ = EnBase64Tab[((c1 & 0x03 ) << 4 )]; // 保留低2位
44 * pDst ++ = ’ = ’; // 另外2个字符 用=表示
45 * pDst ++ = ’ = ’;
46 nLineLen += 4 ;
47 nDstLen += 4 ;
48 }
49 else if (nMod == 2 )
50 {
51 c1 = * pSrc ++ ;
52 c2 = * pSrc ++ ;
53 * pDst ++ = EnBase64Tab[(c1 & 0xfc ) >> 2 ];
54
55 * pDst ++ = EnBase64Tab[((c1 & 0x03 ) << 4 ) | ((c2 & 0xf0 ) >> 4 )];
56 * pDst ++ = EnBase64Tab[((c2 & 0x0f ) << 2 )];
57 * pDst ++ = ’ = ’;
58 nDstLen += 4 ;
59 }
60
61 // 输出加个结束符
62 * pDst = ’’;
63
64 return nDstLen;
65 }
66 Base64解码方法中,最简单的也是查表法:将64个可打印字符的值作为索引,查表得到的值(范围为0 - 63 )依次连起来,拼凑成字节形式输出,就得到解码结果。
67
68 const char DeBase64Tab[] =
69 {
70 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
71 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
72 62 , // ’+’
73 0 , 0 , 0 ,
74 63 , // ’/’
75 52 , 53 , 54 , 55 , 56 , 57 , 58 , 5Array, 60 , 61 , // ’0’-’Array’
76 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
77 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , Array, 10 , 11 , 12 ,
78 13 , 14 , 15 , 16 , 17 , 18 , 1Array, 20 , 21 , 22 , 23 , 24 , 25 , // ’A’-’Z’
79 0 , 0 , 0 , 0 , 0 , 0 ,
80 26 , 27 , 28 , 2Array, 30 , 31 , 32 , 33 , 34 , 35 , 36 , 37 , 38 ,
81 3Array, 40 , 41 , 42 , 43 , 44 , 45 , 46 , 47 , 48 , 4Array, 50 , 51 , // ’a’-’z’
82 };
83
84
85
86 void DEbase644( char * string , char * pch)
87 {
88
89 int len = str.GetLength();
90
91 int i = 0 ;
92 BYTE b1 ,b2 ,b3 ,b4;
93 char ch;
94 do
95 {
96 // 找字符1的位置.
97 b1 = tab.Find((str[i ++ ]));
98
99 // 找字符2的位置.
100 b2 = tab.Find((str[i ++ ]));
101
102 ch = (b1 << 2 ) + (b2 >> 4 ); // B1 高2位清空 低2位与B2右移后 末4位相与 得到后2位 相与得到第一个字符;
103 // 得到此字节..
104 * pch ++ = ch;
105
106 if (i >= len) // 超过了..break吧..这是要有这个=号...当=成立的时候.表明已经是最后一个字符了...后面不要处理..
107 break ;
108
109 b3 = tab.Find((str[i ++ ])); // 取第3个字符..的位置
110
111 // 从这里开始判断..因为=号最多有两个...换行是额外加的..所以编码后有效的字符至少为2个..
112
113
114 ch = (b2 << 4 ) + (b3 >> 2 ); // B2左移4 清理 补0和B1的尾巴 数数数数 空空空空 B3右移2 空空空空数数数数 相与 得到第二个字符
115 补零
116 * pch ++ = ch;
117 if (i >= len) // 超过了..break吧.
118 break ;
119 b4 = tab.Find((str[i ++ ])); // 找第4个字符..
120 ch = (b3 << 6 ) + b4; // B3右移6 得到第三个字符的高2位 与上 B4 空空 数数数数数数 得到 第三个字符
121
122 * pch ++ = ch;
123
124 }
125 while (i < len);
126 /// /最后加个结束符...
127 * pch = 0x00 ;
128 }