以文本方式查看主题

-  中文XML论坛 - 专业的XML技术讨论区  (http://bbs.xml.org.cn/index.asp)
--  『 XML在语音技术中的应用 』   (http://bbs.xml.org.cn/list.asp?boardid=47)
----  Base64编码技术  (http://bbs.xml.org.cn/dispbbs.asp?boardid=47&rootid=&id=38211)


--  作者:zhu_ruixian
--  发布时间:9/22/2006 6:24:00 PM

--  Base64编码技术
Base64简介
在RFC2045(http://www.ietf.org/rfc/rfc2045.txt)中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.)字面上的意思就是把要传送的内容简单的加密,不能让人直接识别。
RFC2045其实就是Multipurpose Internet Mail Extensions,base64就是用来简单加密邮件内容的。base64产生的原因还有一个就是,在Email的传送过程中,由于历史原因,Email只被允许传送ASCII字符,即一个8位字节的低7位。因此,如果您发送了一封带有非ASCII字符(即字节的最高位是1)的Email通过有“历史问题”的网关时就可能会出现问题。网关可能会把最高位置为0!由于以上原因,产生了Base64编码。
Base64编码的应用
首先,在E-Mail中,编码都是base64编码.随便用文本编辑器打开一封邮件,是eml为扩展名的,都可以看到如下内容:
Content-Type: text/html;
 charset="gb2312"
Content-Transfer-Encoding: base64
电子邮件中的内容都是用base64处理过的.
然后就是在文件的保存中base64也有应用。举个例子,在浏览器中输www.baidu.com,回车,网页打开以后,选"文件""另存为",在"保存类型"中选"Web 档案,单一文件(*.mht)"然后点"保存"。保存后的文件,如果在浏览器中打开,像普通的网页一样,包括文字 图片等很多文件。那么程序内部是如何实现的,把很多个文件保存到一个文件中那?你现在可以在记事本中把刚才保存的文件打开,文件的最后你可以看到如下内容:
         Content-Type: image/gif
         Content-Transfer-Encoding: base64
         Content-Location: http://gimg.baidu.com/img/gs.gif

         R0lGODlhDwARAJEAAP///9vb27a2tgAAACwAAAAADwARAAACNISPqcJ6DGFYMaYKsGEBZl0Jn5UF
         5ok2GXAaqTiKnudyFr1NHVci+y7YUUIwH9GxISFHigIAOw==
gs.gif是个图片 下面的内容就是它的base64编码,也就是说网页保存的时候,是通过base64编码把很多文件保存到同一个文件中的。
源代码
我们现在看看base64.c的源代码。打开以后你会发现里面有8个函数:
 long b64dlen(size_t cch);
 long b64elen(size_t cb);
 long strb64d(const char * psz,size_t cch, void * p);
 long strb64e(const void * p,size_t cb,char * psz);
 int strisb64(const char * psz,size_t cch);
 long wcsb64d(const wchar_t * psz, size_t cch, void * p);
 long wcsb64e(const void * p, size_t cb, wchar_t * psz);
 int wcsisb64(const wchar_t * psz,size_t cch);
作用:
 b64dlen  base64解码以后的长度
 b64elen  base64编码以后的长度
 strb64d  把base64编码以后的字符串,转换成为二进制数据
 strb64e  把二进制数据转化为base64编码
 strisb64 确定是不是有效的base64编码
 wcsb64d  功能和strb64d一样,数据类型不同
 wcsb64e  功能和strb64e一样,数据类型不同
 wcsisb64 功能和strisb64一样,数据类型不同
函数的使用
例如
加密文件:
void Base64EncodeFile (char* filename)
{
  FILE *RFile;
  FILE *WFile;
  int len;
  //char *buffer=(char*)malloc(1024);
  char buffer[1023];
   char FileNameBuffer[255];
  char EncodeBuffer[2046];
  memset(buffer,0,255);
  memset(FileNameBuffer,0,255);
  sprintf(FileNameBuffer,"%s.base64",filename);
  if ((RFile = fopen (filename, "rb")) == NULL){
   printf ("Execute Result: %s can't be opened\n", filename);
   return ;
  }
  if ((WFile = fopen (FileNameBuffer, "wb")) == NULL){
   printf ("Execute Result: %s can't be opened\n", FileNameBuffer);
   return ;
  }
  printf ("Execute Result: Base64 String Is Stored In %s ", FileNameBuffer);
   while (len = fread (buffer, 1, 1023, RFile)){
    long length=strb64e(buffer,len,EncodeBuffer);
    fwrite(EncodeBuffer,1,length,WFile);
   }
  fclose (RFile);
  fclose (WFile); 
  return;
}
附带可执行文件,可以base64编码字符串和文件


--  作者:zhu_ruixian
--  发布时间:10/16/2006 1:04:00 PM

--  
在别的地方看到一份源代码,共享一下。
typedef  unsigned long  ulong32 ;
class Base64Data {
public:
 
 static void encode( const unsigned char* buffer, ulong32 bufferSize, AnsiString& output, bool addLineBreak ) {
  ulong32 count = 0;
  ulong32 o = 0;
  
  output = "";
  while (count < bufferSize) {
   ulong32 remainingBytes = bufferSize - count;
   if ( addLineBreak && o && (o % 76 == 0) ) {
    output += "\n";
   }
   switch ( remainingBytes ) {
    case 1: {
     output += Base64Data::base64EncodingTable[ ((buffer[count] >> 2) & 0x3f) ];
     output += Base64Data::base64EncodingTable[ ((buffer[count] << 4) & 0x30) ];
     output += "==";
    }
    break;
    case 2: {
     output += Base64Data::base64EncodingTable[ ((buffer[count] >> 2) & 0x3f) ];
     output += Base64Data::base64EncodingTable[ ((buffer[count] << 4) & 0x30) + ((buffer[count + 1] >> 4) & 0x0f) ];
     output += Base64Data::base64EncodingTable[ ((buffer[count + 1] << 2) & 0x3c) ];
     output += "=";
    }
    break;

    default: {
     output += Base64Data::base64EncodingTable[ ((buffer[count] >> 2) & 0x3f) ];
     output += Base64Data::base64EncodingTable[ ((buffer[count] << 4) & 0x30) + ((buffer[count + 1] >> 4) & 0x0f) ];
     output += Base64Data::base64EncodingTable[ ((buffer[count + 1] << 2) & 0x3c) + ((buffer[count + 2] >> 6) & 0x03) ];
     output += Base64Data::base64EncodingTable[ (buffer[count + 2] & 0x3f) ];
    }
    break;
   }
   o += 4;
   count += 3;
  }
 }

 //calling this with a NULL buffer means that the buffer size will be returned
 static void decode(const AnsiString& input, unsigned char *buffer, ulong32& bufferSize ) {
  ulong32 index = 0;
  ulong32 count = input.size();
  ulong32 bufferIndex = 0;
  
  

  while (index < count)
  {
   while (index < count && (input[index] == 13 || input[index] == 10)) {
    index++;
   }

   if (index < count) {
    unsigned char b1 = (unsigned char)((Base64Data::base64DecodingTable[(int)input[index]] << 2 & 0xfc) +
     (Base64Data::base64DecodingTable[(int)input[index + 1]] >> 4 & 0x03));
    
    if ( buffer ) {
     buffer[bufferIndex] = b1;
    }
    
    bufferIndex++;
    if (input[index + 2] != '=')  {
     unsigned char b2 = (unsigned char)((Base64Data::base64DecodingTable[(int)input[index + 1]] << 4 & 0xf0) +
      (Base64Data::base64DecodingTable[(int)input[index + 2]] >> 2 & 0x0f));
     
     if ( buffer ) {
      buffer[bufferIndex] = b2;
     }

     bufferIndex++;
    }

    if (input[index + 3] != '=') {
     unsigned char b3 = (unsigned char)((Base64Data::base64DecodingTable[(int)input[index + 2]] << 6 & 0xc0) +
      Base64Data::base64DecodingTable[(int)input[index + 3]]);
     
     if ( buffer ) {
      buffer[bufferIndex] = b3;
     }
     
     bufferIndex++;
    }
    index += 4;
   }
  }
  bufferSize = bufferIndex;
 }

 static char* base64EncodingTable;
 static char base64DecodingTable[];
};

char* Base64Data::base64EncodingTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char Base64Data::base64DecodingTable[] = {
           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};
代码没测试,我直接贴过来的。


--  作者:equalto
--  发布时间:11/21/2006 4:15:00 PM

--  
个人认为,
(The Base64 Content-Transfer-Encoding is designed to represent arbitrary sequences of octets in a form that need not be humanly readable.)
应该翻译为:
base64(内容传输编码)是被设计来表现“任意字节序列”的数据,它的表现形式,“!!不需要!!”可以有很好的阅读性。


不同的意见在于:
a、我认为它仅仅是一个编码格式(或者说转码),而不是加密格式
b、它的阅读性不好,不是因为故意要这样设计,而是它设计来,就不是为了满足人的直接阅读需要的。

至于说它产生的原因,可能是为了能用<=127内的asc字符来表示所有的数据吧。


--  作者:siberiarabbit
--  发布时间:1/8/2009 12:50:00 PM

--  
Thank you for your sharing!
W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
1,731.445ms