UTF-7

UTF-7(全称:7比特Unicode转换格式)是一种可变长度字符编码方式,用以将Unicode字符以ASCII编码的字符串来呈现,可以应用在电子邮件传输之类的应用。

SMTP为基本的电子邮件传输标准之一,其指明了传输格式为US-ASCII,并且不允许超过ASCII所定义的字符范围以外的比特值,也就是说八比特的字符串将无法正常的被传输。MIMERFC 2045 ~ 2049)扩展了网络邮件以支持不同的媒体类型以及字符集,包含UTF-8UTF-16的字符集皆可被指定使用。但由于MIME并未明确将Unicode定义为可支持的字符集,并且也没有说明其应如何编码,这使得既有的SMTP传输架构下仍旧无法保证可正确的处理8比特数据。base64编码也有其问题,例如甚至连纯英文的US-ASCII字符也可能会变成不可辨认;至于像是UTF-8与quoted-printable的编码结合,则需要6~9个比特来为非ASCII的字符(Unicode的基本多文种平面中定义的字符)进行编码,至于在基本多文种平面(BMP)以外的字原则需要多达12比特的长度才能完成编码。

简介

UTF-7首次被提出是在一个实验性的通信协定里(RFC 1642,A Mail-Safe Transformation Format of Unicode),这份RFC(Request for Comments)提案后来因RFC 2152的提出而被取代(RFC 2152本身为新闻型(informational)的文案)。在RFC 2152当中明确的指出该份RFC本身不为互联网的标准做出任何明确的定义(明列于文案前头的Status of this Memo)。尽管这份RFC 2152在IANA(Internet Assigned Numbers Authority)的字符集列表里被引述为UTF-7,然而UTF-7本身并非Unicode的标准之一,即使在目前最新的Unicode 5.0里也仅列出UTF-8、UTF-16和UTF-32。

如同引言所提到的,由于在过去SMTP的传输仅能接受7比特的字符,而当时Unicode并无法直接满足既有的SMTP传输限制,在这样地背景下UTF-7被提出。严格来说UTF-7不能算是Unicode所定义的字符集之一,较精确的来说,UTF-7是提供了一种将Unicode转换为7比特US-ASCII字符的转换方式。

有些字符本身可以直接以单一的ASCII字符来呈现。第一个群组被称作「direct characters」,其中包含了62个数字与英文本母,以及包含了九个符号字符:' ( ) , - . / : ?。这些「direct characters」被认为可以很安全的直接在文档里呈现。另一个主要的群组称作「optional direct characters」,其中包含了所有可被打印的字符,这些字符在U+0020~U+007E之间,除了~ \ +和空白字符以外。这些「optional direct characters」的使用虽可减少空间的使用也可增加人的可阅读性,但却会因为一些不良设计的邮件闸道而会产生一些错误,导致必须使用额外的转义字符。

空白字符、Tab字符、以及换行字符一般虽也可直接是为单一的ASCII字符来使用,然而,若是邮件中有使用了编码过的字符串,则必须特别注意这些字符有无被使用在其他地方。而加号字符+的一种编码方式可以+-

其他的字符则必须被编码成UTF-16然后转换为修改的Base64。这些区块的开头会以+符号来标示,结尾则以任何不在Base64里定义的字符来标示。若是在Base64区块之后使用-(连字暨减号)标示为结束的话,则解码器会从下个字符继续解码,反之则用此字符当非Base64的区块的开头继续解码。

范例

  • "Hello, World!"会被编码为"Hello, World!"
  • "1 + 1 = 2"会被编码为"1 +- 1 +AD0 2"
  • "£1"会被编码为"+AKM-1".第一个字符£(英镑的符号)的Unicode码为U+00A3(在UTF-16即为00A316),接着转换至修改的Base64格式,如同下表。表中可见有两个比特多了出来,被以0填补上。
16进位码 0 0 A 3  
2进位码000000001010001100
索引 0 10 12
Base64编码 A K M

手动编码与解码UTF-7的算法

编码

首先必须先决定哪些字符呈现为ASCII格式,哪些字符呈现在Unicode区块。简单的编码器可以假设所有的字符皆可以很安全的被直接编码。然而要将原本属于Unicode区块的字符视为ASCII来加以编码的代价是需要额外的2⅔字符。

Unicode串行一旦被认定后,其必须以下面的进程来加以编码,并以适当的符号加以标注:

我们将使用£† (0x00A3) (0x2020)字符串行来作为以下的范例。

  1. 将字符的Unicode数值 (UTF-16)以二进位呈现:
    0x00A3 → 0000 0000 1010 0011
    0x2020 → 0010 0000 0010 0000
  2. 将二进位串行合并
    0000 0000 1010 0011 及 0010 0000 0010 0000 → 0000 0000 1010 0011 0010 0000 0010 0000
  3. 重新将二进位串行编组,以六位数为一组,由左开始:
    0000 0000 1010 0011 0010 0000 0010 0000 → 000000 001010 001100 100000 001000 00
  4. 如果最后一组小于六位数,则不足的位数以0补足尾数:
    0000 0000 1010 0011 0010 0000 0010 0000 → 000000 001010 001100 100000 001000 000000
  5. 将每一组六位数的数值以对应的Base64码取代:
    000000 001010 001100 100000 001000 000000 → AKMgIA

解码

首先消息必须被拆分到纯文本与Unicode区块,紧接着Unicode区块必须以下面的进程来进行解译(使用上面提到的范例):

  1. 将每一个Base64码以二进位串行来描述,如下:
    AKMgIA → 000000 001010 001100 100000 001000 000000
  2. 重新将二进位编组,以使其16位数一组,从左开始:
    000000 001010 001100 → 0000000010100011 0010000000100000 0000
  3. 若有其中一组无法完全编成16位数一组,则先排除它:
    0000000010100011 0010000000100000
  4. 每一个16比特的一组二进位码为Unicode(UTF-16)的数字字符并且可以被改写为如下:
    0000 0000 1010 0011 ≡ 0x00A3 ≡ 16310

安全性

UTF-7由于允许将相同来源的字符串从base64的模式被平移,而显得安全性薄弱。现今的邮件与传输方式由于都已支持UTF-8,UTF-7则已走入历史而很少再被使用。即便如此,现今的应用软件仍应更加考量支持更安全的编码方式。

然而,除了邮件传输之外,仍有不少传输是采用UTF-7编码来进行传输。近期较著名的安全漏洞发生于Google的搜索漏洞[1],该漏洞肇因于不当的使用UTF-7编码于网址信息上,远程的攻击将可读取或修改网页内容。

尚未被完整开发的UTF-6和UTF-5

有些可应用于电信电报领域的UTF-6和UTF-5提案已经被提出[2][3],然而,截至2006年止,这些提案尚未被正式的制定出来。

这些提案与Punycode并无相关。

参考

  1. http://www.kb.cert.org/vuls/id/989144 页面存档备份,存于, Vulnerability Note VU#989144, Google Mini and Google Search Appliance vulnerable to cross-site scripting
  2. Seng, James, UTF-5, a transformation format of Unicode and ISO 10646 页面存档备份,存于, 28 Jan 2000, retrieved 23 Aug 2007
  3. Welter, Mark; Brian W. Spolarich, WALID, Inc. . Internet Engineering Task Force (IETF) INTERNET-DRAFT. The Internet Society. 2000-11-16 [2007-08-28]. (原始内容存档于2021-04-28).

相关条目

This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.