您的位置:首页 > 大数据 > 人工智能

中文化和国际化问题权威解析之六:MIME编码/字符传输编码

2009-08-11 20:10 288 查看
 
MIME(Multipurpose Internet Mail Extensions)
是"多用途Internet邮件扩充协议"的缩写,在 MIME 协议之前,邮件的编码曾经有过 UUENCODE 等编码方式 ,但是由于 MIME
协议算法简单,并且易于扩展,现在已经成为邮件编码方式的主流,不仅是用来传输 8 bit 的字符,也可以用来传送二进制的文件
,如邮件附件中的图像、音频等信息,而且扩展了很多基于MIME 的应用。

当一段Text或者HTML通过电子邮件传送时,发送的内容首先通过一种指定的字符编码转化成"字节串",然后再把"字节串"通过一种指定的传输编
码(Content-Transfer-Encoding)进行转化得到另一串"字节串"。比如,打开一封电子邮件源代码,可以看到类似的内容:

Content-Type: text/plain; charset="gb2312"

Content-Transfer-Encoding: base64

sbG+qcrQuqO17cf4yee74bGjz9W7+b3wudzA7dbQ0MQNCg0KvPKzxqO6uqO17cnnsaPW0NDEDQoNCg==

最常用的 Content-Transfer-Encoding 有 Base64 和 Quoted-Printable
两种,另外还有一种叫BinHex,基本上是Mac专用。在对二进制文件或者中文文本进行转化时,Base64 得到的"字节串"比
Quoted-Printable 更短。在对英文文本进行转化时,Quoted-Printable 得到的"字节串"比 Base64
更短。因为Base64是对所有的字符(包括ASCII码)进行重新编码,而QP只针对非ASCII码进行编码。

对于邮件的标题,MIME用了一种更简短的格式来标注"字符编码"和"传输编码"。比如,标题内容为 "中",则在邮件源代码中表示为:Subject: =?GB2312?B?1tA=?=

其中:

第一个"=?"与"?"中间的部分指定了字符编码,在这个例子中指定的是 GB2312。

"?"与"?"中间的"B"代表 Base64。如果是"Q"则代表 Quoted-Printable。

最后"?"与"?="之间的部分,就是经过 GB2312 转化成字节串,再经过 Base64 转化后的标题内容。

如果"传输编码"改为 Quoted-Printable,同样,如果标题内容为 "中",则邮件源码为:

Subject: =?GB2312?Q?=D6=D0?=

下面就主要介绍下两种传输编码Base64、QP;

Base64

按照RFC2045的定义,Base64被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。

为什么要使用Base64?

在设计这个编码的时候,我想设计人员最主要考虑了3个问题:

1.是否加密?

2.加密算法复杂程度和效率

3.如何处理传输?

加密是肯定的,但是加密的目的不是让用户发送非常安全的Email。这种加密方式主要就是"防君子不防小人"。即达到一眼望去完全看不出内容即可。


于这个目的加密算法的复杂程度和效率也就不能太大和太低。和上一个理由类似,MIME协议等用于发送Email的协议解决的是如何收发Email,而并不
是如何安全的收发Email。因此算法的复杂程度要小,效率要高,否则因为发送Email而大量占用资源,路就有点走歪了。

但是,如果是基于以上
两点,那么我们使用最简单的恺撒法即可,为什么Base64看起来要比恺撒法复杂呢?这是因为在Email的传送过程中,由于历史原因,Email只被允
许传送ASCII字符,即一个8位字节的低7位。因此,如果您发送了一封带有非ASCII字符(即字节的最高位是1)的Email通过有"历史问题"的网
关时就可能会出现问题。网关可能会把最高位置为0!很明显,问题就这样产生了!因此,为了能够正常的传送Email,这个问题就必须考虑!所以,单单靠改
变字母的位置的恺撒之类的方案也就不行了。关于这一点可以参考RFC2046


基于以上的一些主要原因产生了Base64编码。

Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式。也就是说,转换后的字符串理论上将要比原来的长1/3。实例如下:

转换前 aaaaaabb ccccdddd eeffffff

转换后 00aaaaaa 00bbcccc 00ddddee 00ffffff

上面的三个字节是原文,下面的四个字节是转换后的Base64的二进制编码,其前两位均为0。 至此编码还没完成,转换后,我们还要用一个码表来得到我们想要的字符串(也就是最终的Base64编码),编码表(摘自RFC2045
)如下:

 

ValueEncodingValueEncodingValueEncodingValueEncoding
0A17R34i51z
1B18S35j520
2C19T36k531
3D20U37l542
4E21V38m553
5F22W39n564
6G23X40o575
7H24Y41p586
8I25Z42q597
9J26a43r608
10K27b44s619
11L28c45t62+
12M29d46u63/
13N30e47v  
14O31f48w(pad)=
15P32g49x  
16Q33h50y  
注意:码表最后的pad是专门用来在文档最后进行填充的,因为并非所有文档的字节数都是3的整数倍,如果遇到除不尽的情况,就用=来填充;

QP(Quote-Printable)

其原理是把一个 8 bit 的字符用两个16进制数值表示,然后在前面加"="。所以我们看到经过QP编码后的文件通常是这个样子:=B3=C2=BF=A1=C7=E5=A3=AC=C4=FA=BA=C3=A3=A1。

与Base64相比,QP的保密性要相对较低,因为他不对ASCII码进行重复编码,这样对于普通英文文档就相当于没有编码过,文档内容是完全可见的;这样也带来一个优势,就是对于英文字符占多数的文档编码后文件大小不会增加太多;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息