Back

/ 4 min read

Base64编码学习

base64编码原理

base64编码将3个字节的数据(0-255),通过编码表映射到4个字节的(64个可打印字符)数据集合。

编码表

const char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

编码后的字符串长度为:向上取整(源字符串长度 / 3.0) * 4

size_t encode_str_size = ceil(strlen(input_str) / 3.0) * 4

长度是3的倍数的编码

三个字节的base64编码

  1. 3个字节共3*8 = 24个bit。
  2. 24bit划分为4组。
  3. 每一组都充当索引值。
  4. 获取编码表对应索引值的编码值
  5. 写入编码后的字符串。
编码对应的值 三个字节的base64编码

存在余数的编码

当源字符串的长度mod 3后,存在余数[1, 2],此时需要在编码后的字符串中填充(3 - 余数)个数的=。 例如: 存在余数的编码

实现代码(C++)

base64.cpp
const char base64_chars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
void base64_encode(const unsigned char* input, uint32_t len,
unsigned char* output) {
unsigned int input_index = 0, output_index = 0;
unsigned char origin_char_arr[3]; // 必须全初始化为0
unsigned char encode_char_arr[4];
while (len > 0) {
int read_size;
memset(origin_char_arr, 0, 3);
// 读取
for (read_size = 0; read_size < 3 && len > 0; read_size++, len--) {
origin_char_arr[read_size] = *(input + input_index++);
}
encode_char_arr[0] = origin_char_arr[0] >> 2;
encode_char_arr[1] =
((origin_char_arr[0] & 0x03) << 4) + (origin_char_arr[1] >> 4);
encode_char_arr[2] =
((origin_char_arr[1] & 0xf) << 2) + (origin_char_arr[2] >> 6);
encode_char_arr[3] = origin_char_arr[2] & 0x3f;
// 使用encode_char_arr获取编码值
for (int j = 0; j < 4; j++) {
if (j > read_size) {
output[output_index++] = '=';
} else {
output[output_index++] = base64_chars[encode_char_arr[j]];
}
}
}
return;
}

base64解码

知道了编码的原理,我们就能够实现解码了。

  1. 读入4个编码后的字符,遇到=字符结束。
  2. 用编码后的字符找到对应的索引值。
  3. 将4个索引值转换为3个解码字符
  4. 写入解码后的字符串
base64.cpp
// 从 Base64 字符找到对应的索引
int base64_char_index(char c) {
if (c >= 'A' && c <= 'Z') return c - 'A';
if (c >= 'a' && c <= 'z') return c - 'a' + 26;
if (c >= '0' && c <= '9') return c - '0' + 52;
if (c == '+') return 62;
if (c == '/') return 63;
return -1;
}
void base64_decode(const unsigned char* input, uint32_t len,
unsigned char* output) {
unsigned int input_index = 0, output_index = 0;
unsigned char origin_char_arr[3];
unsigned char encode_char_arr[4];
while (len > 0) {
// 取出四个编码后的值
int read_size;
memset(encode_char_arr, 0, 4);
for (read_size = 0; read_size < 4; read_size++, len--) {
int result = base64_char_index(*(input + input_index++));
if (result == -1) break;
encode_char_arr[read_size] = result;
}
// 转换为3字节
origin_char_arr[0] =
(encode_char_arr[0] << 2) + ((encode_char_arr[1] & 0x30) >> 4);
origin_char_arr[1] =
((encode_char_arr[1] & 0x0f) << 4) + ((encode_char_arr[2] & 0x3c) >> 2);
origin_char_arr[2] =
((encode_char_arr[2] & 0x03) << 6) + encode_char_arr[3];
// 写入解密后的字符串 result 取值范围[2, 3, 4]
for (int i = 0; i < read_size - 1; i++) {
*(output + output_index++) = origin_char_arr[i];
}
}
return;
}

汇编实现