はじめに
こんばんは、GMOコネクト 執行役員CTOの菅野 哲(かんの さとる)です。
今日ね、社内で「Punycode(ピュニコード)」について話したら、「なんすか?それ??」 と言われた。
…いや、わかる。確かに普段意識することは少ない。
でも、ブラウザのアドレスバーに「日本語.jp」と入力したとき、裏側で何が起きているか知っているだろうか? DNSは本来ASCII文字しか扱えない。では、なぜ日本語ドメインが動くのか?
その答えがPunycodeである。
実は我々が日常的に使っているインターネットの根幹を支える技術なのだ。「知らなくても困らないけど、知っていると世界の見え方が変わる」——そんな技術をエンジニアとして解説したいと思い、本記事を書くことにした。
この記事でわかること
- Punycodeの仕組みと、RFC 3492で定義されるBootstringアルゴリズムの動作原理
- IDNA2003からIDNA2008への変遷と、ToASCII/ToUnicode処理の詳細
- 日本語ドメインの登録状況(約82,000件)と具体的な変換例
- Homograph attack(同形異字攻撃)の脅威と、ブラウザごとの対策ポリシー
対象読者
- 「xn--」で始まるドメインを見て「なんだこれ?」と思ったことがある人
- 国際化ドメイン名(IDN)の仕組みを体系的に理解したいエンジニア
- セキュリティ視点でドメイン偽装リスクを把握したい人
Punycodeとは何か:30秒でわかる概要
Punycode(ピュニコード)は、Unicode文字列をASCII互換形式に変換するエンコーディング方式である。
日本語.jp → xn--wgv71a119e.jp
「puny」は英語で「小さい・弱々しい」という意味だが、技術的には「小さなコードで大きなUnicode空間を表現する」というニュアンスで命名されている。2003年にRFC 3492として標準化され、20年以上にわたりインターネットの国際化を支えてきた。
なぜ必要なのか?
DNSは歴史的経緯からASCII文字(a-z, 0-9, ハイフン)しか扱えない。しかし、世界中の人々が自国語でドメインを使いたいというニーズは当然ある。この「既存インフラを変えずに国際化対応する」という難題を解決したのがPunycodeだ。
RFC仕様の全体像と変遷
関連RFCの系譜
Punycodeの基盤となるRFC 3492「Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)」は、2003年3月にAdam M. Costello(UC Berkeley)により発行された。
IDNAフレームワークはその後大きく進化し、現在はIDNA2008と呼ばれる改訂版が主流となっている。
| 世代 | RFC群 | 発行年 | 主要内容 |
|---|---|---|---|
| IDNA2003 | RFC 3490, RFC 3491, RFC 3492 | 2003年 | 初代IDNA仕様、Nameprep正規化、Punycode |
| IDNA2008 | RFC 5890, RFC 5891, RFC 5892, RFC 5893 | 2010年 | 定義/フレームワーク、プロトコル、コードポイント、Bidi規則 |
IDNA2003 → IDNA2008 の主要変更点
IDNA2008ではIDNAbis Working Groupが仕様策定を担当した。主要な技術変更は以下の通り:
| 項目 | IDNA2003 | IDNA2008 |
|---|---|---|
| Unicode依存 | バージョン3.2固定 | プロパティベースのルール(バージョン非依存) |
| 正規化形式 | NFKC | NFC |
| マッピング処理 | プロトコル内 | プロトコル外(ローカル処理) |
| 「ß」の扱い | 「ss」にマッピング | 独立文字として保持 |
| 「ς」の扱い | 「σ」にマッピング | 独立文字として保持 |
特に「ß」(Eszett)や「ς」(Greek Final Sigma)が独立文字として扱われるようになった点は、ドイツ語・ギリシャ語ドメインに実質的な影響を与えた。
実装上の注意: IDNA2003とIDNA2008では同じ入力文字列が異なるPunycode出力になる場合がある。レガシーシステムとの互換性を考慮する際は要注意。
Bootstringアルゴリズムの動作原理
ここからが本記事の核心部分だ。PunycodeはBootstringアルゴリズムの特定パラメータ実装である。
アルゴリズムの4つの柱
RFC 3492で定義されるこのアルゴリズムは、以下の4つの技術を組み合わせて効率的なエンコーディングを実現する:
1. 基本コードポイント分離
入力文字列中のASCII文字(0x00-0x7F)をそのまま出力先頭にコピーし、非ASCII文字が存在すればデリミタとしてハイフン「-」を追加する。
入力: bücher
↓
ASCII部分抽出: bcher
↓
デリミタ追加: bcher-
2. 挿入非ソートコーディング
非ASCII文字をコードポイントの数値順で処理する。同一スクリプト(例:ひらがな U+3040-U+309F)の文字が近接するため、差分値が小さくなるよう最適化される。
3. 可変長整数エンコーディング
閾値を使って終端を検出し、複数の整数を区切りなしで表現する。Base36(a-z: 0-25, 0-9: 26-35)を使用。
4. バイアス適応
各デルタ値のエンコード後にバイアスを再計算し、次のデルタの予測精度を高める。
Punycodeのパラメータ値
base = 36
tmin = 1
tmax = 26
initial_bias = 72
initial_n = 128 // 最初の非ASCII文字のコードポイント開始点
damp = 700 // 初回ダンピング係数
【具体例】「bücher」の変換過程
ドイツ語で「本」を意味する「bücher」を例に、変換過程を追跡しよう。
Step 1: ASCII文字の抽出
bücher → bcher(ü以外のASCII文字を抽出)
Step 2: デリミタ追加
bcher → bcher-(非ASCII文字が存在するため)
Step 3: 非ASCII文字の処理
ü (U+00FC = 252) について:
- reduced_codepoint = 252 - 127 = 125
- 挿入位置 = 1(bの後)
- 挿入可能位置数 = 6
- デルタ = 6 × 124 + 1 = 745
Step 4: 可変長整数エンコード
745 → kva
最終出力
bcher-kva
ACEプレフィックス付き: xn--bcher-kva
「xn--」プレフィックスの謎
なぜ「xn--」なのか?
ACE(ASCII Compatible Encoding)プレフィックスの「xn--」は、RFC 3490標準化時にIANAによりランダム選定された。
「eXtended Names」の略称という説は誤りである。
選定時の考慮事項:
- 「bl--」「bq--」など既存で使用済みのプレフィックスを除外
- 将来のエンコーディング方式変更時に新プレフィックスへ移行可能とする設計
- 既存DNSインフラを変更せずに国際化ドメイン名をサポート
この設計により、DNSサーバーやリゾルバは従来のASCII処理のまま動作し、変更不要となった。エレガントな後方互換性の確保だ。
IDNAフレームワークとToASCII/ToUnicode処理
処理の全体像
IDNAの核心はアプリケーション層での処理にある。
[ユーザー入力] [DNS通信] [表示]
日本語.example → xn--wgv71a.example → 日本語.example
ToASCII ToUnicode
ブラウザ等のクライアントアプリケーションがToASCII操作を適用し、Punycode形式に変換してからDNSクエリを送信する。DNSサーバーは何も変わらない。
ToASCII操作の8ステップ
- ASCII判定: 全文字がASCII(0x00-0x7F)ならStep 3へスキップ
- Nameprep処理: マッピング(大文字→小文字)、NFKC正規化、禁止文字チェック、Bidi検証
- STD3 ASCII規則チェック: LDH(Letter-Digit-Hyphen)以外を禁止
- ASCII再判定: 正規化後に全ASCII化されていればStep 8へ
- ACEプレフィックス確認: 既に「xn--」で始まるならエラー
- Punycodeエンコード: Bootstringアルゴリズム適用
- ACEプレフィックス付加: 「xn--」を先頭に追加
- 長さ検証: 1-63コードポイント以内
Unicode正規化とNAMEPREP
IDNA2003ではStringprep(RFC 3454)のプロファイルである**NAMEPREP(RFC 3491)**を使用し、Unicode 3.2固定でNFKC正規化を適用する。
例:Å (U+212B, Angstrom Sign)
→ Å (U+00C5, Latin Capital Letter A With Ring Above)
→ 同一コードポイントに統合
IDNA2008では正規化がNFCに変更され、マッピング処理はプロトコル外のローカル処理に分離された。これによりUnicodeバージョン依存が解消され、将来のUnicode更新への追従が容易になった。
日本語ドメインの実装と登録状況
JPRSの対応経緯
| 年月 | イベント |
|---|---|
| 2000年12月 | JPRS設立 |
| 2002年4月 | JPNICからJPドメイン名登録管理業務を移管 |
| 2003年7月 | RFC準拠の日本語JPドメイン名登録管理サービス開始 |
| 2004年12月 | 日本語JPドメイン名ポータルサイト「日本語.jp」開設 |
使用可能な文字と制限
| 項目 | 内容 |
|---|---|
| 使用可能文字 | 全角ひらがな・カタカナ・漢字、半角英数字(A-Z, 0-9)、半角ハイフン、「・」「々」「ー」等 |
| 文字数制限 | 1-15文字(全角・半角関係なく) |
| 登録資格 | 日本国内に住所がある方 |
| 登録数制限 | なし |
注意: 属性型JPドメイン(CO.JP、OR.JP等)では日本語ドメインは利用不可。
登録統計(2025年12月時点)
| 種別 | 登録件数 |
|---|---|
| 日本語汎用JPドメイン | 80,729件 |
| 日本語都道府県型JPドメイン | 1,261件 |
| 合計 | 約82,000件 |
汎用JPドメイン総数の約6.5%に相当する。思ったより少ない? それとも多い?
具体的な変換例
| 日本語ドメイン | Punycode変換後 |
|---|---|
| 日本語.jp | xn--wgv71a119e.jp |
| ドメイン名例.jp | xn--eckwd4c7cu47r2wf.jp |
| シーマン.jp | xn--xck1dvc8a.jp |
変換確認には以下のツールが利用できる:
- JPRS公式: https://punycode.jp/
- 日本語JPドメイン名サービス案内: https://日本語.jp/
【セキュリティ】Homograph attackの脅威と対策
ここからはセキュリティの話。知らないと本当に怖い。
Homograph attackとは
IDN Homograph attackは、異なるスクリプトの視覚的類似文字を悪用してドメインを偽装する攻撃である。
Latin 「a」 (U+0061) vs Cyrillic 「а」 (U+0430)
→ 多くのフォントで区別不能
これを悪用すると:
正規: apple.com
偽装: аррӏе.com(全文字キリル文字)
→ 見た目は同じだが、完全に別のドメイン
過去の主要攻撃事例
| 年月 | 事例 |
|---|---|
| 2001年12月 | Microsoft.com偽装の概念実証(Technion大学研究者) |
| 2005年2月 | PayPal.com偽装(Shmooconで実演) |
| 2017年4月 | Apple.com偽装(xn--80ak6aa92e.com、Chrome 58で修正) |
| 2024年 | Spotify偽装フィッシングメール |
Akamaiの2021年調査では、32日間で6,670のホモグラフIDNを検出し、毎日平均67の新規ホモグラフドメインがアクセスされている。
ブラウザの表示ポリシー比較
各ブラウザはHomograph attack対策として、特定条件下でPunycode表示にフォールバックする。
| ブラウザ | Punycode表示条件 | 特記事項 |
|---|---|---|
| Chrome | 混合スクリプト検出、whole-script confusables、Top 500ドメイン類似性 | Lookalike URL警告機能搭載 |
| Firefox | TLDホワイトリスト外、スクリプト混合時 |
network.IDN_show_punycodeで常時Punycode表示可能 |
| Safari | 紛らわしいスクリプト(Cyrillic、Greek)は常にPunycode | 最も厳格だが失敗率も高い |
| Edge | Chromiumと同一アルゴリズム | 2020年以降Chromiumベース |
Chrome 51以降ではUTS 39「Highly Restrictive」プロファイルを採用し、Latin・Cyrillic・Greekの混合を禁止している。
衝撃の事実: USENIX Security 2021の研究によれば、全ブラウザで20.62%-44.46%の検出失敗率が存在する。完璧ではない。
推奨される対策
ユーザー向け
- パスワードマネージャーの使用(ドメイン完全一致でのみ自動入力)
- Firefoxで
network.IDN_show_punycode = trueに設定 - 多要素認証の有効化
レジストリレベル
- .рф(ロシア): キリル文字のみ許可
- Identity Digital(旧Donuts): Unicode Confusablesテーブルに基づくブロッキング
【おまけ】Unicode正規化に起因する脆弱性
Punycodeとは直接関係ないが、Unicode正規化がセキュリティチェック後に実行される場合、以下の脆弱性が発生しうる:
| 攻撃手法 | 悪用される文字 | 結果 |
|---|---|---|
| SQLインジェクション | U+FF07(全角アポストロフィ) | NFKC正規化後に標準アポストロフィに変換 |
| XSS | U+FE64(小なり記号変種) | HTML区切り文字に変換 |
| パストラバーサル | U+FF0E(全角ピリオド) | 「.」に変換されディレクトリ操作可能 |
防御策: 入力受信直後に正規化を実行し、その後にセキュリティチェックを行う順序が重要。
おわりに
Punycodeは「既存のDNSインフラを変更せずに国際化対応を実現する」という設計目標を達成した技術標準である。
- Bootstringアルゴリズムによる効率的なエンコーディング
- ACEプレフィックスによる識別性
- アプリケーション層での処理による後方互換性
この3要素が、20年以上にわたり世界中のIDN運用を支えてきた。
一方で、Homograph attackに代表されるセキュリティリスクは完全には解消されておらず、ブラウザ・レジストリ・ユーザーの多層防御が求められる。
「なんすか?それ??」と言われたあの日から、この記事が誰かの「なるほど!」につながれば幸いです。
参考文献・RFC一覧
| RFC番号 | タイトル | 発行年 |
|---|---|---|
| RFC 3454 | Preparation of Internationalized Strings (Stringprep) | 2002 |
| RFC 3490 | Internationalizing Domain Names in Applications (IDNA) | 2003 |
| RFC 3491 | Nameprep: A Stringprep Profile for IDN | 2003 |
| RFC 3492 | Punycode: A Bootstring encoding of Unicode for IDNA | 2003 |
| RFC 5890 | IDNA: Definitions and Document Framework | 2010 |
| RFC 5891 | IDNA: Protocol | 2010 |
| RFC 5892 | The Unicode Code Points and IDNA | 2010 |
| RFC 5893 | Right-to-Left Scripts for IDNA | 2010 |
| RFC 8264 | PRECIS Framework | 2017 |
略語一覧
| 略語 | 正式名称 |
|---|---|
| IDNA | Internationalized Domain Names in Applications |
| IDN | Internationalized Domain Name |
| ACE | ASCII Compatible Encoding |
| LDH | Letter-Digit-Hyphen |
| IETF | Internet Engineering Task Force |
| NFC/NFKC | Normalization Form (Canonical/Compatibility) Composition |
| JPRS | Japan Registry Services Co., Ltd. |
💬 議論・フィードバック
この記事について質問・指摘・感想があれば、ぜひコメント欄か X(旧Twitter) でお知らせください。
「うちの現場ではこんな問題があった」「このRFCも読むべき」などの情報も大歓迎です!
最後に、GMOコネクトでは研究開発や国際標準化に関する支援や技術検証をはじめ、幅広い支援を行っておりますので、何かありましたらお気軽にお問合せください。