≪第4回へ
前回は証明書識別名のASN.1バイナリを文字列表現するための標準RFC 2253を紹介し、RFC 2253により生成された文字列一通りにはならず、文字列一致をさせることは難しいということを説明しました。
今回は、RFC 2253文字列の一致確認をする際の相互運用性阻害要因について説明していこうと思います。
属性タイプの表記はRFC 2253 2.3節で規定されています。
RFC 2253によると一般的な属性タイプは"C"(国名:countryName)、"O"(組織名:organizationName)のような属性タイプの名前(type name)を表す文字列で表記されます。
ここでまず問題となるのが"published table of attribute types"が一体どれを指しているのかという事です。"RFC 2256 5. Attribute Types"を指していると思われますが、明確にこれを指しているわけではない事、RFC 3280で使用できる属性タイプをカバーしているわけではない事、RFC 2256では小文字で始まる文字列(例 "cn", "serialNumber", "o", "title"等)である事といった点が気になります。
RFC 2253 2.3節の例では以下のように大文字で限定されたものだけです。
XAdESではディレクトリ一般ではなくデジタル証明書に限定して考えればいいと思うのですが、広く使われている証明書プロファイルであるRFC 3280では、受け入れられる属性タイプに関する規定があります。(RFC 3280 4.1.2.4 節 Issuer参照) "4.1.2.6節 Subject"では、後方互換性のためEメールアドレスをSubjectに入れることもあると書かれています。
RFC 3280で受理できると規定された属性タイプとRFC 2253、RFC 2256の属性タイプ名を表にまとめてみました。相互運用性上ややヤバメなのを黄色、比較的頻繁に使用され非常にヤバメなのをオレンジで記してあります。

emailAddress、domainComponent、serialNumberなんかは規定や例が片方にしかなかったり、そもそもRFC 3280で規定がなかったりなど問題を起こしそうな雰囲気です。stateOrProvinceがヤバイ理由は別の機会に説明します。
これらの表に無いものは概ねOID 10進数ドット繋ぎ(例 2.5.4.30等)で表記されることになります。
以下に表記する側、即ち文字列を生成する側の属性タイプに関する問題点をまとめます。
・どれをタイプ名で表示でき、どれがOID表記(例 2.5.4.30)となるのか明確でない
・大文字か小文字か明確でない(例は大文字だがtype nameの定義は小文字)
・RFC 225XではRFC 3280で規定された利用可能属性タイプが網羅されていない
属性値から属性値を表す文字列への変換は"RFC 2253 2.4. Converting an AttributeValue from ASN.1 to a String"で規定されています。
そのままではマズイ文字のエスケープについては規定に書かれた通りやるのは当たり前として、文字列比較の際に相互運用性上問題になりそうなところはこの辺りです。
・値が文字列表現できれば、そのままUTF-8エンコーディングで表記
・できなければ"#"+属性値のBERエンコード16進数表記
・属性タイプがOID表記ならば"#"+属性値のBERエンコード16進数表記を使う(SHOULD)
・文字列表現したとしても1バイトを"\"+16進数として表現してよい(例 "\A6")
つまり文字列でもよいし16進数表記でも構わないということです。
さらには、属性値が文字列表現を持っているか、原文では以下
で判断して文字列で表現するか16進数表現するかを決めるのですが、全く曖昧な基準となっています。属性値はPrintableString、UTF8String、TeletexString、BMPStringなど様々なDirectoryString Typeを使うことが可能ですが、これらのASN.1型の違いによって実際の実装は異なる属性値文字列表記を返すようです。
この事については次回、実装の紹介で説明したいと思います。
"RFC 3280 4.1.2.4 Issuer"ではRFC 3280に準拠したX.509公開鍵証明書の発行者や主体者の識別名でどのようなDirectoryString Typeを使ってよいかが規定されています。これを表にまとめたのが以下です。

RFC 3280に準拠せず大元のITU-T X.509にだけ準拠する場合には特にこのような制限はありません。文字列表現があるにもかかわらずDirectoryString Typeの種類によってはRFC 2253で文字列表記とならずBER表記となってしまうような実装があるという事です。
LDAPでは一つのRDNに複数のAttributeTypeAndValuesを含めることができます。これを"Multi-valued RDN"と呼びます。複数ある場合にRFC 2253ではプラス"+"で繋いで表記します。
RFC 2253ではプラス記号の両側に空白があったとしてもこれを無いものとして受理しなければなりませんが、準拠する実装は空白をつけてはいけません。
もう一点、注意しなければならないのがASN.1エンコーディングのDERとBERの違いです。X.509公開鍵証明書はDERですが、属性値全体が16進数形式で表記される場合には属性値をBERエンコーディングして表記します。例はこんな感じ、、、
DERはBERのサブセットなので、DERであればBERでもあります。これらの大きな違いというのは
(1) DERは一意に表現され同じ意味のデータが別のエンコード値になることはない
(2) BERは同じ意味のデータを幾つか別のエンコード値で表現できる
(2-1) DERではSET OF構造の要素を辞書順ソートし一意にするがBERではソートしない
(2-2) DERはプリミティブ型があれば必ずこれのみを用いる
(2-3) BERではOCTETSTRINGなどプリミティブ型を構造型(constructor form)でも
表現することができ、固定長(definite)と終端記号(00 00)を用いる
不定長(indefinite)形式とを合わせ3種類の表現方法がある。
識別名の属性値で(2-3)のBER構造型を使うことはほぼ無いですが、(2-1)のソート順序が問題となるケースがあり、それがMulti-valued RDNの識別名であるケースです。
例として以下のMulti-valued RDNを持つ識別名を考えてみましょう。
まず、RDNはSET OFというASN.1構造を用います。この識別名がDERでエンコーディングされている場合、このMulti-valued RDNのCNとOの順序はCN(commonName)のOIDが2.5.4.3、O(organizationName)のOIDが2.5.4.10であることから値が同じ'aa'ならばCN、Oの順序になりこれはきちんとDERでソートされていると言えます。
この識別名からBER 16進数形式の属性値を作る場合に、証明書中のDERエンコードされた識別名オクテット列を用いれば全く問題ないのですが、BERを再構成しSET OFは順序は関係ない構造であるからと順序を入れ替えてBERを作ってしまうと証明書識別名と合わないことになってしまいます。
RFC 2253では相対識別名同士はカンマ(",")で繋ぎます。生成時と検証時でちょっと違っていてXAdESを生成する際にはRFC 2253の生成時の要件を満たさなければなりません。
【生成時の要件】
・属性タイプと属性値は等号("=")で繋ぐ
・RDNをカンマ(",")で繋ぐ
・カンマの両側には空白は入れない
【検証時の要件】
・属性タイプと属性値を繋ぐ等号("=")の両側に空白文字があっても受け入れる
・RDNを繋ぐカンマの両側に空白文字があってもこれを受け入れる
・RDNの区切り文字がセミコロン";"であっても受け入れる
以上、RFC 2253で識別名を文字列で表現した結果は、どうやら一意にはなりそうには無く、単純に文字列比較はできず、正規化の類も完全にこれを実装するのは難しそうだという理由が「なんとなく」おわかり頂けたでしょうか。(難しいかな、、、(^^;)
今回はこれくらいにしておきましょう。
かなり長編でマニアックな内容になってしまいゴメンナサイ。
次回はRFC 2253で識別名文字列を出力できそうな実装が、実際どうなっているのかについてご紹介したいと思ってます。
ではでは
XAdESの証明書識別名の比較問題 (もくじ)
・第1回 はじめに
・第2回 XAdESにおける名前比較の要件
・第3回 なぜCAdESやXMLDSigでは問題とならないのか
・第4回 RFC 2253による識別名バイナリの文字列化
・第5回 RFC 2253識別名文字列を比較する際の相互運用性阻害要因
前回は証明書識別名のASN.1バイナリを文字列表現するための標準RFC 2253を紹介し、RFC 2253により生成された文字列一通りにはならず、文字列一致をさせることは難しいということを説明しました。
今回は、RFC 2253文字列の一致確認をする際の相互運用性阻害要因について説明していこうと思います。
属性タイプ(AttributeType)について
属性タイプの表記はRFC 2253 2.3節で規定されています。
If the AttributeType is in a published table of attribute types associated with LDAP [4], then the type name string from that table is used, otherwise it is encoded as the dotted-decimal encoding of the AttributeType's OBJECT IDENTIFIER.
(RFC 2253 2.3節Converting AttributeTypeAndValueより)
RFC 2253によると一般的な属性タイプは"C"(国名:countryName)、"O"(組織名:organizationName)のような属性タイプの名前(type name)を表す文字列で表記されます。
ここでまず問題となるのが"published table of attribute types"が一体どれを指しているのかという事です。"RFC 2256 5. Attribute Types"を指していると思われますが、明確にこれを指しているわけではない事、RFC 3280で使用できる属性タイプをカバーしているわけではない事、RFC 2256では小文字で始まる文字列(例 "cn", "serialNumber", "o", "title"等)である事といった点が気になります。
RFC 2253 2.3節の例では以下のように大文字で限定されたものだけです。
String X.500 AttributeType
------------------------------
CN commonName
L localityName
ST stateOrProvinceName
O organizationName
OU organizationalUnitName
C countryName
STREET streetAddress
DC domainComponent
UID userid
(RFC 2253 2.3節Converting AttributeTypeAndValueより)
XAdESではディレクトリ一般ではなくデジタル証明書に限定して考えればいいと思うのですが、広く使われている証明書プロファイルであるRFC 3280では、受け入れられる属性タイプに関する規定があります。(RFC 3280 4.1.2.4 節 Issuer参照) "4.1.2.6節 Subject"では、後方互換性のためEメールアドレスをSubjectに入れることもあると書かれています。
RFC 3280で受理できると規定された属性タイプとRFC 2253、RFC 2256の属性タイプ名を表にまとめてみました。相互運用性上ややヤバメなのを黄色、比較的頻繁に使用され非常にヤバメなのをオレンジで記してあります。

emailAddress、domainComponent、serialNumberなんかは規定や例が片方にしかなかったり、そもそもRFC 3280で規定がなかったりなど問題を起こしそうな雰囲気です。stateOrProvinceがヤバイ理由は別の機会に説明します。
これらの表に無いものは概ねOID 10進数ドット繋ぎ(例 2.5.4.30等)で表記されることになります。
以下に表記する側、即ち文字列を生成する側の属性タイプに関する問題点をまとめます。
・どれをタイプ名で表示でき、どれがOID表記(例 2.5.4.30)となるのか明確でない
・大文字か小文字か明確でない(例は大文字だがtype nameの定義は小文字)
・RFC 225XではRFC 3280で規定された利用可能属性タイプが網羅されていない
Attribute Valueについて
属性値から属性値を表す文字列への変換は"RFC 2253 2.4. Converting an AttributeValue from ASN.1 to a String"で規定されています。
そのままではマズイ文字のエスケープについては規定に書かれた通りやるのは当たり前として、文字列比較の際に相互運用性上問題になりそうなところはこの辺りです。
・値が文字列表現できれば、そのままUTF-8エンコーディングで表記
・できなければ"#"+属性値のBERエンコード16進数表記
・属性タイプがOID表記ならば"#"+属性値のBERエンコード16進数表記を使う(SHOULD)
・文字列表現したとしても1バイトを"\"+16進数として表現してよい(例 "\A6")
つまり文字列でもよいし16進数表記でも構わないということです。
さらには、属性値が文字列表現を持っているか、原文では以下
If the AttributeValue is of a type which does not have a string representation defined for it
(RFC 2253 2.4. Converting an AttributeValue from ASN.1 to a Stringより)
で判断して文字列で表現するか16進数表現するかを決めるのですが、全く曖昧な基準となっています。属性値はPrintableString、UTF8String、TeletexString、BMPStringなど様々なDirectoryString Typeを使うことが可能ですが、これらのASN.1型の違いによって実際の実装は異なる属性値文字列表記を返すようです。
この事については次回、実装の紹介で説明したいと思います。
"RFC 3280 4.1.2.4 Issuer"ではRFC 3280に準拠したX.509公開鍵証明書の発行者や主体者の識別名でどのようなDirectoryString Typeを使ってよいかが規定されています。これを表にまとめたのが以下です。

RFC 3280に準拠せず大元のITU-T X.509にだけ準拠する場合には特にこのような制限はありません。文字列表現があるにもかかわらずDirectoryString Typeの種類によってはRFC 2253で文字列表記とならずBER表記となってしまうような実装があるという事です。
Multi valued RDNについて
LDAPでは一つのRDNに複数のAttributeTypeAndValuesを含めることができます。これを"Multi-valued RDN"と呼びます。複数ある場合にRFC 2253ではプラス"+"で繋いで表記します。
RFC 2253ではプラス記号の両側に空白があったとしてもこれを無いものとして受理しなければなりませんが、準拠する実装は空白をつけてはいけません。
もう一点、注意しなければならないのがASN.1エンコーディングのDERとBERの違いです。X.509公開鍵証明書はDERですが、属性値全体が16進数形式で表記される場合には属性値をBERエンコーディングして表記します。例はこんな感じ、、、
O=Test (※PrintableStringの場合)
↓属性値16進数表記
2.5.4.10=#310D300B060355040A130454657374
DERはBERのサブセットなので、DERであればBERでもあります。これらの大きな違いというのは
(1) DERは一意に表現され同じ意味のデータが別のエンコード値になることはない
(2) BERは同じ意味のデータを幾つか別のエンコード値で表現できる
(2-1) DERではSET OF構造の要素を辞書順ソートし一意にするがBERではソートしない
(2-2) DERはプリミティブ型があれば必ずこれのみを用いる
(2-3) BERではOCTETSTRINGなどプリミティブ型を構造型(constructor form)でも
表現することができ、固定長(definite)と終端記号(00 00)を用いる
不定長(indefinite)形式とを合わせ3種類の表現方法がある。
識別名の属性値で(2-3)のBER構造型を使うことはほぼ無いですが、(2-1)のソート順序が問題となるケースがあり、それがMulti-valued RDNの識別名であるケースです。
例として以下のMulti-valued RDNを持つ識別名を考えてみましょう。
CN=aa+O=aa,C=JP
まず、RDNはSET OFというASN.1構造を用います。この識別名がDERでエンコーディングされている場合、このMulti-valued RDNのCNとOの順序はCN(commonName)のOIDが2.5.4.3、O(organizationName)のOIDが2.5.4.10であることから値が同じ'aa'ならばCN、Oの順序になりこれはきちんとDERでソートされていると言えます。
この識別名からBER 16進数形式の属性値を作る場合に、証明書中のDERエンコードされた識別名オクテット列を用いれば全く問題ないのですが、BERを再構成しSET OFは順序は関係ない構造であるからと順序を入れ替えてBERを作ってしまうと証明書識別名と合わないことになってしまいます。
識別名(DN)全体について
RFC 2253では相対識別名同士はカンマ(",")で繋ぎます。生成時と検証時でちょっと違っていてXAdESを生成する際にはRFC 2253の生成時の要件を満たさなければなりません。
【生成時の要件】
・属性タイプと属性値は等号("=")で繋ぐ
・RDNをカンマ(",")で繋ぐ
・カンマの両側には空白は入れない
【検証時の要件】
・属性タイプと属性値を繋ぐ等号("=")の両側に空白文字があっても受け入れる
・RDNを繋ぐカンマの両側に空白文字があってもこれを受け入れる
・RDNの区切り文字がセミコロン";"であっても受け入れる
以上、RFC 2253で識別名を文字列で表現した結果は、どうやら一意にはなりそうには無く、単純に文字列比較はできず、正規化の類も完全にこれを実装するのは難しそうだという理由が「なんとなく」おわかり頂けたでしょうか。(難しいかな、、、(^^;)
今回はこれくらいにしておきましょう。
かなり長編でマニアックな内容になってしまいゴメンナサイ。
次回はRFC 2253で識別名文字列を出力できそうな実装が、実際どうなっているのかについてご紹介したいと思ってます。
ではでは
XAdESの証明書識別名の比較問題 (もくじ)
・第1回 はじめに
・第2回 XAdESにおける名前比較の要件
・第3回 なぜCAdESやXMLDSigでは問題とならないのか
・第4回 RFC 2253による識別名バイナリの文字列化
・第5回 RFC 2253識別名文字列を比較する際の相互運用性阻害要因