java IDN 功能不可逆?

java IDN functions not reversible?

为什么有些国际化域名不可逆:

String domain = "aʼnċăwb7rňuħ.eu";
System.out.println(domain);
domain = IDN.toASCII(domain);
System.out.println(domain);
domain = IDN.toUnicode(domain);
System.out.println(domain);

它显示:

aʼnċăwb7rňuħ.eu
xn--anwb7ru-93a5e8ozmq2m.eu
aʼnċăwb7rňuħ.eu

如您所见,第二个字符已被拆分!

谢谢

IDN 到 ASCII 的过程本质上是不可逆的,因为它涉及执行 Unicode 规范化(以形成 NFKC)作为过程的一部分。通常,多个 Unicode 字符序列可以具有相同的规范化形式; IDN 到 Unicode 程序将从 ACE 标签中生成 一个 这些形式,但不能保证它与最初编码的形式相同。

如果 toUnicode(toASCII(x)) 的结果确实与 x 不同,那么对于 IDN 而言,两者仍然是等效的,而且它们应该是彼此等效的 Unicode 兼容性。一般来说,它们会被 Unicode 字体类似地渲染。从这个意义上说,您的情况存在明显差异有点令人惊讶,但归根结底,您对可逆性的明显期望是没有根据的。

这是设计使然。据我所知,字符串中的第二个字符是 \u0149 代码点。根据最新的Unicode码表:

this character is deprecated and its use is strongly discouraged

Unicode 代码表表示弃用代码点相当于 \u02bc 后跟 \u006e

根据 javadocs,IDN.toASCII(String) 所做的第一步是使用 RFC 3491 stringprep / nameprep 算法来处理输入字符串中的字符。 RFC 摘要说:

This document describes how to prepare internationalized domain name (IDN) labels in order to increase the likelihood that name input and name comparison work in ways that make sense for typical users throughout the world. This profile of the stringprep protocol is used as part of a suite of on-the-wire protocols for internationalizing the Domain Name System (DNS).

(换句话说,stringprep 旨在让创建看起来像一回事但含义不同的棘手域名变得更加困难。)

事实上,如果你向下钻取,你会发现在 stringprep 表中规定的 \u0149 的映射是 \u02bc \u006e ;即 Unicode 代码表中定义的等价物。

而且...这就是正在发生的事情。


总结

  1. 您期望可以往返国际化域名是没有根据的。
  2. 您无论如何都不应该使用该字符,因为它已被弃用。 (当然,在 IDN 中使用它是个坏主意!)