注:这篇博客讲解得比较详细,个人认为比较好,转载过来留下次查看.如果侵犯了作者利益,请留言删除
Base64编码说明
Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式。 如果剩下的字符不足3个字节,则用0填充,输出字符使用'=',因此编码后输出的文本末尾可能会出现1或2个'='。
为了保证所输出的编码位可读字符,Base64制定了一个编码表,以便进行统一转换。编码表的大小为2^6=64,这也是Base64名称的由来。
转码过程举例:
3*8=4*6
内存1个字符占8位
转前: s 1 3
先转成ascii:对应 115 49 51
2进制: 01110011 00110001 00110011
6个一组(4组) 011100110011000100110011
然后才有后面的 011100 110011 000100 110011
然后计算机是8位8位的存数 6不够,自动就补两个高位0了
所有有了 高位补0
科学计算器输入 00011100 00110011 00000100 00110011
得到 28 51 4 51
查对下照表 c z E z
Base64编码表
码值 | 字符 | 码值 | 字符 | 码值 | 字符 | 码值 | 字符 | |||
---|---|---|---|---|---|---|---|---|---|---|
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 | / |
C++实现:
base64.h
1 #ifndef _BASE64_HH
2 #define _BASE64_HH
3
4 #ifdef __cplusplus
5 extern "C" {
6 #endif //__cplusplus
7
8 unsigned char* base64Decode(char* pszInput, unsigned int& iReturnSize, bool trimTrailingZeros = true);
9
10 char* base64Encode(char const* origSigned, unsigned iOrigLength);
11
12 #ifdef __cplusplus
13 }
14 #endif //__cplusplus
15
16 #endif //_BASE64_HH
base64.cpp
1 #include "base64.h"
2 #include <string.h>
3
4 static char base64DecodeTable[65];
5 //初始化编码对照表
6 static const char base64Char[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
7
8 char* strDupSize(char const* str)
9 {
10 if (str == NULL) return NULL;
11 size_t len = strlen(str) + 1;
12 char* copy = new char[len];
13
14 return copy;
15 }
16
17 //初始化解码对照表
18 static void initBase64DecodeTable()
19 {
20 for (int i = 0; i < 65; ++i)
21 base64DecodeTable[i] = (char)0x80; // default value: invalid
22
23 for (int i = 'A'; i <= 'Z'; ++i)
24 base64DecodeTable[i] = 0 + (i - 'A');
25 for (int i = 'a'; i <= 'z'; ++i)
26 base64DecodeTable[i] = 26 + (i - 'a');
27 for (int i = '0'; i <= '9'; ++i)
28 base64DecodeTable[i] = 52 + (i - '0');
29 base64DecodeTable[(unsigned char)'+'] = 62;
30 base64DecodeTable[(unsigned char)'/'] = 63;
31 base64DecodeTable[(unsigned char)'='] = 64; //0x40
32 }
33
34 // 解码
35 unsigned char* base64Decode(char* pszInput, unsigned int& iReturnSize, bool trimTrailingZeros)
36 {
37 static bool haveInitedBase64DecodeTable = false;
38 if (!haveInitedBase64DecodeTable)
39 {
40 initBase64DecodeTable();
41 haveInitedBase64DecodeTable = true;
42 }
43
44 unsigned char* pszOutput = new unsigned char[strlen(pszInput)];
45 int k = 0;
46 /*******************************************************************************************
47 *技巧:先减去3 ---in case "pszInput" is not a multiple of 4 bytes (although it should be) *
48 * 个人觉得这里不用做处理,因为编码时候已经做过处理,密文肯定为4的整数倍 *
49 *******************************************************************************************/
50 int const jMax = strlen(pszInput) - 3;
51
52 //将密文四个字节为一组,每组解码为三个字节
53 for (int j = 0; j < jMax; j += 4)
54 {
55 char inTmp[4], outTmp[4];
56 for (int i = 0; i < 4; ++i)
57 {
58 inTmp[i] = pszInput[i+j];
59 outTmp[i] = base64DecodeTable[(unsigned char)inTmp[i]];
60 if ((outTmp[i]&0x40) != 0) //如果遇到'=',将其视为结束字符
61 outTmp[i] = 0x00;
62 }
63
64 pszOutput[k++] = (outTmp[0]<<2) | (outTmp[1]>>4);
65 pszOutput[k++] = (outTmp[1]<<4) | (outTmp[2]>>2);
66 pszOutput[k++] = (outTmp[2]<<6) | outTmp[3];
67 }
68
69 if (trimTrailingZeros)
70 {
71 while (k > 0 && pszOutput[k-1] == '\0')
72 --k;
73 }
74 iReturnSize = k;
75 unsigned char* result = new unsigned char[iReturnSize];
76 memset(result, 0, iReturnSize);
77 memmove(result, pszOutput, iReturnSize);
78 delete[] pszOutput;
79 return result;
80 }
81
82 // 编码
83 char* base64Encode(char const* origSigned, unsigned iOrigLength)
84 {
85 unsigned char const* orig = (unsigned char const*)origSigned;
86 if (orig == NULL)
87 return NULL;
88
89 unsigned const iNumResultBytes = 4*(iOrigLength/3 + (iOrigLength%3 ? 1 : 0));
90 char* result = new char[iNumResultBytes + 1];
91
92 //源码三个字节为一组,编码后将三个字节变为四个字节
93 unsigned i;
94 for (i = 0; i < iOrigLength/3; ++i)
95 {
96 // 取源码的第一个字节的前六位,前面加两个零生成第一个字节
97 result[4*i+0] = base64Char[(orig[3*i]>>2) & 0x3F];
98 // 取源码的第一个字节的后两位和第二个字节的前四位,前面补两个零生成第二个字节
99 result[4*i+1] = base64Char[((orig[3*i]<<4) | (orig[3*i+1]>>4)) & 0x3F];
100 // 取源码的第二个字节的后四位和第三个字节的前两位,前面补两个零生成第三个字节
101 result[4*i+2] = base64Char[((orig[3*i+1]<<2) | (orig[3*i+2]>>6)) & 0x3F];
102 // 取源码的第三个字节的后六位,前面补两个零生成第四个字节
103 result[4*i+3] = base64Char[orig[3*i+2]&0x3F];
104 }
105 //不足三个字节的最后补'='字符,补足三个字节
106 if (iOrigLength%3)
107 {
108 result[4*i+0] = base64Char[(orig[3*i]>>2) & 0x3F];
109 if (iOrigLength%3 == 2)
110 {
111 result[4*i+1] = base64Char[((orig[3*i]<<4) | (orig[3*i+1]>>4))&0x3F];
112 result[4*i+2] = base64Char[(orig[3*i+1]<<2)&0x3C];
113 }
114 else
115 {
116 result[4*i+1] = base64Char[((orig[3*i])<<4)&0x3F];
117 result[4*i+2] = '=';
118 }
119 result[4*i+3] = '=';
120 }
121
122 result[iNumResultBytes] = '\0';
123 return result;
124 }
测试代码main.cpp
1 #include "base64.h"
2 #include <iostream>
3
4 using namespace std;
5
6 int main()
7 {
8 cout << "请输入要转换的字符串(支持中文):" << endl;
9 char szStrOrigin[256];
10 scanf("%s", szStrOrigin);
11 unsigned int iReturnSize;
12 cout << "编码之前字符串:" << szStrOrigin << endl;
13 char *pEncodeStr = base64Encode(szStrOrigin, strlen(szStrOrigin));
14 cout << "编码之后字符串:" << pEncodeStr << endl;
15 unsigned char *pDecodeStr = base64Decode(pEncodeStr, iReturnSize);
16 cout << "解码之后字符串:" << pDecodeStr << endl;
17 system("pause");
18 }
运行结果: