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编码
- 3个字节共
3*8 = 24
个bit。 - 将
24bit
划分为4组。 - 每一组都充当索引值。
- 获取编码表对应索引值的编码值。
- 写入编码后的字符串。


存在余数的编码
当源字符串的长度mod 3
后,存在余数[1, 2],此时需要在编码后的字符串中填充(3 - 余数)个数的=
。
例如:
实现代码(C++)
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解码
知道了编码的原理,我们就能够实现解码了。
- 读入4个编码后的字符,遇到
=
字符结束。 - 用编码后的字符找到对应的索引值。
- 将4个索引值转换为3个解码字符
- 写入解码后的字符串
// 从 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;}