[1] [DFN[stringprep]] は、 [[IETF]] の規格で[[文字列]]の[[正規化]]を行うために定義された[RUBY[枠組み][フレームワーク]]です。
[[IDN]] などの[[識別子]]で使われています。

;; [177] [[RFC]] としては [[Stringprep]] は[[廃止]]されましたが、
まだ互換性のために [[Stringprep]] を使い続けなければならないこともあるかもしれません。

* 仕様書

[REFS[
- [2] '''[CITE@en[RFC 3454 - Preparation of Internationalized Strings ("stringprep")]]
<http://tools.ietf.org/html/rfc3454>'''
- [176] [CITE[RFC Errata Report]] ([TIME[2015-03-23 14:53:37 +09:00]] 版) <http://www.rfc-editor.org/errata_search.php?rfc=3454>
- [124] [CITE[Stringprep Profiles]] 
<http://www.iana.org/assignments/stringprep-profiles/stringprep-profiles.xml#stringprep-profiles-1>
]REFS]

* 処理

[3] [[Stringprep]] の処理は大きく4段階に分かれます。実装はこの順番に処理しなければ[['''なりません''']]
[SRC[>>2 2.]]。この処理の入力は処理対象の[[文字列]]であり、
出力は処理結果の[[文字列]]か、または[[誤り]]のいずれかです。
[WEAK[([[誤り]]かつ[[文字列]]が返されることはありません。 [SRC[>>2 5.、6.]])]]

[FIG(steps)[
= [54] '''[RUBYB[写像]@en[mapping]]''': [[写像表]] (>>59) に基づき、
特定の[[文字]]をそれに対応する0[[文字]]以上の[[文字列]]へと[[写像]]します。
-- [58] [CODE(char)[[[SOFT HYPHEN]]]] の類の除去や[[大文字]]・[[小文字]]の統一 ([[case folding]])
などに使われます。
-- [61] [[写像]]は一度のみ行います。[[写像]]によって他の[[文字列]]に置き換えられた後、更にそれに[[写像]]を行うことは''しません''。
[SRC[>>2 3.]]
= [55] '''正規化''': [[NFKC]] により正規化します。
プロファイルによってはこの作業を省略します。
= [56] '''禁止文字の検査''': [[禁止表]] (>>74) に含まれる[[文字]]を検出したら[[誤り]]とします。
= [57] '''Bidi に関する検査''': Unicode の [[bidi]] 
算法に基づく表示で問題を起こす可能性があれば誤りとします。
プロファイルによってはこの作業を省略します。
]FIG]

[53] >>54 と >>55 では[[文字列]]の長さが増減することがあり、実装はこれに備えなければ[['''なりません''']]
[SRC[>>2 2.]]。

;; [152] [[Stringprep]] では入出力を [[Unicode]] [[文字列]]としています。
それ以外の[[文字コード]]を使う場合は変換が必要ですが、 [[Stringprep]]
の仕様の範囲外とされています。

;; [160] [[RFC 4518]] はこれより前の最初の手順として[RUBYB[転符号化]@en[Transcoding]]
(>>161) を、これより後の最後の手順として [[Insignificant Character Handling]] 
(>>166) を追加しています。

* プロファイルと Unicode の版

[5] [[RFC 3454]] は [[Unicode 3.2]] に基づいています。
基本的に RFC 3454 とそれに基づくプロファイルは Unicode 3.2
に基づき設計されることになります。 RFC 3454
は新しい版の Unicode で使うことが想定されていないと明確に述べています [SRC[>>2 1.2]]。

[48] 
RFC 3454 は新しい版の Unicode 
に対応した新しい版のプロファイルを作ってもプロファイルを使う[[プロトコル]]を全面改訂したりしなくて済むように、
写像表などの非互換変更を禁じたり、
未定義符号位置の処理に関する規定 (>>4) を設けたりしています。

[11] [[IDNA2003]] でも、新しい版を使って[[正規化]]しては[['''ならない''']]と明確に規定されています。

;; [CITE@en[RFC 3490 - Internationalizing Domain Names in Applications (IDNA)]] 
<http://tools.ietf.org/html/rfc3490#section-7>

* 文字レパートリ

[49] [[Stringprep]] の[[プロファイル]]は、利用する[[文字レパートリ]]を選択しなければ[['''なりません''']]
[SRC[>>2 1.2]]。
ただし、現在規定されているのは [[Unicode 3.2]] [[レパートリ]] [SRC[>>2 A.]] のみで、他の選択肢はありません。

[50] [[文字レパートリ]]は固定されたものではなく、将来の改訂で[[文字]]が追加されることがあります
[SRC[>>2 1.2]]。

;; [51] といっても唯一定義されている「[[Unicode 3.2]]」[[レパートリ]]が拡張されることは流石にないでしょう・・・。

[52] [[Unicode 3.2]] [[文字レパートリ]]における[[未定義]]の[[符号位置]]の一覧も [[RFC]]
で定義されています [SRC[>>2 A.]]。実装は [[Unicode 3.2]] の仕様では''なく''、この [[RFC]]
の一覧に基づいて処理しなければ[['''なりません''']] [SRC[>>2 A., >>2 7.]]。

* 符号位置の分類

[118] 特定の [[Stringprep]] である[[符号位置]]がどう処理されるかにより、
[[符号位置]]は次の4つの[[カテゴリー]]のいずれかに分類できます [SRC[>>2 7.1]]。

- [119] [DFN[[[AO]]]]: 出力に現れ得る[[符号位置]]
- [120] [DFN[[[MN]]]]: [[写像]]や[[正規化]]によって消えるために出力に現れ得ない[[符号位置]]
- [121] [DFN[[[D]]]]: 禁止によって[[誤り]]とされるために出力に現れ得ない[[符号位置]]
- [122] [DFN[[[U]]]]: [[未定義]]の[[符号位置]]

[123] [[IDNA2008]] もこれと似た[[導出特性値]]という概念を規定していますが、
[[IDNA2008]] では [[Unicode]] の[[特性]]から直接的に定義されていて、ここでの分類とは大きく異なります。

* 写像表

[59] [[Stringprep]] で使用する[[写像表]]は[[プロファイル]]毎に規定します。

[60] 基本的には [[Stringprep]] 仕様で予め定義された表を使う[['''べきです''']]が、
必要なら独自に定義しても[['''構いません''']]。 [SRC[>>2 3.]]

** 附属書B.1

[62] [CITE@en[B.1 Commonly mapped to nothing]] <http://tools.ietf.org/html/rfc3454#appendix-B.1>

[63] この[[表]]は、[CODE(charname)@en[[[SOFT HYPHEN]]]]、[CODE(charname)@en[[[ZERO WIDTH JOINER]]]]、
[[異体字選択子]]など、含まれていてもいなくても同じ[[識別子]]とみなされるべき [SRC[>>2 3.1]]
[[文字]]を零文字に置き換える (削除する) ものです。

** 附属書B.2

[64] [CITE@en[B.2 Mapping for case-folding used with NFKC]]
<http://tools.ietf.org/html/rfc3454#appendix-B.2>

[65] この[[表]]は、[[NFKC]] を使う場合のための[[大文字]]から[[小文字]]に変換するものです
[SRC[>>2 3.2]]。

[73] この[[写像表]]は附属書B.3 (>>66) を >>71 により補強したものです [SRC[>>2 3.2]]。

** 附属書B.3

[66] [CITE@en[B.3 Mapping for case-folding used with no normalization]]
<http://tools.ietf.org/html/rfc3454#appendix-B.3>

[67] この[[写像表]]は、[[正規化]]しない場合のための[[大文字]]から[[小文字]]に変換するものです
[SRC[>>2 3.2]]。

[72] この[[写像表]]は [[Unicode 3.2]] の [[CaseFolding-3.txt]] に基づいています [SRC[>>2 3.2]]。

** case folding の写像表

[68] [[大文字・小文字不区別]]としたい場合には、附属書B.2 (>>62) または附属書B.3 (>>64)
を使って[[写像]]する[['''べきです''']] [SRC[>>2 3.2]]。

;; [69] 現在の[[インターネット]]の[[プロトコル]]と[[応用]]では[[小文字]]が一般的なので、
[[大文字]]を[[小文字]]に変換しています [SRC[>>2 3.2]]。

[70] しかし独自の[[写像表]]を使いたいのなら、 [[UTR #21]] に基づく[['''べき''']]であり、
[[大文字]]から[[小文字]]に変換する[['''べき''']]です。 [[CaseFolding.txt]]
に基づいて[[写像表]]を作る[['''べき''']]であり、完全な[RUBYB[大文字・小文字の写像]@en[full case mapping]]
を使う ([[状態]] [[C]], [[F]], [[I]] を使う) [['''べき''']]です。 [SRC[>>2 3.2]]

[71] [[NFKC]] を使うなら、 [[UTR #21]] では[[写像]]されてなくても処理が必要な[[文字]]があるため、
注意が必要です。 (一部の[[ギリシャ文字]]と多くの[[ラテン文字]]を含む[[記号]]が該当します。)
これは、
= [VAR[a]] を入力とする
= [VAR[b]] を、 [VAR[a]] を [[case folding]] し、 [[NFKC]] で[[正規化]]したものとする
= [VAR[c]] を、 [VAR[b]] を [[case folding]] し、 [[NFKC]] で[[正規化]]したものとする
= [VAR[c]] が [VAR[b]] と同じでなければ、 [VAR[a]] から [VAR[c]] への[[写像]]を追加する

... という方法で求められます。 [SRC[>>2 3.2]]

* 正規化

[142] [[Unicode]] の[[正規化形]]には[[冪等性]]に関する不具合がありました。この不具合は[[訂正 #5]]
で修正されていますが、それまでは[[正規化形]]の実装に2通りの可能性がありました。

[143] [[Perlモジュール]] [CODE(char)[[[Unicode::Stringprep]]]] は、
[[Stringprep]] の[[正規化]]によってこの2通りの実装方法での差異が生じる列を検出した場合、
失敗として扱います。 [SRC[>>14]]

;; [156] [[RFC]] に従った実装とは言えませんが、やむを得ないのかもしれません。

* 禁止表

[74] [[Stringprep]] で使用する禁止[[文字]]の[[表]]は[[プロファイル]]毎に規定します。

** 附属書C.1.1

[75] [CITE@en[C.1.1 ASCII space characters]]
<http://tools.ietf.org/html/rfc3454#appendix-C.1.1>

[76] [[ASCII]] に含まれる[[間隔文字]]の表で、 [CODE(charname)@en[[[SPACE]]]]
だけが含まれています。

** 附属書C.1.2

[77] [CITE@en[C.1.2 Non-ASCII space characters]]
<http://tools.ietf.org/html/rfc3454#appendix-C.1.2>

[78] [[非ASCII文字]]な[[間隔文字]]の表です。

** 附属書C.2.1

[79] [CITE@en[C.2.1 ASCII control characters]]
<http://tools.ietf.org/html/rfc3454#appendix-C.2.1>

[81] [[ASCII]] に含まれる[[制御文字]]の表です。

** 附属書C.2.2

[80] [CITE@en[C.2.2 Non-ASCII control characters]]
<http://tools.ietf.org/html/rfc3454#appendix-C.2.2>

[82] [[非ASCII文字]]な[[制御文字]]の表です。

** 附属書C.3

[83] [CITE@en[C.3 Private use]]
<http://tools.ietf.org/html/rfc3454#appendix-C.3>

[84] [[私用域]]の[[符号位置]]の表です。

** 附属書C.4

[85] [CITE@en[C.4 Non-character code points]]
<http://tools.ietf.org/html/rfc3454#appendix-C.4>

[86] [[非文字]]の[[符号位置]]の表です。

[93] [[PropList.txt]] [SRC[>>2 5.4]] に基づいているとみられます。

** 附属書C.5

[87] [CITE@en[C.5 Surrogate codes]]
<http://tools.ietf.org/html/rfc3454#appendix-C.5>

[88] [[サロゲート]]の[[符号位置]]の表です。

** 附属書C.6

[89] [CITE@en[C.6 Inappropriate for plain text]]
<http://tools.ietf.org/html/rfc3454#appendix-C.6>

[94] 普通の文章には登場しない[[文字]] [SRC[>>2 5.6]] が含まれています。

** 附属書C.7

[90] [CITE@en[C.7 Inappropriate for canonical representation]]
<http://tools.ietf.org/html/rfc3454#appendix-C.7>

[95] [[IDC]] が含まれています。同じ[[文字]]が複数の方法で表現できてしまうので禁止するとされています。
[SRC[>>2 5.7]]

;; [96] それは誤解なような気がしますが。 [[IDS]] は[[文字]]そのものの表現方法ではないのでは。

** 附属書C.8

[91] [CITE@en[C.8 Change display properties or are deprecated]]
<http://tools.ietf.org/html/rfc3454#appendix-C.8>

[97] [[レンダリング]]を操作するものや [[Unicode]] で[[非推奨]]とされているものが含まれています。
[SRC[>>2 5.8]]

** 附属書C.9

[92] [CITE@en[C.9 Tagging characters]]
<http://tools.ietf.org/html/rfc3454#appendix-C.9>

[98] 不可視な[[タグ文字]]が含まれています [SRC[>>2 5.9]]。

* Bidi 文字チェック

[99] [[bidi]] 処理によって [[ltr]] と [[rtl]] が混在することによる混乱を避けるため、
[[bidi]] 的に[[文字]]が適当に並べられていることをチェックします。
このチェックは[[プロファイル]]により省略して[['''構いません''']] [SRC[>>2 6.]]。

[100] チェックを行う場合、[[文字列]]は次の条件をすべて満たさなければ[['''なりません''']]
[SRC[>>2 6.]]。

- [101] >>91 の[[文字]]は禁止されなければ[['''なりません''']]。 [SRC[>>2 6.]]
-- [102] これ、[[プロファイル]]に対する要件??
- [103] [[RandALCat文字]]が含まれる場合には、[[LCat文字]]を含んでは[['''なりません''']]。 [SRC[>>2 6.]]
- [104] [[RandALCat文字]]が含まれる場合には、先頭と末尾が [[RandALCat文字]]でなければ[['''なりません''']]。
[SRC[>>2 6.]]

[108] [[RFC]] には附属書に [[RandALCat文字]]と [[LCat文字]]の一覧が含まれていますが、
他の表とは違って、 [[Unicode 3.2]] の元のデータでなくこの表を使わなければならないとは明記されていません。
単なるミスなのか何か意図があるのかは不明です。

[109] [[IDNA2008]] は、この条件だと最後の[[文字]]が[[結合文字]]となる場合をカバーしきれておらず、
本来認められるべき[[文字列]]であっても排除されてしまうと指摘しています。
そのため代わりに [[bidi規則]]を規定しています。

** 例

[105] >>104 より、
- [106] <U+0627><U+0031> (aleph 1)

... は禁止されますが、
- [107]  <U+0627><U+0031><U+0628> (aleph 1 beh)

... は認められます [SRC[>>2 6.]]。

* 未定義符号位置の扱い

[4] まだ[[文字]]が割当てられておらず、将来割当てられるかもしれない[[符号位置]]についての規定もあります。

[12] Stringprep のプロファイルを適用する文字列は大別して
[DFN[[RUBYB[[[蓄積文字列]]]@en[stored string]]]]と[DFN[[RUBYB[[[照会]]]@en[query]]]]の2種類があります
[SRC[>>2 7.]]。
蓄積文字列はデータベースに登録する項目名のようなもので、
照会はデータベースから項目を取出すために指定する項目名のようなものです。

- [110] [[蓄積文字列]]は[[未定義]]の[[符号位置]]を含んでは[['''なりません''']]。 [SRC[>>2 7.]]
-- [115] 更に言えば、すべての[[文字]]は [[AO]] でなければならず、[[MN]]、[[D]]、[[U]] の[[符号位置]]を含んでは[['''なりません''']] [SRC[>>2 7.1]]。
- [111] [[照会]]は[[未定義]]の[[符号位置]]を含んでも[['''構いません''']]。 [SRC[>>2 7.]]
-- [116] [[照会]]を作成する[[アプリケーション]]では [[U]] の[[符号位置]]を [[AO]]
と同じように扱わなければ[['''なりません''']]。
-- [117] ただし[[アプリケーション]]はより厳密にチェックするための[[前処理]]を行って[['''構いません''']]。 [[U]] な[[符号位置]]について警告したり、[[誤り]]を報告したりしても構いません。

[113] より新しい版の [[Unicode]] で[[文字]]が割り当てられると、
それに伴い[[未定義]]だった時と[[正規化]]の結果が変わってしまうことがあります。
また、写像表や禁止文字も拡充されることがあるでしょう。その時に、
古い版でもし[[蓄積文字列]]に[[未定義]]の[[符号位置]]が含まれていると、
新しい版で [[Stringprep]] を適用した結果アクセスできなくなってしまう危険性があります。

[13] [[IDNA2003]] には [[AllowUnassigned]] [[フラグ]]が規定されています。 [[Nameprep]]
において未定義の[[符号位置]]をどう扱うかはこの[[フラグ]]に依存します。基本的に[[登録]]では[[偽]]
([[蓄積文字列]])、[[lookup]] では[[真]] ([[照会]]) とします。

* プロファイルの定義

[36] [[プロファイル]]は、次のものを含んでいなければ[['''なりません''']] [SRC[>>2 1.2]]。
- [37] [[プロファイル]]の想定する適用可能性
- [38] [[文字レパートリ]] 
- [39] 利用する[[写像]]の[[表]]
-- [40] [[Stringprep]] 共通のもの
-- [41] 独自のもの (ある場合)
- [42] [[正規化]]の方法 (利用する場合)
- [43] 禁止する[[文字]]の[[表]]
-- [45] [[Stringprep]] 共通のもの
-- [46] 独自のもの (ある場合)
- [44] [[bidi]] 文字列検査の方法 (利用する場合)

[32] 関係する2つの[[プロファイル]]がそれぞれ別々の[[プロファイル]]を使っていると、
[[文字列]]をどう[[正規化]]するか、何が認められるかが違っているため、
[[相互運用]]が難しくなります。ですから、新しい[[プロファイル]]を無闇に作らず、
既存の[[プロファイル]]を流用するよう、強く求められています [SRC[>>2 1.2]]。

[35] [[Stringprep]] は[[プロファイル]]間でできるだけ表を共有することを意図しており、
従って[[プロファイル]]が独自に[[表]]を作ることもできるとはいえ、
極力 [[Stringprep]] 仕様で定義されている[[表]]の組み合わせに依ることが望ましいです [SRC[>>2 1.2]]。

[33] [[プロファイル]]においてできるだけ多くの[[文字]]を利用可能としたい場合、
可能な限り、[[文字]]の利用を禁止するのではなく他の[[文字]]に変換することを選ぶべきです。 [SRC[>>2 1.2]]

[34] [[Stringprep]] によって[[文字]]関係の[[規格]]の逝かれているところを「修正」
することもあるいはできるかもしれませんが、それは行う[['''べきではありません''']] [SRC[>>2 1.2]]。

** 登録

[6] [[Stringprep]] の[[プロファイル]]には [[IETF合意]]が[['''必要''']] [SRC[>>2 10.]] であり、
[[IESG評価]]が[['''必要''']] [SRC[>>2 10.]] であり、 [[RFC]] 化されて
[[IANA]] に登録されなければ[['''なりません''']] [SRC[>>2 1.2]]。

** 安定性

[114] 新しい版の[[文字レパートリ]]に対応した新しい版の[[プロファイル]]では
[[U]] カテゴリーだった[[符号位置]]を [[D]]、[[MN]]、[[AO]] に変更して構いません。
しかし、 [[AO]]、[[MN]]、[[D]] だった[[符号位置]]を他のカテゴリーに変更しては[['''なりません''']]
[SRC[>>2 7.1]]。

* プロファイルの一覧

[47] 次のような[[プロファイル]]がありました。

[FIG(table col)[
:name: 名前
:ver: 版
:iana: [[IANA]] 状態
:ietf: [[IETF]] 状態
:rep:[[文字レパートリ]]
:map1:[ABBR[写像 B.1][RFC 3454 B.1 (除去)]]
:map2:[ABBR[写像 B.2][RFC 3454 B.2 (小文字化 (NFKC))]]
:map3:[ABBR[写像 B.3][RFC 3454 B.3 (小文字化)]]
:mapo:その他写像
:norm:正規化
:f11:[ABBR[禁止 C.1.1][RFC 3454 C.1.1 [CODE(char)[U+0020]]]]
:f12:[ABBR[禁止 C.1.2][RFC 3454 C.1.2 その他の間隔]]
:f21:[ABBR[禁止 C.2.1][RFC 3454 C.2.1 C0 制御文字]]
:f22:[ABBR[禁止 C.2.2][RFC 3454 C.2.2 その他の制御文字]]
:f3:[ABBR[禁止 C.3][RFC 3454 C.3 私用文字]]
:f4:[ABBR[禁止 C.4][RFC 3454 C.4 代理文字]]
:f5:[ABBR[禁止 C.5][RFC 3454 C.5 非文字]]
:f6:[ABBR[禁止 C.6][RFC 3454 C.6 ルビ]]
:f7:[ABBR[禁止 C.7][RFC 3454 C.7 IDS]]
:f8:[ABBR[禁止 C.8][RFC 3454 C.8 bidi]]
:f9:[ABBR[禁止 C.9][RFC 3454 C.9 タグ]]
:fo:その他禁止
:bidi:[[bidi]]
:context: 利用される場面
:note: 備考

:name: [[iSCSI]]
:rep:[[Unicode 3.2]]
:map1:○
:map2:○
:map3:
:mapo:
:norm:[[NFKC]]
:f11:○
:f12:○
:f21:○
:f22:○
:f3:○
:f4:○
:f5:○
:f6:○
:f7:○
:f8:○
:f9:○
:fo:>>8, >>26
:bidi:○
:ver: 1
:ietf: [[RFC 3722]]
:iana: 現行

:name:[[Nameprep]]
:rep:[[Unicode 3.2]]
:map1:○
:map2:○
:map3:
:mapo:
:norm:[[NFKC]]
:f11:
:f12:○
:f21:
:f22:○
:f3:○
:f4:○
:f5:○
:f6:○
:f7:○
:f8:○
:f9:○
:fo:
:bidi:○
:ietf: [[RFC 3491]] ([[RFC 5891]] により[[廃止]])
:iana: 現行
:ver: 1
:context: [[IDNA2003]]
:note:
[[IETF]] 的には [[IDNA2008]] により[[廃止]]、
現実には [[UTS #46]] に移行。

:name: [DFN[[[Nodeprep]]]]
:ver: 1
:iana: 非現行
:ietf: [[RFC 3920]] [SRC[>>125]] ([[RFC 6122]] により[[廃止]])、
[[RFC 6122]] [SRC[>>133]] ([[RFC 7622]] により[[廃止]])
:rep:[[Unicode 3.2]]
:map1:○
:map2:○
:map3:
:mapo:
:norm:[[NFKC]]
:f11:○
:f12:○
:f21:○
:f22:○
:f3:○
:f4:○
:f5:○
:f6:○
:f7:○
:f8:○
:f9:○
:fo:>>9
:bidi:○
:context:
[129] [[XMPP]] [[節点識別子]]
:note:
[139] [[RFC]] は改訂されていますが、内容は変わっていないので版はどちらも「1」です。

:name: [DFN[[[Policy MIB Stringprep]]]]
:ver: 1
:iana: 現行
:ietf: [[RFC 4011]]
:rep:[[Unicode 3.2]]
:map1:○
:map2:
:map3:
:mapo:
:norm:[[NFKC]]
:f11:
:f12:
:f21:○
:f22:○
:f3:○
:f4:○
:f5:○
:f6:○
:f7:○
:f8:○
:f9:○

:name: [DFN[[[Resourceprep]]]]
:ver: 1
:iana: 非現行
:ietf: [[RFC 3920]] [SRC[>>126]] ([[RFC 6122]] により[[廃止]])、
[[RFC 6122]] [SRC[>>135]] ([[RFC 7622]] により[[廃止]])
:rep:[[Unicode 3.2]]
:map1:○
:map2:
:map3:
:mapo:
:norm:[[NFKC]]
:f11:
:f12:○
:f21:○
:f22:○
:f3:○
:f4:○
:f5:○
:f6:○
:f7:○
:f8:○
:f9:○
:fo:
:bidi:○
:context:
[132] [[XMPP]] [[資源部分]] (旧称・[[資源識別子]])
:note:
[140] [[RFC]] は改訂されていますが、内容は変わっていないので版はどちらも「1」です。

:name: [DFN[[[SASLprep]]]]
:rep:[[Unicode 3.2]]
:map1:○
:map2:
:map3:
:mapo:[ABBR[C.1.2] [RFC 3454 C.1.2 間隔]] → [ABBR[C.1.1] [RFC 3454 C.1.1 [CODE(char)[U+0020]]]]
:norm:[[NFKC]]
:f11:
:f12:○
:f21:○
:f22:○
:f3:○
:f4:○
:f5:○
:f6:○
:f7:○
:f8:○
:f9:○
:bidi:○
:ver: 1
:iana: 非現行
:ietf: [[RFC 4013]] ([[RFC 7613]] により[[廃止]])

:name: [DFN[[[trace]]]]
:ver: 1
:iana: 現行
:ietf: [[RFC 4505]] [SRC[>>24]]
:rep:[[Unicode 3.2]]
:map1:
:map2:
:map3:
:mapo:
:norm:
:f11:
:f12:
:f21:○
:f22:○
:f3:○
:f4:○
:f5:○
:f6:○
:f7:
:f8:
:f9:○
:bidi:○
:context:
[22] [[SASL]] [CODE[[[ANONYMOUS]]]]
:note:
[23] 一つ前の [[RFC 2245]] は[[非ASCII文字]]を認めておらず、 [[Stringprep]]
も使っていませんでした。

:name: [DFN[[[KRBprep]]]]
:ietf: [[I-D]] [SRC[>>16]] (放棄)
:iana: 未登録
:context: [[Kerberos]]
:note:
[21] 早期の [[Internet Draft]] 止まりで [[RFC]] 化されていませんが、
[[GNU Libidn]] で実装されています [SRC[>>7]]。
(この表は [[libidn]] の実装状況に従っています。)
:map1: ○
:map3: ○
:norm: [[NFKC]]
:f12: ○
:f22: ○
:f3: ○
:f4: ○
:f5: ○
:f6: ○
:f7: ○
:f8: ○
:f9: ○
:bidi: ○

:name: [[RFC 4518]]
:iana: 未登録
:ietf: [[RFC 4518]]
:rep:[[Unicode 3.2]]
:map1:
:map2:※
:map3:
:mapo:あり
:norm:[[NFKC]]
:f11:
:f12:
:f21:
:f22:
:f3:○
:f4:○
:f5:○
:f6:
:f7:
:f8:○
:f9:
:fo:[CODE[[[U+FFFD]]]]
:note: なぜか[[プロファイル]]扱いにはなっていません。
]FIG]

[REFS[
- [125] [DEL[[CITE@en[RFC 3920 - Extensible Messaging and Presence Protocol (XMPP): Core]]]]
-- [128] <http://tools.ietf.org/html/rfc3920#section-15.6>
-- [127] '''<http://tools.ietf.org/html/rfc3920#appendix-A>'''
- [133] [CITE@en[RFC 6122 - Extensible Messaging and Presence Protocol (XMPP): Address Format]]
-- [134] <http://tools.ietf.org/html/rfc6122#section-5.1>
-- [137] '''<http://tools.ietf.org/html/rfc6122#appendix-A>'''
- [126] [DEL[[CITE@en[RFC 3920 - Extensible Messaging and Presence Protocol (XMPP): Core]]]]
-- [131] '''<http://tools.ietf.org/html/rfc3920#appendix-B>'''
-- [130] <http://tools.ietf.org/html/rfc3920#section-15.7>
- [135] [CITE@en[RFC 6122 - Extensible Messaging and Presence Protocol (XMPP): Address Format]]
-- [136] <http://tools.ietf.org/html/rfc6122#section-5.2>
-- [138] '''<http://tools.ietf.org/html/rfc6122#appendix-B>'''
- [24] [CITE@en[RFC 4505 - Anonymous Simple Authentication and Security Layer (SASL) Mechanism]] 
-- [25] '''<http://tools.ietf.org/html/rfc4505#section-3>'''
-- [27] <http://tools.ietf.org/html/rfc4505#page-6>
- [16] [CITE@en[draft-ietf-krb-wg-utf8-profile-01 - Preparation of Internationalized Strings Profile for Kerberos UTF-8 Strings]]
<http://tools.ietf.org/html/draft-ietf-krb-wg-utf8-profile-01>
- [7] [CITE[libidn: profiles.c File Reference]] ([TIME[2016-01-05 01:00:01 +09:00]] 版) <http://www.gnu.org/software/libidn/doxygen/profiles_8c.html#a0d24f6921037c5fb1ca54975ce328c07>
]REFS]

** RFC 4518

[157] [DFN[[[RFC 4518]]]] は [[LDAP]] 用の[[プロファイル]]を定義しています。
この[[プロファイル]]は [[stringprep]] の前や後の処理を含めて規定しています。

;; [159] そのためか [[IANA登録簿]]には[[プロファイル]]として登録されていません。

;; [175] [[LDAP]] 自体のみならず、 [[証明書]]の [[distinguished name]]
の[[比較]]でも用いられます。

[REFS[
- [158] [CITE@en[RFC 4518 - Lightweight Directory Access Protocol (LDAP): Internationalized String Preparation]] ([TIME[2014-12-29 00:45:51 +09:00]] 版) <http://tools.ietf.org/html/rfc4518>
- [171] [CITE[RFC Errata Report]] ([TIME[2015-03-23 14:45:37 +09:00]] 版) <http://www.rfc-editor.org/errata_search.php?rfc=4518>
]REFS]

[161] [[Map]] より前に[RUBYB[[[転符号化]]]@en[Transcoding]]を行います。これは [[Unicode]]
[[文字列]]へと変換する操作です。

;; [[LDAP文字列]]参照。

[162] [[Map]] は、 [[RFC 3454]] の表を使わずに独自の表 (>>163) を使っています。 [[RFC 3454]]
の表と若干の出入りがある他、 [[RFC 3454]] で禁止に分類されている[[文字]]が除去されたり、
[CODE(char)[[[U+0020]]]] に[[写像]]されたりします。

[REFS[
- [163] [CITE@en[Character mapping "rfc4518:map:common"]] ([TIME[2015-03-23 01:47:39 +09:00]] 版) <http://chars.suikawiki.org/map/rfc4518%3Amap%3Acommon>
]REFS]

[165] [[Map]] に [[case folding]] ([[RFC 3454]] 表 B.2) が含まれるか否かは、
[[比較]]方法により変わります。

;; [[LDAP文字列]]参照。

[164] [[Prohibit]] は、 [[RFC 3454]] の表の他に [CODE[[[U+FFFD]]]] も含まれています。
また [[RFC 3454]] の表A.1 ([[Unicode 3.2]] 時点での[[未定義符号位置]]) も含まれています
(つまり[[蓄積文字列]] (>>110) に相当します)。 >>167 は禁止される[[符号位置]]の一覧です。

[REFS[
- [167] [CITE@en[Character set "$rfc4518:prohibited"]] ([TIME[2015-03-23 14:29:24 +09:00]] 版) <http://chars.suikawiki.org/set/%24rfc4518%3Aprohibited>
]REFS]

[166] 処理の最後に [DFN[[[Insignificant Character Handling]]]] [SRC[>>163, >>171]] を行います。
これには次の3種類があり、[[比較]]方法によりいずれかを選択します。

[FIG(steps)[
= [172] [DFN[[[Insignificant Space Handling]]]]
== 入力が[[属性値]]または非部分文字列 assertion value なら、
=== 入力に[[間隔]]以外の[[文字]]が含まれないなら、[[文字列]] [CODE(charname)@en[[[SPACE]]]] [CODE(charname)@en[[[SPACE]]]] を返します。
=== そうでないなら、
==== [[間隔]]の連続をすべて[[文字列]] [CODE(charname)@en[[[SPACE]]]] [CODE(charname)@en[[[SPACE]]]] に置き換えます。
==== 先頭と末尾に[[文字列]] [CODE(charname)@en[[[SPACE]]]] [CODE(charname)@en[[[SPACE]]]] 
があれば除去します。
==== 先頭と末尾に [CODE(charname)@en[[[SPACE]]]] を挿入します。
== 入力が部分文字列 assertion value なら、
=== 入力に[[間隔]]以外の[[文字]]が含まれないなら、 [CODE(charname)@en[[[SPACE]]]]
を返します。
=== そうでないなら、
==== [[間隔]]の連続をすべて[[文字列]] [CODE(charname)@en[[[SPACE]]]] [CODE(charname)@en[[[SPACE]]]] に置き換えます。
==== 入力が initial substring なら、先頭の[[間隔]]列を除去し、 [CODE(charname)@en[[[SPACE]]]]
を挿入します。
==== 入力が initial substring か any substring で[[間隔]]で終わるなら、
末尾の[[間隔]]列を除去し、 [CODE(charname)@en[[[SPACE]]]] を挿入します。
==== 入力が any substring か final substring で[[間隔]]で始まるなら、
先頭の[[間隔]]列を除去し、 [CODE(charname)@en[[[SPACE]]]] を挿入します。
==== 入力が final substring なら、末尾の[[間隔]]列を除去し、 [CODE(charname)@en[[[SPACE]]]]
を挿入します。
= [173] [DFN[[[numericString Insignificant Character Handling]]]]
== [[間隔]]をすべて削除します。
= [174] [DFN[[[telephoneNumber Insignificant Character Handling]]]]
== [[間隔]]をすべて削除します。
== [[ハイフン]]をすべて削除します。
]FIG]

[168] ここで[RUBYB[[[間隔]]]@en[space]]とは、 [CODE(charname)@en[[[SPACE]]]]
であって直後に[[結合文字]]がないものをいいます。 [SRC[>>158]]

[169] ここで[RUBYB[[[ハイフン]]]@en[hyphen]]とは、いくつかの[[文字]] (>>170)
の直後に[[結合文字]]が来ないものをいいます [SRC[>>158]]。

[REFS[
- [170] [CITE@en[Character set "$rfc4518:hyphen-char"]] ([TIME[2015-03-23 14:44:20 +09:00]] 版) <http://chars.suikawiki.org/set/%24rfc4518%3Ahyphen-char>
]REFS]

[155] >>19 は [[GNU Libidn]] で実装されています。 >>19 は >>153、>>154 を経て
[[RFC 4518]] となっています。

[REFS[
- [19] [CITE@en[draft-zeilenga-ldapbis-strmatch-02 - Internationalized String Matching Rules for X.500]]
<http://tools.ietf.org/html/draft-zeilenga-ldapbis-strmatch-02>
- [153] [CITE@en[draft-zeilenga-ldapbis-strprep-00 - LDAP: Internationalized String Preparation]] ([TIME[2015-01-26 15:44:44 +09:00]] 版) <https://tools.ietf.org/html/draft-zeilenga-ldapbis-strprep-00>
- [154] [CITE@en[draft-ietf-ldapbis-strprep-07 - Lightweight Directory Access Protocol (LDAP): Internationalized String Preparation]] ([TIME[2015-01-18 22:30:35 +09:00]] 版) <https://tools.ietf.org/html/draft-ietf-ldapbis-strprep-07>
]REFS]

[150] 
しかし必要性が不明瞭なのに [[Stringprep]] 本家と似て非なるものを制定することになるとは、
この時点で既に技術開発としての [[Stringprep]] 族は破綻していたと言わざるを得ませんね。

[151] 
[[プロトコル]]によって細部は違っても全体的な処理の流れは同じだから共通化しようというのが
[[stringprep]] のはずだったのに、そのフレームワークに合わない改変をするしかなくなって、
しかもそのバリエーションを包含できる [[stringprep]] の新版ではなくて、
似て非なる別規格を作ることになったのですから。

[184] 
技術的にはそういうほど別物でもなさそうに見えるので、統合できなかったのは[[政治的理由]]なんだろうなあ。。。


** iSCSI の追加禁止文字

[8]
[[RFC 3722]] 6.1. の表 (共通入力機構不適切文字):
,*符号位置	,*文字名称
,[CODE(char)[[[U+3002]]]]	,[CODE(char)[[[IDEOGRAPHIC FULL STOP]]]]

[26] 
[[RFC 3722]] 6.2. の表 (禁止済み ASCII 文字):
,*符号位置
,[CODE(char)[[[U+0000]]]]〜[CODE(char)[[[U+002C]]]]
,[CODE(char)[[[U+002F]]]]
,[CODE(char)[[[U+003B]]]]〜[CODE(char)[[[U+0040]]]]
,[CODE(char)[[[U+005B]]]]〜[CODE(char)[[[U+0060]]]]
,[CODE(char)[[[U+007B]]]]〜[CODE(char)[[[U+007F]]]]

** Nodeprep の追加禁止文字

[9] [[RFC 3920]] / [[RFC 6122]] A.5. の表:
,[CODE(char)[[[U+0022]]]]	,[CODE(char)[[[QUOTATION MARK]]]]
,[CODE(char)[[[U+0026]]]]	,[CODE(char)[[[AMPERSAND]]]]
,[CODE(char)[[[U+0027]]]]	,[CODE(char)[[[APOSTROPHE]]]]
,[CODE(char)[[[U+002F]]]]	,[CODE(char)[[[SOLIDUS]]]]
,[CODE(char)[[[U+003A]]]]	,[CODE(char)[[[COLON]]]]
,[CODE(char)[[[U+003C]]]]	,[CODE(char)[[[LESS-THAN SIGN]]]]
,[CODE(char)[[[U+003E]]]]	,[CODE(char)[[[GREATER-THAN SIGN]]]]
,[CODE(char)[[[U+0040]]]]	,[CODE(char)[[[COMMERTIAL AT]]]]

* テストケース

[18] [CITE[Nameprep and IDNA Test Vectors]]
<http://www.gnu.org/software/libidn/draft-josefsson-idn-test-vectors.html>

[20] [CITE@en-US[Savannah Git Hosting - libidn.git/tree - tests/]] 
<http://git.savannah.gnu.org/gitweb/?p=libidn.git;a=tree;f=tests>

* 歴史

** RFC 3454

[180] [[IETF]] は [[IDNA]] と共に [[Stringprep]] を開発し、
その[[プロファイル]]である [[Nameprep]] を [[IDNA]] で用いることとしました。

[181] [[Stringprep]] は [DFN[[[RFC 3454]]]] として出版されました。

** IDNA2008 との関係

[28] [[IDNA2003]] は [[Stringprep]] の[[プロファイル]]である [[Nameprep]] を使っていましたが、
[[IDNA2008]] は [[Nameprep]] を使わずにすべて独自に定義しています。 [[Nameprep]] と
[[IDNA2008]] にはまったく互換性がありません。

[29] [[IDNA2008]] の [[RFC]] では、他の [[Stringprep]] を使う[[応用]]である[[セキュリティ]]系プロトコルとは要件が異なり
([[ドメイン名]]は分かりやすいことが重要だが[[合言葉]]は分かりにくいことが重要)、
共通の仕組みを用いることは必ずしも好ましくないと指摘しています。

[REFS[
- [30] [CITE@en[RFC 5890 - Internationalized Domain Names for Applications (IDNA): Definitions and Document Framework]] ([TIME[2011-02-05 07:34:19 +09:00]] 版) <http://tools.ietf.org/html/rfc5890#section-4.7>
- [31] [CITE@en[RFC 5894 - Internationalized Domain Names for Applications (IDNA): Background, Explanation, and Rationale]] ([TIME[2011-02-05 07:34:29 +09:00]] 版) <http://tools.ietf.org/html/rfc5894#section-7.5>
]REFS]

** PRECIS へ

[145] [[RFC 6885]] は [[Stringprep]] の[[プロファイル]]とその問題点をまとめたものです。 [[Stringprep]]
は [[Unicode 3.2]] に固定されているなど問題があり [[IDNA2008]] は [[Stringprep]] を使わなくなりましたが、
新しいプロトコルは改版可能であるなど [[DNS]] とは事情が異なるとして、それとは別の方法で [[Stringprep]]
を改良する必要があると指摘し、[[プロファイル]]の用法を分析しています。

[REFS[
- [144] [CITE@en[RFC 6885 - Stringprep Revision and Problem Statement for the Preparation and Comparison of Internationalized Strings (PRECIS)]] ([TIME[2013-07-29 10:54:24 +09:00]] 版) <http://tools.ietf.org/html/rfc6885>
]REFS]

[146] [[IETF]] では「Preparation and Comparison of Internationalized Strings」を略して「[[PRECIS]]」
と称しており、 [[Stringprep]] の改訂のために [[PRECIS WG]] を設けています。

[182] [[RFC 3454]] は [[PRECIS]] の [[RFC 7564]] の出版に伴い[[廃止]]されています。

;; [[廃止]]の時点でまだ [[Stringprep]] の各[[プロファイル]]の
[[PRECIS]] 版は出版されておらず、参照先の [[RFC]] が[[廃止]]状態になっているわけですが、
そんなので [[IETF]] の手続き的には良いのでしょうか...

;; [183] [[PRECIS]] も参照。

[141] [[RFC 7613]] は[[利用者名]]や[[合言葉]]のための [[PRECIS]]
[[プロファイル]]を規定しています。

[147] [[RFC 7613]] は [[RFC 4013]] [[SASLprep]] を[[廃止]]しています [SRC[>>112]]。
ただし従来の [[SASLprep]] を用いる[[応用]]は、明示的に改訂しない限り、
[[PRECIS]] に自動的に移行するわけではない [SRC[>>112]] とされています。

[REFS[
- [112] [CITE@en[RFC 7613 - Preparation, Enforcement, and Comparison of Internationalized Strings Representing Usernames and Passwords]] ([TIME[2015-10-23 06:11:01 +09:00]] 版) <https://tools.ietf.org/html/rfc7613#section-1>
]REFS]

* 実装

[14] [CITE[Unicode::Stringprep - search.cpan.org]]
( ([TIME[2011-03-06 19:17:21 +09:00]] 版))
<http://search.cpan.org/dist/Unicode-Stringprep/lib/Unicode/Stringprep.pm>

[17] [[GNU Libidn]] は >>16、>>19 に対応しているらしいです。

* メモ

[10]
なんか >>7 と同じ表が既に存在しているし[AA[orz]]

[CITE[Stringprep Profiles]] <http://nameprep.org/stringprep.html>

[15] 
<http://search.cpan.org/dist/Unicode-Stringprep/lib/Unicode/Stringprep.pm#CAVEATS>

[FIG(quote)[
[FIGCAPTION[
[178] [CITE@en[RFC 7542 - The Network Access Identifier]]
([TIME[2015-10-18 15:17:56 +09:00]] 版)
<https://tools.ietf.org/html/rfc7542#section-1.4>
]FIGCAPTION]

> 
>    *  Section 2.4 of '''['''RFC4282''']''' required mappings that are language
>       specific and that are nearly impossible for intermediate nodes to
>       perform correctly without information about that language.
>    *  Section 2.4 of '''['''RFC4282''']''' requires normalization of usernames,
>       which may conflict with local system or administrative
>       requirements.
>    *  The recommendations in Section 2.4 of '''['''RFC4282''']''' for treatment of
>       bidirectional characters have proven to be unworkable.
>    *  The prohibition of the use of unassigned code points in
>       Section 2.4 of '''['''RFC4282''']''' effectively prohibits support for new
>       scripts.
>    *  No Authentication, Authorization, and Accounting (AAA) client,
>       proxy, or server has implemented any of the requirements in
>       Section 2.4 of '''['''RFC4282''']''', among other sections.

]FIG]

[179] [[NAI]] は [[RFC 4282]] 時代に [[Stringprep]] を採用していましたが、
[[RFC 7542]] は >>178 の通り、これが機能しなかったとして、
ただの [[NFC]] に変更しています。 [[PRECIS]] も使っていません。

[148] [CITE@en[RFC 8146 - Adding Support for Salted Password Databases to EAP-pwd]]
([TIME[2017-04-22 11:18:27 +09:00]])
<https://tools.ietf.org/html/rfc8146>

[149] [CITE@en[draft-irtf-cfrg-augpake-08 - Augmented Password-Authenticated Key Exchange (AugPAKE)]]
([TIME[2017-11-13 15:11:53 +09:00]])
<https://tools.ietf.org/html/draft-irtf-cfrg-augpake-08>