base64 编解码

base64 基本知识

base64是将二进制数据转换为64个可打印字符的转换方式.

base64 编码

将三字节转为四字节, 如下:

如果不是三的整数倍, 则补0; 根据补的0的个数, 需要在结果字符串的最后面添加'='

实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
std::string base64_encode(uint8_t* in, uint32_t inLen) {
uint8_t arrayIn[3] = {0};
uint8_t arrayOut[4] = {0};

// 判断是否是
uint32_t round = (uint32_t)(inLen / 3);
uint32_t i = 0;
uint32_t j = 0;
std::vector<uint8_t> outRet;
while (i++ < round) {
arrayIn[0] = in[j++];
arrayIn[1] = in[j++];
arrayIn[2] = in[j++];

arrayOut[0] = ((arrayIn[0] & 0xfc) >> 2);
arrayOut[1] = ((arrayIn[0] & 0x03) << 4) + ((arrayIn[1] & 0xf0) >> 4);
arrayOut[2] = ((arrayIn[1] & 0x0f) << 2) + ((arrayIn[2] & 0xc0) >> 6);
arrayOut[3] = (arrayIn[2] & 0x3f);

outRet.push_back(base64_chars[arrayOut[0]]);
outRet.push_back(base64_chars[arrayOut[1]]);
outRet.push_back(base64_chars[arrayOut[2]]);
outRet.push_back(base64_chars[arrayOut[3]]);
}

// 如果不是三的倍数的话
// 处理余下的内容, 如果添加的话, 需要=号
round = (uint32_t)(inLen % 3);
if (1 == round) {
arrayIn[0] = in[inLen - 1];
arrayIn[1] = '\0';

arrayOut[0] = ((arrayIn[0] & 0xfc) >> 2);
arrayOut[1] = ((arrayIn[0] & 0x03) << 4) + ((arrayIn[1] & 0xf0) >> 4);

outRet.push_back(base64_chars[arrayOut[0]]);
outRet.push_back(base64_chars[arrayOut[1]]);
// outRet.push_back('=');
// outRet.push_back('=');
} else if (2 == round) {
arrayIn[0] = in[inLen - 2];
arrayIn[1] = in[inLen - 1];
arrayIn[2] = '\0';

arrayOut[0] = ((arrayIn[0] & 0xfc) >> 2);
arrayOut[1] = ((arrayIn[0] & 0x03) << 4) + ((arrayIn[1] & 0xf0) >> 4);
arrayOut[2] = ((arrayIn[1] & 0x0f) << 2) + ((arrayIn[2] & 0xc0) >> 6);

outRet.push_back(base64_chars[arrayOut[0]]);
outRet.push_back(base64_chars[arrayOut[1]]);
outRet.push_back(base64_chars[arrayOut[2]]);
// outRet.push_back('=');
}

// vec 转 string
std::string out(outRet.begin(), outRet.end());
return (out);
}

base64 解码

将四个字节转换为三个字节, 上面的逆过程.

实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
uint8_t* base64_decode(std::string& in, uint32_t& outLen) {
uint8_t arrayIn[4] = {0};
uint8_t arrayOut[3] = {0};

uint32_t round = (uint32_t)(in.size() / 4);
uint32_t i = 0;
uint32_t j = 0;
std::vector<uint8_t> vecRet;
while (i++ < round) {
arrayIn[0] = static_cast<uint8_t>(base64_chars.find(in[j++]));
arrayIn[1] = static_cast<uint8_t>(base64_chars.find(in[j++]));
arrayIn[2] = static_cast<uint8_t>(base64_chars.find(in[j++]));
arrayIn[3] = static_cast<uint8_t>(base64_chars.find(in[j++]));

// 转换
arrayOut[0] = (arrayIn[0] << 2) + ((arrayIn[1] & 0x30) >> 4);
arrayOut[1] = ((arrayIn[1] & 0x0f) << 4) + ((arrayIn[2] & 0x3c) >> 2);
arrayOut[2] = ((arrayIn[2] & 0x03) << 6) + arrayIn[3];

// 三个数已知
vecRet.push_back(arrayOut[0]);
vecRet.push_back(arrayOut[1]);
vecRet.push_back(arrayOut[2]);
}

// 如果不是4的整数倍, 则其他的单独进行
round = (uint32_t)(in.size() % 4);
if (2 == round) {
// 可转换为一个字符
arrayIn[0] = static_cast<uint8_t>(base64_chars.find(in[in.size() - 2]));
arrayIn[1] = static_cast<uint8_t>(base64_chars.find(in[in.size() - 1]));

arrayOut[0] = (arrayIn[0] << 2) + ((arrayIn[1] & 0x30) >> 4);
vecRet.push_back(arrayOut[0]);
} else if (3 == round) {
// 可转换为2个字符
arrayIn[0] = static_cast<uint8_t>(base64_chars.find(in[in.size() - 3]));
arrayIn[1] = static_cast<uint8_t>(base64_chars.find(in[in.size() - 2]));
arrayIn[2] = static_cast<uint8_t>(base64_chars.find(in[in.size() - 1]));

arrayOut[0] = (arrayIn[0] << 2) + ((arrayIn[1] & 0x30) >> 4);
arrayOut[1] = ((arrayIn[1] & 0x0f) << 4) + ((arrayIn[2] & 0x3c) >> 2);
vecRet.push_back(arrayOut[0]);
vecRet.push_back(arrayOut[1]);
}

outLen = vecRet.size();
uint8_t* ret = new uint8_t[outLen];
for (i = 0; i < outLen; ++i) {
ret[i] = vecRet[i];
}

return (ret);
}