BASE64编码

Eddy 发布于2009-11-28 13:24:53 分类: 加密解密 已浏览loading 网友评论0条 我要评论

什么是Base64?
按照RFC2045的定义,Base64被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。(The Base64 Content-Transfer-Encoding is designed to represent arbitrary sequences of octets in a form that need not be humanly readable.)

Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3*8 = 4*6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。

转换后,我们用一个码表来得到我们想要的字符串(也就是最终的Base64编码),这个表是这样的:

BASE64编码表

索引 对应字符 索引 对应字符 索引 对应字符 索引 对应字符
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v    
14 O 31 f 48 w    
15 P 32 g 49 x    
16 Q 33 h 50 y    

转换例子:

 

C语言实现:

#include <stdio.h>
#include <string.h>

typedef unsigned char BYTE;

/*====================================================================
 Base64编码函数
 btSrc指向被编码的数据缓冲区
 iSrcLen被编码的数据的大小(字节)
 btRet指向存放Base64编码的数据缓冲区
 piRetLen指向存放Base64编码的数据缓冲区的长度
 若btRet为NULL函数返回0,piRetLen传回btSrc的Base64编码所需缓冲区的大小
 若btRet指向的缓冲区太小,函数返回-1
 否则函数返回实际btSrc的Base64编码所需缓冲区的大小
=====================================================================*/
int EncodeBase64(BYTE *btSrc, int iSrcLen, BYTE *btRet, int *piRetLen) //Base64编码
{
 int i = 0, j = 0, k = 0 ;
 BYTE EncodeBase64Map[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
 i = (iSrcLen+2) / 3 * 4 ; //获取btSrc的Base64编码所需缓冲区的大小
 if(btRet != NULL)
 {
  if(*piRetLen < i) //Base64编码所需缓冲区偏小
   return -1 ;
  *piRetLen = i ; //*piRetLen返回btSrc的Base64编码的缓冲区大小
 }
 else
 {
  *piRetLen = i ;
  return 0 ;
 }

 k = iSrcLen - iSrcLen % 3 ;
 for(i=j=0; i<k; i+=3) //编码
 {
  btRet[j++] = EncodeBase64Map[(btSrc[i]>>2)&0x3F] ;
  btRet[j++] = EncodeBase64Map[((btSrc[i]<<4) + (btSrc[i+1]>>4))&0x3F] ;
  btRet[j++] = EncodeBase64Map[((btSrc[i+1]<<2) + (btSrc[i+2]>>6))&0x3F] ;
  btRet[j++] = EncodeBase64Map[btSrc[i+2]&0x3F] ;
 }
 k = iSrcLen - k ;
 if(1 == k)
 {
  btRet[j++] = EncodeBase64Map[(btSrc[i]>>2)&0x3F] ;
  btRet[j++] = EncodeBase64Map[(btSrc[i]<<4)&0x3F] ;
  btRet[j++] = btRet[j] = '=' ;
 }
 else if(2 == k)
 {
  btRet[j++] = EncodeBase64Map[(btSrc[i]>>2)&0x3F] ;
  btRet[j++] = EncodeBase64Map[((btSrc[i]<<4) + (btSrc[i+1]>>4))&0x3F] ;
  btRet[j++] = EncodeBase64Map[(btSrc[i+1]<<2)&0x3F] ;
  btRet[j] = '=' ;
 }

 return ++j ;
}

/*====================================================================
 Base64解码函数
 btSrc指向被解码的数据缓冲区
 iSrcLen被解码的数据的大小(字节)
 btRet指向存放Base64解码的数据缓冲区
 piRetLen指向存放Base64解码的数据缓冲区的长度
 若btRet为NULL函数返回0,piRetLen传回btSrc的Base64解码所需缓冲区的大小
 若btRet指向的缓冲区太小,函数返回-1
 否则函数返回btSrc的Base64解码所需缓冲区的大小
=====================================================================*/
int DecodeBase64(BYTE *btSrc, int iSrcLen, BYTE *btRet, int *piRetLen) //Base64解码
{
 int i = 0, j = 0 ;
 BYTE EncodeBase64Map[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 BYTE DecodeBase64Map[256] = {0} ;
 
 for(j = iSrcLen; j>0 && '='==btSrc[j-1]; --j) ; //忽略=号
 i = (j/4)*3+(j%4+1)/2; //计算解码后 字符串的长度
 
 if(btRet != NULL)
 {
  if(*piRetLen < i) //Base64解码所需缓冲区偏小
   return -1 ;
  *piRetLen = i ; //*piRetLen返回btSrc的Base64解码的缓冲区大小
 }
 else
 {
  *piRetLen = i ;
  return 0 ;
 }

 j = sizeof(EncodeBase64Map) ;
 for(i=0; i<j; ++i)
  DecodeBase64Map[ EncodeBase64Map[i] ] = i ;
 for(i=j=0; i<iSrcLen; i+=4)
 {
  btRet[j++] = DecodeBase64Map[btSrc[i  ]] << 2 | DecodeBase64Map[btSrc[i+1]] >> 4 ;
  btRet[j++] = DecodeBase64Map[btSrc[i+1]] << 4 | DecodeBase64Map[btSrc[i+2]] >> 2 ;
  btRet[j++] = DecodeBase64Map[btSrc[i+2]] << 6 | DecodeBase64Map[btSrc[i+3]] ;
 }

 return *piRetLen ;
}

int main(void)
{
 char str[128]={0} ;
 char szTemp[128] = {0} ;
 int iRetLen, i ;
 printf("Base64编码:\n") ;
 scanf("%s", str) ;
 iRetLen = sizeof(szTemp) ;
 EncodeBase64(str, strlen(str), szTemp, &iRetLen) ;
 szTemp[iRetLen] = '\0' ;
 printf("%s\n", szTemp) ;
 printf("Base64解码:\n") ;
 iRetLen = sizeof(szTemp) ;
 scanf("%s", szTemp) ;
 DecodeBase64(szTemp, strlen(szTemp), str, &iRetLen) ;
 str[iRetLen] = '\0' ;
 printf("%s\n", str) ;
 for(i=0; i<iRetLen; ++i)
  printf("%0x ", (unsigned char)(str[i])) ;
 return 0 ;
}

已经有(0)位网友发表了评论,你也评一评吧!
原创文章如转载,请注明:转载自Eddy Blog
原文地址:http://www.rrgod.com/decryption/158.html     欢迎订阅Eddy Blog

关于 BASE64  编码  C语言  的相关文章

记住我的信息,下次不用再输入 欢迎给Eddy Blog留言