Punycode 转换工具(中文域名 IDN)

按 RFC 3492 的 Bootstring 算法,在 Unicode 域名与 ACE 串(xn-- 前缀)之间双向转换。域名按点拆开逐标签处理,只有含非 ASCII 的标签才加前缀,已经带 xn-- 的不会重复编码。

只有含非 ASCII 的标签才加 xn-- 前缀,纯 ASCII 标签原样保留,域名按点逐标签处理。
中国 → xn--fiqs8s 方向:编码(Unicode → ACE) 标签数:1;最长标签 10 字符(上限 63) -- 批量 -- 中国 → xn--fiqs8s 北京 → xn--1lq90i 例え.テスト → xn--r8jz45g.xn--zckzah bücher → xn--bcher-kva café → xn--caf-dma xn--fiqs8s → xn--fiqs8s

默认示例:中国 编成 xn--fiqs8s。输入、方向、上限、大小写任意一项改动即重新计算,光标停在输入框里按回车同样触发一次。

使用方法

  1. 「域名或字符串」默认填「中国」,光标停在这个框里直接按回车就转换一次,改动内容也会立刻重算,不必点按钮。
  2. 「转换方向」有两项:编码是把 Unicode 域名转成带 xn-- 前缀的 ACE 串,解码是把 ACE 串翻回 Unicode。默认编码方向,用来生成注册商表单里那串 ASCII;点「反向」把两项对调。
  3. 「标签长度上限校验」默认 63,范围 1 到 63。DNS 规定单个标签最多 63 字符,超了会直接报错并给出实际长度。
  4. 「ACE 输出大小写」默认 0(小写),可填 1(大写)。RFC 3492 的数字值大小写不敏感,A 与 a 是同一个值,所以这个选项只改显示形态,不改编码内容。
  5. 「批量转换」默认写好六行示例,每行一条域名,按 Ctrl+Enter(Mac 上是 Cmd+Enter)一次算完;万一被清空,点转换时会自动填回这六行。
  6. 结果区第一行是「输入 → 输出」,下面跟着方向、标签数与最长标签长度,再下面是批量结果逐行列出,方便直接粘进注册商表单或证书申请。
  7. 结果下面是一张 20 行的自检表,把 12 个常见域名与 8 个长度样本各转一遍并做往返校验,默认显示 6 行,点「加载更多」展开全部,点「导出 CSV」存成带字节序标记的表格文件。
  8. 输入为空、出现空标签、解码方向缺 xn-- 前缀、遇到非法字符、数字序列被截断、转换结果超过标签上限,每一条都会给出针对该情况的具体提示。

这个 Punycode 转换工具能解决什么问题

第一类是注册与解析的口径差。注册商的域名表单只收 ASCII,直接填「中国」会被拒;DNS 报文里的标签也只允许字母、数字和连字符。Punycode 就是把 Unicode 码点编成这套 ASCII 的桥:中国 编出来是 xn--fiqs8s,拿这串去填表单、写解析记录、申请证书才能通过。

第二类是多标签域名的拆分错误。域名按点分成若干标签,Punycode 是对每个标签单独算的,不是对整串算。例え.テスト 有两个标签,正确结果是 xn--r8jz45g.xn--zckzah;如果把整串当一个标签喂给编码器,产出的东西既注册不上也解析不出来。本页默认按点逐标签处理。

第三类是日志与排障。浏览器地址栏、证书里的 CN 与 SAN、DNS 查询日志里出现的往往已经是 xn-- 串,看不出原域名是哪一个。把 xn--r8jz45g.xn--zckzah 贴进来切到解码方向,就能确认它到底对应哪个域名,也能顺手核实证书签的是不是你要的那个名字。

第四类是重复编码。已经带 xn-- 前缀的串再编码一次,会叠成双重前缀,注册与解析都会失败。本页只对含非 ASCII 的标签加前缀,纯 ASCII 与已带 xn-- 的输入原样返回,绝不叠第二层前缀。

这个工具在本站也叫「Punycode转换器」,Punycode 是 RFC 3492 定义的那套把 Unicode 编成 ASCII 的 Bootstring 算法。

计算原理与变量说明

RFC 3492 把这套算法叫 Bootstring,参数一共八个:base = 36、tmin = 1、tmax = 26、skew = 38、damp = 700、初始 bias = 72、初始 n = 128、分隔符是连字符。base 是进位基数,36 对应 26 个字母加 10 个数字;tmin 与 tmax 是每一位数字取值的下限与上限;skew 与 damp 控制 bias 的收敛速度。

编码第一步是把输入里所有小于 128 的码点原样抄进输出,这些叫基本字符;只要抄出了至少一个基本字符,就在后面补一个连字符当分隔符。bücher 的基本字符是 b、c、h、e、r 五个,所以输出以 bcher- 开头;中国 没有基本字符,所以没有分隔符,输出直接是 fiqs8s。

接着按码点从小到大处理非 ASCII 字符。每一轮先在当前未处理的码点里找最小值 m,把 delta 累加 (m - n) × (h + 1),其中 n 是上一轮的码点(初始 128),h 是已经处理完的字符数;然后对每一个等于 m 的字符输出一个变长整数:每步取阈值 t(k 小于等于 bias 时取 tmin,k 大于等于 bias + tmax 时取 tmax,否则取 k 减 bias),用 base 减 t 作除数把 delta 拆成若干位数字,最后以一位小于 t 的数字收尾。

数字与字符的对应很直接:0 到 25 写成 a 到 z,26 到 35 写成 0 到 9;反过来解析时大写与小写同值,A 与 a 解出的结果一样,这正是 RFC 3492 说的解码对大小写不敏感。

bias 的更新由 adapt 负责:d 先取首次调用时的 delta 整除 700、之后取 delta 整除 2,再自加 d 整除 numpoints;然后只要 d 还大于 (36 - 1) × 26 / 2 的整除结果 455,就反复做 d 整除 35 并让 k 累加 36;最后返回 k 加上 36 × d / (d + 38) 的整除结果。damp 700 只在第一次生效,作用是把开头一批字符的定位开销摊薄。

xn-- 不是编码内容。它是 ACE(ASCII Compatible Encoding)前缀,四个字符固定不变,解码时先剥掉再跑 Bootstring。所以同一个域名在不同系统里可能写成小写或大写形式,前缀形态不同但编码内容一致。

域名级处理按点切标签。转换时把输入按点拆开逐个判断:只有含非 ASCII 字符的标签才加 xn--,已经是 xn-- 开头的不重复转换。www.liuquan.net 三个标签全是 ASCII,结果就是原串;例え.テスト 两个标签都要编码,结果是 xn--r8jz45g.xn--zckzah。

63 这个上限来自 DNS 报文格式。单个标签的长度字段只有 6 位,最大值 63;整个域名的总长上限是 253。中华人民共和国 编码后是 xn--fiq4mp3eqscr2bfxgex2c,最长标签 25,仍在 63 以内,但汉字再往上加就会很快顶到边界。

完整示例

默认示例是 中国。它没有基本字符,输出不带分隔符,结果是 xn--fiqs8s;再解回来仍是 中国,往返一致。

把输入改成 北京,得到 xn--1lq90i;改成 上海 得到 xn--fhqz97e,改成 香港 得到 xn--j6w193g。三个都是两个汉字,编码长度各不相同,因为 Punycode 编的是码点序号与插入位置,不是字符个数。

输入 例え.テスト:两个标签分别编码,得到 xn--r8jz45g.xn--zckzah,最长标签 11。整串当一个标签编码,产出的串分隔符位置会不对。

带基本字符的情况:bücher 得到 xn--bcher-kva(bcher 是基本字符,kva 编的是 ü 的位置);münchen 得到 xn--mnchen-3ya;café 得到 xn--caf-dma;ñandú 得到 xn--and-6ma2c;äöü 得到 xn--4ca0bs。

不需要转换的五种:example、liuquan、a-b-c、www.liuquan.net、xn--fiqs8s,输出与输入逐字相同。批量框默认六行的最后一行就是 xn--fiqs8s,专门用来验证这一点。

切到解码方向,输入 xn--fiqs8s 得到 中国;输入 xn--r8jz45g.xn--zckzah 得到 例え.テスト;输入 xn--fiq4mp3eqscr2bfxgex2c 得到 中华人民共和国。批量框同样按解码方向逐行处理,但每一行都必须带 xn-- 前缀。

Punycode 与 ACE 对照表

第一张表是 12 个常见域名的编码结果,第三列是把 ACE 再解回 Unicode 的回解值,用来确认往返没有改掉字符。

域名(Unicode)ACE(xn--)回解
中国xn--fiqs8s中国
北京xn--1lq90i北京
上海xn--fhqz97e上海
香港xn--j6w193g香港
淘宝xn--pbt173b淘宝
腾讯xn--r70as2s腾讯
亚马逊xn--jlq480n2rg亚马逊
例え.テストxn--r8jz45g.xn--zckzah例え.テスト
bücherxn--bcher-kvabücher
münchenxn--mnchen-3yamünchen
caféxn--caf-dmacafé
ñandúxn--and-6ma2cñandú

第二张表看长度。单个标签上限 63 字符,整个域名上限 253 字符;「最长标签」取的是转换后各标签里最长的那一个。

输入转换结果最长标签
中国xn--fiqs8s10
中华人民共和国xn--fiq4mp3eqscr2bfxgex2c25
例え.テストxn--r8jz45g.xn--zckzah11
bücherxn--bcher-kva13
aa1
verylongchinesedomainlabelverylongchinesedomainlabel26
xn--fiqs8sxn--fiqs8s10
xn--1lq90ixn--1lq90i10

读第一张表看逐标签:例え.テスト 这一行的 ACE 里有两个 xn--,正是两个标签各转一次的结果。读第二张表看长度:中华人民共和国 编完是 25 个字符,汉字越多增长越快,八个汉字就已经吃掉 63 的一大半。

结果边界、舍入与适用说明

常见问题

中文域名一定要转成 xn-- 才能注册吗?

提交给注册商与 DNS 的那串必须是 ASCII,所以需要转。浏览器地址栏里输入中文是另一回事:浏览器先按 IDNA 把 Unicode 映射并规范化,再编码成 xn-- 发往 DNS,地址栏通常仍显示中文。两边看到的不是同一串字符,但指向同一个域名。

为什么 例え.テスト 转出来有两个 xn--?

因为域名按点切标签后逐个转换,每个含非 ASCII 的标签各加一次前缀。例え 编成 xn--r8jz45g,テスト 编成 xn--zckzah,拼起来就是 xn--r8jz45g.xn--zckzah。把整串当一个标签编码会得到错误结果。

xn-- 串为什么有的地方大写有的地方小写?

RFC 3492 规定解码对大小写不敏感:0 到 25 既可以是 a 到 z 也可以是 A 到 Z,26 到 35 是数字,所以两种写法解出的是同一个域名。惯例输出用小写,本页的大小写选项只为对齐某些系统的显示形态。

已经带 xn-- 的域名再转一次会怎样?

不会重复编码。转换时逐个标签判断,标签里没有非 ASCII 字符就不加前缀,所以 xn--fiqs8s 的结果还是 xn--fiqs8s。如果手工在前面再拼一个 xn--,整串会被当成普通 ASCII 原样保留,注册时同样失败。

单个标签 63 字符够用吗?中文域名能放几个字?

63 是 DNS 报文里标签长度字段的硬上限。中文域名编码后每个汉字约占 4 到 5 个字符:中国 是 10,中华人民共和国 是 25。按这个速率单个标签大约能放十几个汉字,超了本页会直接给出实际长度。

解码时提示「非法字符」是怎么回事?

说明剥掉 xn-- 后剩下的串里有不属于 base36 数字表的字符。合法字符只有 a 到 z、A 到 Z、0 到 9 和作为分隔符的连字符。常见原因是复制时被截断、多了标点空格,或把 Unicode 域名直接丢进了解码方向。

这个工具免费吗?

免费,无需注册即可使用。

输入的数据安全吗?

安全。转换在当前浏览器本地完成,不会上传输入内容。

相关工具