简介
BASE64是目前最常见的编码算法,用于将二进制数据表示为可打印字符串,具体的转换方式由一个64个字符组成的查找表决定,但都是将三个字节(24bit)转换为4个字符(base64中一个字符可以表示6bit的状态,所以也是24bit)
特征
base64主要的特征一个是输出的结果是大量乱七八糟的可打印字符串,事实上如果看到大量乱七八糟的字符串都可以怀疑是base系列,因为如果是其他加密算法基本上不会输出为可打印字符串
另一个特征就是base64算法会带一个64个字符组成的查找表
实现
主要是实现3个8bit对6个4bit的映射,编解码都差不多,下面三张wikipedia的图很好的解释了映射逻辑



如果输入不是3的倍数就对缺的部分补padding,默认标准是补”=”
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
| string encode(string input) { string res = ""; for (size_t i = 0; i < input.size(); i += 3) { uint32_t tmp = 0; int pad = 3; for (size_t j = i; j < i + 3; j++) { if (j < input.size()) { tmp = (tmp << 8) | input[j]; pad--; } else tmp <<= 8; } for (int j = 0; j < 4 - pad; j++) { uint32_t mask = (1 << 6) - 1; res += base64Table[(tmp >> (6 * (3 - j))) & mask]; } while (pad--) res += paddingCode; } return res; }
|
解码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| string decode(string input) { string res = ""; for (size_t i = 0; i < input.size(); i += 4) { uint32_t tmp = 0; for (size_t j = i; j < i + 4 && input[j] != paddingCode; j++) tmp = (tmp << 6) | find(base64Table, input[j]); uint32_t mask = (1 << 8) - 1; if (tmp & (mask << 16)) res += (tmp & (mask << 16)) >> 16; if (tmp & (mask << 8)) res += (tmp & (mask << 8)) >> 8; if (tmp & (mask)) res += (tmp & (mask)); } return res; }
|
完整代码
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 60 61 62 63 64 65 66
| #include <bits/stdc++.h> using namespace std; string base64Table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; char paddingCode = '='; char find(string &table, char ch) { for (size_t i = 0; i < table.size(); i++) { if (table[i] == ch) return (char)i; } return -1; } string encode(string input) { string res = ""; for (size_t i = 0; i < input.size(); i += 3) { uint32_t tmp = 0; int pad = 3; for (size_t j = i; j < i + 3; j++) { if (j < input.size()) { tmp = (tmp << 8) | input[j]; pad--; } else tmp <<= 8; } for (int j = 0; j < 4 - pad; j++) { uint32_t mask = (1 << 6) - 1; res += base64Table[(tmp >> (6 * (3 - j))) & mask]; } while (pad--) res += paddingCode; } return res; } string decode(string input) { string res = ""; for (size_t i = 0; i < input.size(); i += 4) { uint32_t tmp = 0; for (size_t j = i; j < i + 4 && input[j] != paddingCode; j++) tmp = (tmp << 6) | find(base64Table, input[j]); uint32_t mask = (1 << 8) - 1; if (tmp & (mask << 16)) res += (tmp & (mask << 16)) >> 16; if (tmp & (mask << 8)) res += (tmp & (mask << 8)) >> 8; if (tmp & (mask)) res += (tmp & (mask)); } return res; } int main() { string inputCode; getline(cin, inputCode); cout << encode(inputCode) << "\n"; cout << decode(encode(inputCode)); return 0; }
|
reference
wikipedia-base64