UTF-7

UTF-7（全称：7位元Unicode转换格式）是一种可变长度字元编码方式，用以将Unicode字元以ASCII编码的字元串来呈现，可以应用在电子邮件传输之类的应用。

SMTP为基本的电子邮件传输标准之一，其指明了传输格式为US-ASCII，并且不允许超过ASCII所定义的字元范围以外的位元值，也就是说八位元的字串将无法正常的被传输。MIME（RFC 2045 ~ 2049）扩展了网络邮件以支援不同的媒体类型以及字元集，包含UTF-8与UTF-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进位码｜0｜0｜0｜0｜0｜0｜0｜0｜1｜0｜1｜0｜0｜0｜1｜1｜0｜0

索引｜0｜10｜12

Base64编码｜A｜K｜M

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

### 编码

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

Unicode序列一旦被认定后，其必须以下面的程序来加以编码，并以适当的符号加以标注：

我们将使用£† (0x00A3) (0x2020)字元序列来作为以下的范例。

- 将字元的Unicode数值 (UTF-16)以二进制呈现：`0x00A3 → 0000 0000 1010 0011``0x2020 → 0010 0000 0010 0000`
- 将二进制序列合并`0000 0000 1010 0011 及 0010 0000 0010 0000 → 0000 0000 1010 0011 0010 0000 0010 0000`
- 重新将二进制序列编组，以六位数为一组，由左开始：`0000 0000 1010 0011 0010 0000 0010 0000 → 000000 001010 001100 100000 001000 00`
- 如果最后一组小于六位数，则不足的位数以0补足尾数：`0000 0000 1010 0011 0010 0000 0010 0000 → 000000 001010 001100 100000 001000 000000`
- 将每一组六位数的数值以对应的Base64码取代：`000000 001010 001100 100000 001000 000000 → AKMgIA`

### 解码

首先讯息必须被拆分到纯文字与Unicode区块，紧接着Unicode区块必须以下面的程序来进行解译（使用上面提到的范例）：

- 将每一个Base64码以二进制序列来描述，如下：AKMgIA → 000000 001010 001100 100000 001000 000000
- 重新将二进制编组，以使其16位数一组，从左开始：000000 001010 001100 → 0000000010100011 0010000000100000 0000
- 若有其中一组无法完全编成16位数一组，则先排除它：0000000010100011 0010000000100000
- 每一个16位元的一组二进制码为Unicode（UTF-16）的数字字元并且可以被改写为如下：0000 0000 1010 0011 ≡ 0x00A3 ≡ 16310

### 安全性

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

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

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

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

这些提案与Punycode并无相关。