依睛(IT blog) 我回来了,PHP<-->C/C++ LINUX

笨鸟

统计

积分与排名

友情连接

最新评论

Base64编码、解码的实现

Base64编码、解码的实现 收藏

转: http://blog.csdn.net/xuezhimeng/archive/2009/01/23/3851844.aspx

////////////////////////////////////////////////////////引用网文/////////////////////////////////////////////

什么是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编码在线转换器 :
http://www.motobit.com/util/base64-decoder-encoder.asp

Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,在发送电子邮件时,服务器认证的用户名和密码需要用Base64编码,附件也需要用Base64编码。
下面简单介绍Base64算法的原理,由于代码太长就不在此贴出
Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。

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

这样说会不会太抽象了?不怕,我们来看一个例子:

转换前 aaaaaabb ccccdddd eeffffff
转换后 00aaaaaa 00bbcccc 00ddddee 00ffffff

应该很清楚了吧?上面的三个字节是原文,下面的四个字节是转换后的Base64编码,其前两位均为0。

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

Value Encoding Value Encoding Value Encoding Value Encoding
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 (pad) =
15 P 32 g 49 x
16 Q 33 h 50 y
让我们再来看一个实际的例子,加深印象!

转换前 10101101 10111010 01110110
转换后 00101011 00011011 00101001 00110110
十进制 43 27 41 54
对应码表中的值 r b p 2


所以上面的24位编码,编码后的Base64值为 rbp2
解码同理,把 rbq2 的二进制位连接上再重组得到三个8位值,得出原码。
(解码只是编码的逆过程,在此我就不多说了,另外有关MIME的RFC还是有很多的,如果需要详细情况请自行查找。)

用更接近于编程的思维来说,编码的过程是这样的:

第一个字符通过右移2位获得第一个目标字符的Base64表位置,根据这个数值取到表上相应的字符,就是第一个目标字符。
然后将第一个字符左移4位加上第二个字符右移4位,即获得第二个目标字符。
再将第二个字符左移2位加上第三个字符右移6位,获得第三个目标字符。
最后取第三个字符的右6位即获得第四个目标字符。

在以上的每一个步骤之后,再把结果与 0x3F 进行 AND 位操作,就可以得到编码后的字符了。

////////////////////////////////////////////////////////引用网文到此结束/////////////////////////////////////////////

以下是Base64编码、解码的C语言实现:(VC 6.0下编译通过)


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

posted on 2009-01-29 18:49 向左向右走 阅读(1044) 评论(0)  编辑 收藏 引用 所属分类: C/C++学习资料库

只有注册用户登录后才能发表评论。