C语言 Base64算法

Base64是网络上最常见的用于传输8Bit 字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。可查看RFC2045~RFC2049,上面有MIME的详细规范。

Base64编码是从二进制到字符的过程,可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性,需要解码后才能阅读。

我由于最近工作需要,需要把Base64位算法移植到嵌入式设备中,所以就百度查了下这个算法,这个算法并不复杂,所以自己就动手写了一个,没有参考网上现成代码,就是根据原理自己写了一个

1、讲下Base64算法原理

   1)将给定的字符串转换成对应的字符编码(如:GBK、UTF-8)

  2)将获得该字符编码转换成二进制码

  3)对获得的二进制码进行分组操作

  第一步:每3个字节(8位二进制)为一组,一共24个二进制位

  第二步:将这个24个二进制位分成4组,每个组有6个二进制位,不足6位的,后面补0。

  第三步:在每个组前面加两个0,这样每个组就又变成了8位,即每个组一个字节,4个组就4个字节了。

  第四步:根据Base64的转码表找到每个字节对应的符号,这个符号就是Base64的编码值

注意:实际输入数据不一定是字符,只要是十六进制数据就可以,都可以转换的

2、Base64算法实现

const char*Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  //Base64编码对照表
/********************************************************************
函数原型:GencBase64
功   能:base64编码函数
输入参数:indata: 需要编码数据
        inlen : 编码数据长度
        outdata:编码后输出数据
输   出:> 0 编码后输出数据长度 < 0 需要编码的数据里面有错误数据(实际不会有这种情况,所有数据都可以编码,都可以转换)
说   明:无
*--------------------------------------------------------------------
*修改时间		|	修改者		|	备注
*--------------------------------------------------------------------
*2018-04-23		        liuchunjie	        First
********************************************************************/
int16_t GencBase64(unsigned char* indata, uint16_t inlen,unsigned char *outdata)
{
    uint16_t i,j;
	//1、首先3字节组成1组,然后转换成4字节1组
	for(i = 0,j = 0;i < (inlen/3)*3;i = i + 3,j = j + 4)
	{
		outdata[j] = 0;    //清除要做操作缓冲,其实这里没必要,可以去掉
		outdata[j + 1] = 0;
		outdata[j + 2] = 0;
		outdata[j + 3] = 0;
		outdata[j] = indata[i] >> 2;
		outdata[j + 1] = (((indata[i]&0x03) << 4) | (indata[i + 1] >> 4));
		outdata[j + 2] = (((indata[i + 1]&0x0F) << 2) | ((indata[i + 2]&0xC0) >> 6));
		outdata[j + 3] = (indata[i + 2]&0x3F);
	}
	//2、其次对照Base64编码表,转换成对应字符编码
	for(i = 0;i < j;i++)
	{
		outdata[i] = Base64[outdata[i]];
	}
	if((inlen%3) == 1)//说明最后还有1个字节剩余,剩余1个字节,最后转换成Base64编码时最后要补2个'='字符,形成4字节1组,这样最后编码数据就是4的倍数
	{
		outdata[i] = 0;    //清除要操作缓冲
		outdata[i + 1] = 0;
		outdata[i + 2] = 0;
		outdata[i + 3] = 0;
		outdata[i] = indata[inlen - 1] >> 2;
		outdata[i + 1] = ((indata[inlen - 1]&0x03) << 4);
		outdata[i] = Base64[outdata[i]];
		outdata[i + 1] = Base64[outdata[i + 1]];
		outdata[i + 2] = '=';
		outdata[i + 3] = '=';
		i = i + 4;
	}
	if((inlen%3) == 2)//说明最后还有2个字节剩余,剩余2个字节,最后转换成Base64编码时最后要补1个'='字,形成4字节1组,这样最后编码数据就是4的倍数
	{
		outdata[i] = 0;    //清除要操作缓冲
		outdata[i + 1] = 0;
		outdata[i + 2] = 0;
		outdata[i + 3] = 0;
		outdata[i] = indata[inlen - 2] >> 2;
		outdata[i + 1] = (((indata[inlen - 2]&0x03) << 4) | (indata[inlen - 1] >> 4));
		outdata[i + 2] = (indata[inlen - 1]&0x0F) << 2;
		outdata[i] = Base64[outdata[i]];
		outdata[i + 1] = Base64[outdata[i + 1]];
		outdata[i + 2] = Base64[outdata[i + 2]];
		outdata[i + 3] = '=';
		i = i + 4;
	}
	return i;   //返回编码后数据总长度 
}
/********************************************************************
函数原型:GdecBase64
功   能:base64解码函数
输入参数:indata: 需要解码数据
        inlen : 解码数据长度
        outdata:解码后输出数据
输   出: > 0 解码后输出数据长度 < 0 需要解码的数据里面有错误数据(实际有可能有这种情况,比如为了测试程序的健壮性,可以添加一些错误数据在里面,这里所谓错误数据就是不在base64编码对照表里面数据,比如'('字符,就是不合法数据)
说   明: 解码函数是用来解码接收数据的,所以你不可能保证接收数据里面都是正确的
注   意:传输数据为了能够保证传输数据是4的倍数,后面会补充1个或者2个'='
*--------------------------------------------------------------------
修改时间			|	修改者		|	备注
*--------------------------------------------------------------------
*2018-04-23			liuchunjie	        First
********************************************************************/
int16_t GdecBase64(unsigned char* indata, uint16_t inlen,unsigned char *outdata)
{
    uint16_t i,j;
	uint16_t tlength = 0;
	uint8_t buff[50] = {0};
	//1、首先去掉最后1个或者2个'='字符,最多就是2个
	for(i = 0;i < 2;i++)
	{
		if(indata[inlen - 1 - i] == '=')
 		{
		    inlen--;
		}
                else
	        {
		    break;
	        }
	}
	for(i = 0;i < inlen;i++)
	{
		for(j = 0;j < 64;j++)
		{
			if(*(indata + i) == *(Base64 + j))
			{
				break;
			}
		}
		if(j == 64)//传输数据里面有错误数据,数据没在base64编码对照表里面
		{
			return -1;
		}
		buff[i] = j;//找对对应索引值保存起来,为后面合成数据
	}
	//判断数据是否够4的倍数,不够补齐,补0x00
	if((i % 4) == 1)//说明数据最后剩余1数据,所以需要补充3个0x00,组成4的倍数
	{
	    buff[i] = 0x00;
		buff[i + 1] = 0x00;
		buff[i + 2] = 0x00;
		i = i + 3;
	}
	if((i % 4) == 2)//说明数据最后剩余2数据,所以需要补充2个0x00,组成4的倍数
	{
		buff[i] = 0x00;
		buff[i + 1] = 0x00;
		i = i + 2;
	}
	if((i % 4) == 3)//说明数据最后剩余3数据,所以需要补充1个0x00,组成4的倍数
	{
		buff[i] = 0x00;
		i = i + 1;
    }
    for(j = 0,tlength = 0;j < i;j = j + 4,tlength = tlength + 3)//上面数据已经组成4的倍数了,这样转换后的数据一定是3的倍数,这样解码后数据可能比原来多几个0x00数据,如果你不希望多出几个0x00,其实你也可以不组成4的倍数,我这里主要是为了方便解码
    {
        outdata[tlength] = (buff[j] << 2) | ((buff[j + 1]&0x30) >> 4);
        outdata[tlength + 1] = (((buff[j + 1]&0x0F) << 4) | ((buff[j + 2]&0x3C) >> 2));
        outdata[tlength + 2] = (((buff[j + 2]&0x03) << 6) | buff[j + 3]);		
    }
    return tlength;
}

以上就是代码实现的过程

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值