BASE64编码 C实现


BASE64编码可以看作是一种数据可视化的编码集,也可以看作是一种简单的数据加密处理。即展现出数据编码的思路,也满足了数据可视化的要求。同时展现出一种简单的数据加密方法。


在处理很多数据缓冲区的时候,对于不可见字符,都比较头疼,不知道这些不可见字符到底是什么,即使是比对他们的ASSCII,也比较麻烦,需要中断或者调试或者修改代码等到。所以很多时候会将这些不可见字符转换为可视化的串,从而检查调试其数值是否正确。可视化的过程当然可以选择BASE64,同样也可以选择其他的方式,如直接将每个字节转换成两位十六进制数,也同样可以进行比较,而且不会破坏字节与字节之间的关系,显得更加方便。

同样是三个字节,转换为BASE64编码需要4个字节,转换为16进制则需要6个字节,因此,相对于16进制表示法,BASE64可以减少数据长度。从编码学的角度来看,也可以很好的理解,对于每个字节,BASE64使用了6比特,而十六进制只使用四字节(编码16个字符只需要4字节,但是表示的话,还是每个字节表示一个字符)。


BASE64编码规则:将原字符串顺序切割为长度3的分组(最后一个分组长度不一定为3),然后将每个分组转换为4字节的BASE64编码,对于长度为3的分组,将3个字节转换为二进制,总共24比特,将这24比特顺次切割为4个6比特的分组,再把每个分组高位补两个0,补足8比特。根据下面的BASE64编码表将4个8比特字节转换为对应的字符;对于长度为1的分组,取高6位生成第一位BASE64编码,低两位右补4个0,并转换为第二个BASE64编码,然后在这两个编码后补两个等号“=”,生成四位BASE64编码;对于长度为2的分组,处理逻辑类似与长度为1的分组,将2字节的16位二进制从左到右顺次分割,第一个6比特生成第一个BASE64编码,第二个6比特生成第二个BASE64编码,剩余的四比特右边补两个0,生成第三个BASE64编码,后面补一个“=”号,凑足4个BASE64编码。然后按照顺序,将多组BASE64编码串起来,生成最终的BASE64编码串。

BASE64解码规则:将BASE64编码的串切割为宽4的分组,对于每一个分组,将四个字符转换成对应的BASE64编码值二进制,取每个字节的低6位,并将这六位按顺序连接起来,得到24比特,将这24比特分割为3个8比特字节。然后还原成三个ASCII字符。如果带BASE64编码带等号的话,跟编码规则相反,一个等号时,得到2个原字符,两个等号时,得到一个原字符。最后把所有解码得到的字符分组按顺序串联起来。


下面给出基于C的BASE64实现,使用了字典表,比较方便,高效:


// base_base64.h

#ifndef __BASE_BASE64_H__
#define __BASE_BASE64_H__

int encode_base64(const char *src,int src_len,char *dst,int *dst_len);

int decode_base64(const char *src,int src_len,char *dst,int *dst_len);

#endif

// base_base64.c
#include <stdio.h>
#include <string.h>


#include "base_define.h"
#include "base_base64.h"

char encode_base64_dict[] ={"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"};

char decode_base64_dict[] ={
	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,62, 0, 0, 0,63, 
	52,53,54,55,56,57,58,59,60,61, 0, 0, 0, 0, 0, 0,
	 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
	15,16,17,18,19,20,21,22,23,24,25, 0, 0, 0, 0, 0,
	 0,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
	41,42,43,44,45,46,47,48,49,50,51, 0, 0, 0, 0, 0,
	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
int encode_base64(const char *src,int src_len,char *dst,int *dst_len){
    int ret = BASE_RET_SUCCESS;
    int dst_index=0;
    int group_num,last_num,i,k;
    group_num = src_len/3;
    last_num = src_len %3;
    i = (src_len + 2)/3;
    if(i * 4 > (*dst_len)){
	ret = BASE_RET_FAILED;
	return ret;
    }
    memset(dst,0,*dst_len);
    for(i=0;i<group_num;i++){
	k = 3*i;
	dst[dst_index++] = encode_base64_dict[(src[k]>>2) & 0X3F];
	dst[dst_index++] = encode_base64_dict[((((src[k])&0X03)<<4)| (src[k+1])>>4) & 0X3F];
	dst[dst_index++] = encode_base64_dict[(((src[k+1]&0X0F)<<2) | (src[k+2])>>6) & 0X3F];
	dst[dst_index++] = encode_base64_dict[((src[k+2]) & 0X3F)];
    }
    if(last_num == 2){
	k = group_num * 3;
	dst[dst_index++] = encode_base64_dict[((src[k])>>2) & 0X3F];
	dst[dst_index++] = encode_base64_dict[((((src[k])&0X03)<<4) | (src[k+1]>>4)) & 0X3F];
	dst[dst_index++] = encode_base64_dict[(((src[k+1])&0X0F)<<2) & 0X3F];
	dst[dst_index++] = '=';
    }else if(last_num == 1){
	k = group_num * 3;
        dst[dst_index++] = encode_base64_dict[((src[k])>>2) & 0X3F];
        dst[dst_index++] = encode_base64_dict[(((src[k])&0X03)<<4) & 0X30];
        dst[dst_index++] = '=';
        dst[dst_index++] = '=';
    }
     
    ret = BASE_RET_SUCCESS;
    *dst_len = dst_index;
    return ret;
}

int decode_base64(const char *src,int src_len,char *dst,int *dst_len){
    int ret = BASE_RET_SUCCESS;
    int group_num,last_num,dst_index = 0;
    group_num = src_len / 4;
    last_num = src_len %4;
    if((last_num > 0) || (group_num * 3 > (*dst_len))){
	ret = BASE_RET_FAILED;
	return ret;
    }
    int i,k;
    char tmp_val[4] = {0};
    k = -4;
    for(i = 0;i<group_num ;i++){
	k = k + 4;
	tmp_val[0] = decode_base64_dict[src[k]];
	tmp_val[1] = decode_base64_dict[src[k+1]];
	tmp_val[2] = decode_base64_dict[src[k+2]];
	tmp_val[3] = decode_base64_dict[src[k+3]];
	dst[dst_index++] = ((tmp_val[0]<<2) | (tmp_val[1]>>4));
	dst[dst_index++] = ((tmp_val[1] & 0X0F) <<4) | ((tmp_val[2])>>2);
	dst[dst_index++] = ((tmp_val[2] & 0X03) <<6) | tmp_val[3];
    }
    for(i = dst_index-1;i> 0;i--){
	if(dst[i] == 0){
	    dst_index--;
	}else{
	     break;
	}
    } 
    ret = BASE_RET_SUCCESS;
    *dst_len = dst_index;    
    return ret;
}

使用字典表,可以直接通过字典查使用下标转换编码。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值