Base64编码简介

  本文介绍基于rfc4648的Base64编码格式,关于如何使用Python中的base64模块快速进行编码,请参考这里。rfc4648介绍了Base64/32/16编码机制,同时废止了rfc3548。相关的资料和标准有:rfc2045定义了MIME中的Base64传输编码,rfc4880定义了OpenPGP中使用的Radix-64编码

  Base64使用64个通用的可打印字符来存储和表示二进制字数据,同时也可以进行简单的加密,生成不可读文本。Base64字符集包括大、小写英文字母,阿拉伯数字0-9,以及"+"和"/",以及作后缀填充的"="共计65个字符,其中编码时只使用前64个。如何使用这64个字符来表示二进制数据呢?这就需要在十进制的0到63以及使用的64个字符之间建立一一对应关系。具体的映射是将十进制的0到63依次与"A-Z", "a-z", "0-9", "+", "/"一一对应。在计算机中64种可能只需要6bits就能表达(26=64),因此Base64表示法实质上是以6bits为单位,使用规定的通用字符集来表示和存储二进制数据。

  计算机中的数据是以字节为单位的,且8bits = 1byte。Base64中使用6bits表示一个字符,这就导致了计算机中的三个字节(8bits*3)在经过Base64编码后将变成四个字符(6bits*4),转码后的Base64字符串将比原数据长大约三分之一。Base64的转码方法也正是围绕这样的换算关系展开。

  转码时只需使用一个24bits的缓冲区,依次从原数据中读入三个字节的数据,再每次从缓冲中取6bits转化成Base64字符输出。当原始数据的长度恰好为3bytes的整数倍时,直接转码。当读取到原始数据的末尾剩余数据不足3字节时,在原始二进制码末尾补0直到恰好是6bits的倍数,这时,第65个字符"="就派上用场了。如果原始文本刚好是3字节的整数倍,转码后不需要在Base64编码末尾添加任何后缀;如果最后剩余两字节,则在转码后的字串末尾添加一个"=",如果最后剩余一字节,则在转码后的字符串末尾添加两个"="。这个过程可以用下面的图表示。

  

  情形一:文本长度刚好是3字节的整数倍

原文本(单位:字节) M a n
二进制数据 0 1 0 0 1 1 0 1 0 1 1 0 0 0 0 1 0 1 1 0 1 1 1 0
二进制数据(补0) 0 1 0 0 1 1 0 1 0 1 1 0 0 0 0 1 0 1 1 0 1 1 1 0
Base64编码  T

 

 

 

 

 

此时转码后的字串将为:TWFu

 

  情形二:文本比3字节的整数倍多2字节

原文本(单位:字节)

M a  

二进制数据

0 1 0 0 1 1 0 1 0 1 1 0 0 0 0 1                

二进制数据(补0后)

0 1 0 0 1 1 0 1 0 1 1 0 0 0 0 1 0 0            

Base64编码

 T E  

 

 

 

 

 

 

 

此时转码后的字串将为:TWE=

 

  情形三:文本比3字节的整数倍多1字节

原文本(单位:字节)

M    

二进制数据

0 1 0 0 1 1 0 1                                

二进制数据(补0后)

0 1 0 0 1 1 0 1 0 0 0 0                        

Base64编码

 T    

 

 

 

 

 

 

 

此时转码后的字串将为:TQ==

  经过上面规则编码后的字串解码也非常简单。不难发现,由于每一填充符"="代表二进制源码末尾添加了2bits的0,Base64编码后字串的长度将是4的整数倍,根据末尾"="的个数计算编码过程中补0的个数,就可以正常解码。另外,在电子邮件中,每行不能容纳超过76个字符,解析时注意忽略回车符。

  本文介绍了标准Base64编码的格式,事实上还存在“安全url”等变种编码格式,这些变化适应特定的需求,替代字符集中的部分字符,有兴趣的话可以参考rfc4648

  Python中基于rfc3548提供了进行Base64/32/16编码的库,接口非常高效地实现了所需的编码。关于Python中的Base64编码库,请参考这里。

  

posted @ 2014-07-17 22:15  王智愚  阅读(989)  评论(0编辑  收藏  举报