Punycode

ドメイン基礎
Unicode ドメイン名を ASCII 互換形式に変換するエンコーディング システム。国際化ドメイン名が DNS で機能することを可能にします。
← 用語集に戻る

Punycodeとは

PunycodeはRFC 3492で定義されたエンコード構文で、Unicode文字列をDNSが扱える限定されたASCII文字集合へ変換します。既存のDNS基盤であらゆる言語のドメイン名を機能させる、国際化ドメイン名(IDN)の技術的基盤です。

Punycodeが解決する問題

Domain Name Systemは1980年代にASCII文字だけを前提として設計されました。DNSラベルに使えるのは次の文字だけです。

この制限は、主にラテン文字を使わない膨大な数のインターネット利用者を排除していました。Punycodeは任意のUnicode文字列を有効なASCIIへエンコードして、この差を埋めます。

Punycodeエンコードの仕組み

PunycodeはASCII文字を保持しながら、非ASCII文字をコンパクトなASCII表現にする巧妙なアルゴリズムを使います。

エンコード処理

1. 文字を分離する: ASCII文字と非ASCII文字に分ける

2. ASCIIをコピーする: ASCII文字を元の位置に保つ

3. 非ASCIIをエンコードする: 一般化された可変長整数エンコードを使う

4. 接頭辞を付ける: Punycodeエンコードを示す「xn--」を先頭に付ける

元の文字列(Unicode)エンコード後(Punycode)
münchenxn--mnchen-3ya
北京xn--fiqs8s
münchen.dexn--mnchen-3ya.de
中文.comxn--fiq228c.com
café.comxn--caf-dma.com
この表は、人が読むUnicode表記と、DNSで扱うPunycode表記の対応を示しています。

「xn--」接頭辞

「xn--」接頭辞はACE(ASCII Compatible Encoding)接頭辞と呼ばれます。DNSリゾルバーやアプリケーションに、そのラベルがPunycodeでエンコードされた内容を含むことを知らせます。この接頭辞には次の特徴があります。

実際の利用

ブラウザーの処理

現在のブラウザーはPunycodeを自動的に処理します。

User types: 中文.com

Browser sends: xn--fiq228c.com (to DNS)

Browser displays: 中文.com (in address bar)

開発者による実装

JavaScript(Node.js)による実装:
const punycode = require('punycode/');

// Encode to Punycode

const encoded = punycode.toASCII('münchen.de');

// Result: xn--mnchen-3ya.de

// Decode from Punycode

const decoded = punycode.toUnicode('xn--mnchen-3ya.de');

// Result: münchen.de

Python:
domain = 'münchen.de'

encoded = domain.encode('idna').decode('ascii')

# Result: xn--mnchen-3ya.de

URLの処理

IDNを含むURLを扱う場合:

// URL API handles Punycode automatically

const url = new URL('https://中文.com/path');

console.log(url.hostname); // xn--fiq228c.com

console.log(url.href); // https://xn--fiq228c.com/path

セキュリティへの影響

Punycodeは任意のUnicode文字を表現できるため、セキュリティリスクも生じます。

見た目を利用したなりすまし

攻撃者は、正規サイトと同じように見えるドメインを登録できます。

аррlе.com (Cyrillic 'а' and 'р')

apple.com (Latin letters)

フォントによっては同じ表示になりますが、実際には異なるドメインです。

ブラウザーの保護機能

なりすましに対処するため、ブラウザーは次の保護を実装しています。

1. 混在スクリプト検出: 複数の文字体系を不審に混ぜたドメインではPunycodeを表示する

2. 類似文字検出: ASCIIに見える文字を使うドメインに警告する

3. 許可リスト: 信頼されたTLDでだけUnicode表示を許可する

APIでPunycodeを扱う

ドメインツールを構築するときは、次の方針にします。

Punycodeを常に保存する: 一貫性とデータベース索引のため、内部ではASCII形式を使う。 両方の形式を受け付ける: 利用者がUnicodeとPunycodeのどちらでも入力できるようにし、必要に応じて変換する。 Unicodeを表示する: ユーザーインターフェースでは、人が読める形式を示す。
function normalizeDomain(input) {

const punycode = require('punycode/');

// Convert to lowercase Punycode for internal use

return punycode.toASCII(input.toLowerCase());

}

Punycodeは多くの利用者からは意識されませんが、国際化ウェブアプリケーションを構築する開発者には不可欠な知識です。

この知識を実践する

DomScan の API を使用してドメインの可用性、状態などを確認します。