1.base64编码的原理
由于历史原因,Email只被允许传送ASCII字符,即一个8位字节的低7位。因此,如果您发送了一封带有非ASCII字符(即字节的最高位是1)的Email通过有“历史问题”的网关时就可能会出现问题。所以base64位编码才存在。
base64编码的原理就是将3个8位字节转换成4个6位字节进行传输,当然在高2位会填0。base64编码表有64个元素:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/。26+26+10+2 = 64 = 2^6。
所以base64对要编码的字符串是以3个字节为单位进行转换的,但是如果不是3的倍数怎么办,base64引入了一个pad,即若最终剩余1个或2个字节,则最后填充2个或1个pad字节,pad字节的内容为'=',所以base64编码的最后往往会有1到2个‘=’。
2.举例
如字符串"abc",采用base64编码,转换为二进制如下:
编码前:11000001 11000010 11000011
编码后:00110000 00011100 00001011 00000011
即48 28 11 3,对应wcLD
若最后剩余字符'ab',则编码如下:
编码前:11000001 11000010
编码后:00110000 00011100 00001000 pad
即48 28 8 pad,对应wcI=
3.实现如下
/*base64位编码原理:
总共64个字符, 26+26+10+2 = 64 = 2^6
将3个8位字节转换为4个6位字节,然后在前面2位补0
如果总字节数不是3的倍数,那么就会剩余1个或2个字节,需要补成3的倍数,补的字节填'=',所以末尾最多2个'='
*/
const char* base64_encode(const unsigned char *text, int size, char *buf, int *out_len)
{
char *head_buf = buf;
static const char *base64_encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int buflen = 0;
while (size > 0) {
*buf++ = base64_encoding[(text[0] >> 2) & 0x3f];//得到第一个字节的前6位
if (size > 2) {
*buf++ = base64_encoding[((text[0] & 3) << 4) | (text[1] >> 4)];//第一个字节的后2位和第二个字节的前4位拼在一起
*buf++ = base64_encoding[((text[1] & 0xf) << 2) | (text[2] >> 6)];//第二个字节的后4位和第三个字节的前2位拼在一起
*buf++ = base64_encoding[text[2] & 0x3f];//第三个字节的后6位
}
else {
switch (size) {
case 1:
*buf++ = base64_encoding[(text[0] & 3) << 4];//第一个字节的后2位,后4位为0
*buf++ = '=';
*buf++ = '=';
break;
case 2:
*buf++ = base64_encoding[((text[0] & 3) << 4) | (text[1] >> 4)];//第一个字节的后2位和第二个字节的前4位拼在一起
*buf++ = base64_encoding[(text[1] & 0xf) << 2];//第二个字节后四位,后2位为0
*buf++ = '=';
break;
}
}
text += 3;
size -= 3;
buflen += 4;
}
*buf = '\0';
*outlen = buflen;
return head_buf;
}
static inline
char getBase64Value(char ch)
{
if ((ch >= 'A') && (ch <= 'Z'))
return ch - 'A';
if ((ch >= 'a') && (ch <= 'z'))
return ch - 'a' + 26;
if ((ch >= '0') && (ch <= '9'))
return ch - '0' + 52;
switch (ch) {
case '+':
return 62;
case '/':
return 63;
case '='://base64 pad
return 0;
default:
return 0;
}
}
int base64_decoding(const char *text, int size, char *buf)
{
if (size % 4)
return -1;
unsigned char chunk[4];
int parsenum = 0;
while (size > 0) {
chunk[0] = getBase64Value(text[0]);
chunk[1] = getBase64Value(text[1]);
chunk[2] = getBase64Value(text[2]);
chunk[3] = getBase64Value(text[3]);
*buf++ = (chunk[0] << 2 | chunk[1] >> 4);//将第一个字节的后6位和第二个字节的前4位(前2位为0)拼在一起
*buf++ = (chunk[1] << 4 | chunk[2] >> 2);//将第二个字节的后4位和第三个字节的前6位(前2位为0)拼在一起
*buf++ = (chunk[2] << 6 | chunk[3]);//将第三个字节的后2位和第四个字节(前2位为0)拼在一起
text += 4;
size -= 4;
parsenum += 3;
}
return parsenum;
}