Base64原理
Base64 是一種基於 64 個可打印字符來表示二進制數據的表示方法。由於 2^6 = 64,所以每 6 個比特爲一個單元,對應某個可打印字符。3 個字節有 24 個比特,對應於 4 個 Base64 單元,即 3 個字節可由 4 個可打印字符來表示。它可用來作爲電子郵件的傳輸編碼。在 Base64 中的可打印字符包括字母 A-Z
、a-z
、數字 0-9
和 +
, /
。
Base64 常用於在通常處理文本數據的場合,表示、傳輸、存儲一些二進制數據,包括 MIME 的電子郵件及XML的一些複雜數據。
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 | / |
示例:將 Man
編碼得到 TWFu
如果要編碼的字節數不能被 3 整除,最後會多出 1 個或 2 個字節,那麼可以使用下面的方法進行處理:先使用 0 字節值在末尾補足,使其能夠被 3 整除,然後再進行 Base64 的編碼。在編碼後的 Base64 文本後加上一個或兩個 = 號,代表補足的字節數。也就是說,當最後剩餘兩個八位(待補足)字節(2 個 byte)時,最後一個 6 位的 Base64 字節塊有四位是 0 值,最後附加上兩個等號;如果最後剩餘一個八位(待補足)字節( 1 個 byte)時,最後一個 6 位的 base 字節塊有兩位是 0 值,最後附加一個等號。
C++ 代碼
base64 編解碼的 c++ 代碼如下所示,代碼來源:github
// https://github.com/ReneNyffenegger/cpp-base64
#include "base64.h"
#include <iostream>
// there are 64 characters
static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
static inline bool is_base64(unsigned char c) {
return (isalnum(c) || (c == '+') || (c == '/'));
}
std::string base64_encode(const char *bytes_to_encode, unsigned int in_len) {
std::string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3]; // store 3 byte of bytes_to_encode
unsigned char char_array_4[4]; // store encoded character to 4 bytes
while (in_len--) {
char_array_3[i++] = *(bytes_to_encode++); // get three bytes (24 bits)
if (i == 3) {
// eg. we have 3 bytes as ( 0100 1101, 0110 0001, 0110 1110) --> (010011, 010110, 000101, 101110)
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; // get first 6 bits of first byte,
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); // get last 2 bits of first byte and first 4 bit of second byte
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); // get last 4 bits of second byte and first 2 bits of third byte
char_array_4[3] = char_array_3[2] & 0x3f; // get last 6 bits of third byte
for (i = 0; (i < 4); i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
}
if (i)
{
for (j = i; j < 3; j++)
char_array_3[j] = '\0';
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];
while ((i++ < 3))
ret += '=';
}
return ret;
}
std::string base64_decode(const std::string& encoded_string) {
size_t in_len = encoded_string.size();
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std::string ret;
while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++;
if (i == 4) {
for (i = 0; i < 4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]) & 0xff;
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++)
ret += char_array_3[i];
i = 0;
}
}
if (i) {
for (j = 0; j < i; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]) & 0xff;
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
}
return ret;
}