URI::UTF8::Punycode

Punycode

[2] Punycode は、DNS などのドメイン名Unicode文字符号化するために使われている算法 (アルゴリズム) です。 Punycode は任意の Unicode文字ASCII文字に転写し、旧来の DNS で扱える形にします。

仕様書

呼称

[60] RFC 5890 は、「Punycode 文字列」のような表現はその意図が不明確なため、 「Punycode」は算法 (アルゴリズム) であり、 それ以外の用法は非推奨 (discourage) とすると述べています >>59

[77] PunycodeNameprep や「xn--」を付加したXNラベルなど、 IDNA における他の処理も含めた総称として使われることがありますが、この用法は言及対象が不明瞭になってしまうので不適切です。 Punycode はあくまで Unicode 文字列ASCII 文字列に変換する方法のみを指して言うべきです。

[85] Punycode は「プニコード」、「ピュニコード」などと発音されます。

算法

[4] Punycode は、 Bootstring実現値です。

引数

[9] Punycode は、 Bootstring引数を次のように設定したものです >>1 5.

[10] base
36
[11] tmin
1
[12] tmax
26
[13] skew
38
[14] damp
700
[15] initialbias
72
[16] initialn
128 (0x80)

[17] これは Unicode符号位置に対して有効に機能するような引数の設定となっています。 (算法としての制約は非負整数の列が入力となることであり、 Unicode である必要はありません。) >>1 5.

[28] 復号器大文字小文字、その混合のいずれも認識しなければなりません符号化器大文字・小文字混合注釈を使う場合を除き、大文字のみ、または小文字のみを出力するべきです>>1 5.

型の大きさ

[32] IDNA 用途では、 26ビット符号無し整数を使うと (正当な入出力に対して) 桁溢れなく処理できます。26ビットあれば U+10FFFF まで、 63文字までのラベルを正しく扱えます。 >>1 6.4

[33] IDNA 以外でより長い文字列を扱いたい時、 U+10FFFF より先が含まれる ISO/IEC 10646 文字列 (やそれ以外の文字コード文字列) を扱いたい時には 26ビットでは足りないかもしれません。

大文字・小文字混合注釈

[29] Punycode大文字・小文字混合注釈が使えるようになっています。 >>1 5. (tmax が 26 で、25 以下はラテン文字なので、差分の最後の1文字は常に大文字小文字が存在するラテン文字になります。)

[30] ただし、ドメイン名では大文字・小文字不区別なので、大文字・小文字混合注釈も使われません。 >>1 5.

[55] 正確には、使わないというか、使う必要性がないという感じです。使っても構いません。

[56] IDNA2008 ではUラベルの定義上大文字小文字を混在させることに意味がなく、 Aラベルで使う Punycode符号化した文字列は小文字にするべきとされています >>57

符号化

[79] Punycode符号化は、 Bootstring符号化を、 Punycode引数を用いて実行する操作です。

[80] 入力はUnicode文字列で、出力Unicode文字列です。 出力は、ASCII文字の範囲の文字列になります。

[84] ToASCII から呼び出されます。

復号

[81] Punycode復号は、 Bootstring復号を、 Punycode引数を用いて実行する操作です。

[82] 入力はUnicode文字列で、出力Unicode文字列または失敗です。

[83] Unicode IDNA互換性処理から呼び出されます。

文字コードとしての Punycode

[61] PunycodeDNSラベルでの文字符号化に特化した算法であり、 汎用の文字コードよりはむしろ符号理論的な符号化情報圧縮の延長にある技術です。 汎用の文字コードは大抵の場合、文字の順序と符号化されたビット組合せの列の順序が同じである、 とある符号位置を表すビット組合せの列が前後の文脈によって著しく変化することがない、 任意の長さの文字列符号化復号することが容易である、 文字列の連結や一部分の取り出しが容易であるといった性質を備えていますが、 Punycode はこれらの性質を持っていません。

ASCII 文字列

[87] ASCII文字列Punycode符号化すると、 ASCII文字列の最後に - を追加した値となります。

[88] 実装によっては挙動がおかしいことがあります。 ASCII文字列ドメイン名に使うときは Punycode 符号化しないので、 発覚しないことが多いです。他の用途に転用するときは注意が必要です。

空文字列

[89] 空文字列Punycode符号化するとどうなるべきなのか不明瞭です。

[90] また -Punycode復号した結果が空文字列なのか、 エラーなのか、 - なのか、はっきりしません。

[91] これらもドメイン名では使わないので問題とはなっていないのですが、 他の用途に転用するときは要注意です。

ACE 接頭辞

[3] Punycode を表す ACE接頭辞は、 xn-- です RFC 3490 5.

実装

[53] RFC 3492 には C言語による実装例があります。通常の RFCライセンスよりも緩く、 自由な利用・改変・再配布が認められています (詳しくは RFC の附属書 B を参照)。 http://tools.ietf.org/html/rfc3492#appendix-B

[54] 実際に多くの言語による実装はこの実装例 (や本文中の擬似コード) を移植したもののようです。

[6] Net::IDN::Punycode - search.cpan.org http://search.cpan.org/dist/Net-IDN-Encode/lib/Net/IDN/Punycode.pm

[65] >>6 のバージョン 1.0 は XSPP も結果が変です。例えば U+0061 (a) U+1F62 (ὢ) U+03B9 (ι) U+0062 (b) の結果は ab-09b734z であるべきところ、 ab-ymt になります。

[5] Encode::Punycode - search.cpan.org http://search.cpan.org/dist/Encode-Punycode/lib/Encode/Punycode.pm

>>6 の単なるラッパーです。

[74] Mojo::Util - search.cpan.org ( 版) http://search.cpan.org/dist/Mojolicious/lib/Mojo/Util.pm#punycode_decode

[75] >>74>>65 と同じ現象が発生します。

[66] Claus Färber / IDNA-Punycode - search.cpan.org ( 版) http://search.cpan.org/dist/IDNA-Punycode/

[67] >>66 はバージョン1系は Net::IDN::PunycodeNet::IDN::Encode のラッパーです。バージョン0系は独自の実装です。バージョン0系は基本符号位置拡張符号位置を結ぶ 「-」の扱いが (どちらかが空文字列の時) 変です。

[70] URI::_punycode - search.cpan.org ( 版) http://search.cpan.org/dist/URI/URI/_punycode.pm

[71] これも「-」の扱いが変です。

[68] Twinkle Computing / URI-UTF8-Punycode - search.cpan.org ( 版) http://search.cpan.org/dist/URI-UTF8-Punycode/

[69] >>68復号結果の utf8フラグを立てません。

[72] Thomas Jacob / Net-LibIDN-0.12 - search.cpan.org ( 版) http://search.cpan.org/dist/Net-LibIDN/

[73] >>72 は入出力がバイト列で、 charset を明示的に指定しないといけません。 utf8フラグを立てません。

[76] Encode::Bootstring基本符号位置の設定方法がおかしく、 Punycode には使えません・・・。

歴史

[7] Punycode は当初 AMC-ACE-Z と呼ばれていました。

[8] IETFPunycode を用いることが決定するまでは、 RACEACE として採用される可能性が高いと考えられており、 実際に .com.jp など一部の TLDRACE を用いて IDN を運用していました。

[62] Punycode と同時に RFC 化された IDNA2003 は公式には IDNA2008 によって置き換えられましたが、 PunycodeIDNA2008 でも引き続きそのまま採用されています。

関連

Unicode との関係

[64] Punycode は (整数が十分大きいことを前提に) 任意の Unicode符号位置を扱えます。 PunycodeUnicode 用として定義されており、 各種引数の設定もそれに最適化されていますが、 Punycode (や Bootstring) の仕組み上は符号位置整数で表現可能な任意の符号化文字集合に適用できます。

Stringprep との関係

[63] IDNA2003 では StringprepPunycode が併用されますが、 両者には依存関係がありません。 IDNA 以外の用途で Stringprep を使わずに Punycode を使うことも理論上は可能です。

ラベルとの関係

[24] Bootstring算法Punycode引数の組み合わせからは、 ドメイン名ラベルで認められていない出力が得られることがあります。 あらゆる ASCII符号位置基本符号位置なのでそのまま結果に含まれていますし、 先頭や末尾が - になることもあります。ですが、

[34] エジプト語 RFC 3492 7.1 (A)

[35] 簡化字中国語 RFC 3492 7.1 (B)

[36] 伝統字中国語 RFC 3492 7.1 (C)

[37] チェコ語 RFC 3492 7.1 (D)

[38] ヘブライ語 RFC 3492 7.1 (E)

[39] ヒンディー語 (デバナガリ文字) RFC 3492 7.1 (F)

[40] 日本語 RFC 3492 7.1 (G)

[41] 韓国語 RFC 3492 7.1 (H)

[42] ロシア語 RFC 3492 7.1 (I)

[43] スペイン語 RFC 3492 7.1 (J)

[44] 越南語 RFC 3492 7.1 (K)

[45] RFC 3492 7.1 (L)

[46] RFC 3492 7.1 (M)

[47] RFC 3492 7.1 (N)

[48] RFC 3492 7.1 (O)

[49] RFC 3492 7.1 (P)

[50] RFC 3492 7.1 (Q)

[51] RFC 3492 7.1 (R)

[52] RFC 3492 7.1 (S)

メモ

[31] @IT:DNS Tips:Punycodeって小さなコード? http://www.atmarkit.co.jp/fnetwork/dnstips/022.html

[78] Punycodeのjavascript実装と変換テスト - Qiita ( ( 版)) https://qiita.com/weal/items/5c0ffefc44cfe7525cbe

[86] ものがたり - RFC 3492: one of the best joke (2007-05-26 02:02:45 +09:00 版) https://d.hatena.ne.jp/atsushieno/20070526/p1 (名無しさん )