base64的编码和解码

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值