前言
经过多方面查找后,以及好几天的努力,才完成了base64的编码与解码工作。水平有限,代码有些繁琐,希望大家批评指正。
原理
base64的索引表
-base64的编码都是按字符串长度,以每3个8bit的字符为一组,
-然后针对每组,首先获取每个字符的ASCII编码,
-然后将ASCII编码转换成8bit的二进制,得到一组3*8=24bit的字节
-然后再将这24bit划分为4个6bit的字节,并在每个6bit的字节前面都填两个高位0,得到4个8bit的字节
-然后将这4个8bit的字节转换成10进制,对照Base64索引表,得到对应编码后的字符。
-base64编码是,3个字符变为4个字符。若编码字符不足3个(二进制不是6的倍数),则在后面补0,使之可以形成一个新字符;若最后几个字符不能转化出4个字符,则在后面直接补‘=’。详见下表
代码实现
编码
#include<stdio.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
char boss[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
int sumb(int a)
{
int i,j,m,n;
int sum=1;
for(i=0;i<a;i++)
{
sum*=2;
}
return sum;
}
int b_to_o(char str[])
{
int m,n,i,j;
int num=0;
m=strlen(str);
for(i=0;i<m;i++)
{
j=str[i]-'0';
num+=j*sumb(m-i-1);
}
return num;
}
int main()
{
int m,n,i,j,k,l,c,len;
char str[10000]={0}; //用来储存出初始字符串
char temp[1000]={0}; //每六个一组取出后,形成新的字符串,储存于其中
char num[20000]={0}; //字符串转化成二进制之后,形成一个字符串,储存
char tp[1000]={0}; //2进制字符串
char link[1000]={0}; //中转
int mud[1000];
char r,s,t;
printf("请输入待加密的字符串:");
gets(str);
len=strlen(str);
if(len%3==0)
{
for(i=0;i<len;i++)
{
m=str[i];
// printf("%d\n",m);
itoa(m,tp,2);
sprintf(link,"%08s",tp);
strcat(num,link);
//printf("***\n");
}
//printf("%s\n",num);
l=(len*8)/6;
//printf("%d\n",l);
for(i=0;i<l;i++)
{
c=0;
for(j=0+6*i;j<6*(i+1);j++)
{
temp[c]=num[j];
c++;
}
//puts(temp);
mud[i]=b_to_o(temp);
// printf("%d\n",mud[i]);
}
//puts(mud);
for(i=0;i<l;i++)
{
printf("%c",boss[mud[i]]);//printf("***\n");
}
}
else
{
int mm,mf;
mm=len%3;
len=len-mm;
char ww[1000]={0};
for(i=0;i<len;i++)
{
ww[c]=str[i];
c++;
}
for(i=0;i<len;i++)
{
m=str[i];
// printf("%d\n",m);
itoa(m,tp,2);
sprintf(link,"%08s",tp);
strcat(num,link);
//printf("***\n");
}
//printf("%s\n",num);
l=(len*8)/6;
//printf("%d\n",l);
for(i=0;i<l;i++)
{
c=0;
for(j=0+6*i;j<6*(i+1);j++)
{
temp[c]=num[j];
c++;
}
//puts(temp);
mud[i]=b_to_o(temp);
}
// printf("%d\n",mud[i-1]);
mf=i;
// printf("**\n");
memset(temp,0,sizeof(temp));
memset(num,0,sizeof(num));
//printf("**\n");
if(mm==1)
{
m=str[len];
itoa(m,tp,2);
sprintf(link,"%08s",tp);
// printf("**\n");
strcat(num,link);
char pp[]="0000";
strcat(num,pp);
//puts(num);
// printf("strlen is %d\n",strlen(num));
// puts(num);
for(i=0;i<2;i++)
{
c=0;
for(j=0+6*i;j<6*(i+1);j++)
{
temp[c]=num[j];
c++;
}
//puts(temp);
mud[mf++]=b_to_o(temp);
// printf("%d\n",mud[mf]);
}
mud[mf]=64;
mud[mf+1]=64;
}
else if(mm==2)
{
for(i=1; i<=mm; i++)
{
m=str[len-i];
itoa(m,tp,2);
sprintf(link,"%08s",tp);
// printf("**\n");
strcat(num,link);
}
char pp[]="00";
strcat(num,pp);
//puts(num);
// printf("strlen is %d\n",strlen(num));
//puts(num);
for(i=0;i<3;i++)
{
c=0;
for(j=0+6*i;j<6*(i+1);j++)
{
temp[c]=num[j];
c++;
}
//puts(temp);
mud[mf++]=b_to_o(temp);
//printf("%d\n",mud[mf]);
}
mud[mf]=64;
}
for(i=0;i<l+4;i++)
{
//printf("%d\n",mud[i]);
printf("%c",boss[mud[i]]);//printf("***\n");
}
}
}
解密
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
char boss[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
int c_to_n(char s)
{
int i,j,k,len;
len=strlen(boss);
for(i=0;i<len;i++)
{
if(boss[i]==s)
break;
}
return i;
}
int sumb(int a)
{
int i,j,m,n;
int sum=1;
for(i=0;i<a;i++)
{
sum*=2;
}
return sum;
}
int b_to_o(char str[])
{
int m,n,i,j;
int num=0;
m=strlen(str);
for(i=0;i<m;i++)
{
j=str[i]-'0';
num+=j*sumb(m-i-1);
}
return num;
}
int main()
{
int i,j,m,n,k,len,c,len1,len2,len3,flag=0,mf,p;
int main[1000]={0}; //储存最后结果
char str[10000]={0};
char s1[10000]={0}; //前面能被3整除的字符串
char s2[100]={0}; //the str behind a,
char bin[100]={0}; //十进制化为二进制
char link[100]={0}; //中转
char num[10000]={0}; //conact the strs
char temp[1000]={0}; //取出字符串
printf("请输入待解密的字符串:");
gets(str);
len=strlen(str);
if(str[len-1]=='=')
{
for(i=0; i<len-4; i++)
{
s1[i]=str[i];
}
c=0;
if(str[len-2]=='=')
{
flag=2;
for(j=len-4;j<len-2;j++)
{
s2[c]=str[j];
c++;
}
}
else
{
flag=1;
for(j=len-4;j<len-1;j++)
{
s2[c]=str[j];
c++;
}
}
len1=strlen(s1);
len2=strlen(s2);
for(i=0;i<len1;i++)
{
m=c_to_n(s1[i]);
itoa(m,bin,2);
sprintf(temp,"%06s",bin);
strcat(num,temp);
}
// printf("%d\n",strlen(num));
memset(bin,0,sizeof(bin));
memset(temp,0,sizeof(temp));
for(i=0;i<len2;i++)
{
m=c_to_n(s2[i]);
//printf("%d\n",m);
itoa(m,bin,2);
//puts(bin);
sprintf(temp,"%06s",bin);
// puts(temp);
strcat(num,temp);
}
len3=strlen(num);
//printf("*%d\n",len2);
if(flag==1)
{
num[len3-2]='\0';
}
else if(flag==2)
{
num[len3-4]='\0';
}
len3=strlen(num);
k=len3/8;
for(i=0;i<k;i++)
{
c=0;
for(j=0+8*i;j<8*(i+1);j++)
{
temp[c]=num[j];
c++;
}
main[i]=b_to_o(temp);
}
mf=i;
for(i=0;i<mf;i++)
{
// printf("%d",main[i]);
printf("%c",main[i]);
}
}
else
{
for(i=0;i<len;i++)
{
m=c_to_n(str[i]);
itoa(m,bin,2);
sprintf(link,"%06s",bin);
strcat(num,link);
}
// puts(num);
len1=strlen(num);
p=len1/8;
for(i=0;i<p;i++)
{
c=0;
for(j=0+8*i;j<8*(i+1);j++)
{
temp[c]=num[j];
c++;
}
//printf("it is temp :%s\n",temp);
main[i]=b_to_o(temp);
// printf("%d\n",main[i]);
}
mf=i;
for(i=0;i<mf;i++)
{
printf("%c",main[i]);
}
}
}
参考
https://www.cnblogs.com/diligenceday/p/6002382.html
http://www.cnblogs.com/hongru/archive/2012/01/14/2321397.html
https://baike.baidu.com/item/base64/8545775?fr=aladdin