作用
在互联网上传输二进制数据。在互联网上传输非可打印字符时,可能会导致乱码、不能被网关有效处理等问题,而可打印字符不会有这些问题。故将二进制字符转为可打印字符就可以了。
原理
base64就是将3个8位的数据,转为4个6位的数据。转换后的字符都是可打印字符。一般设置为"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"。当然,你可以根据自己的需求,使用别的可打印字符。
处理位数不足
如果要编码的字节不是3的倍数,就会剩余2个字节或1个字节
1. 2个字节,16位,可以用3个6位来表示,这样编码后生成3个字符,最后两位用0填充
0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 0 | 0 | 7 | 8 | 9 | 10 | 11 | 12 | 0 | 0 | 13 | 14 | 15 | 16 | 0 | 0 |
2. 1个字节,8位,可以用2个6位表示,编码后生成2个字符,最后四位用0填充
0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 0 | 0 | 7 | 8 | 0 | 0 | 0 | 0 |
这样还有一个问题,生成的字符要么3个,要么2个,不是4的倍数。一般,生成的字符数都对齐为4的倍数。所以,不够的我们使用'='来填充
代码
下面是参考nginx实现的base64编码和解码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void base64_encode(u_char* dst, const u_char* src)
{
char basis[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int len = strlen((char*)src);
while (len > 2)
{
*dst++ = basis[(src[0] >> 2) & 0x3f];
*dst++ = basis[((src[0] & 3) << 4) | (src[1] >> 4)];
*dst++ = basis[((src[1] & 0x0f) << 2) | (src[2] >> 6)];
*dst++ = basis[src[2] & 0x3f];
src += 3;
len -= 3;
}
if (len == 1)
{
*dst++ = basis[src[0] >> 2];
*dst++ = basis[(src[0] & 0x3) << 4];
*dst++ = '=';
*dst++ = '=';
}
if (len == 2)
{
*dst++ = basis[src[0] >> 2];
*dst++ = basis[((src[0] & 3) << 4) | (src[1] >> 4)];
*dst++ = basis[(src[1] & 0xf) << 2];
*dst++ = '=';
}
*dst = '