base64的编码和解码

来源:互联网 发布:监控需要网络吗 编辑:程序博客网 时间:2024/05/01 01:23

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 inlinechar 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 padreturn 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;}