要約

  • X.509 v3の拡張は、OID、既定値が偽のcriticalブール値、DERで符号化された拡張値から成り、その選択も証明書署名の対象になる。
  • 未知または処理不能なクリティカル拡張があれば拒否しなければならない。未知の非クリティカル拡張は無視できるが、認識済みの拡張は非クリティカルでも処理が必要である。
  • criticalは重要度や正しさを表さない。意味を実行する能力がない検証器に、受理を許すかどうかを決める。

固定された証明書に未来の制約を置く場所はなかった

1993年のPEM鍵管理を定めたRFC 1422は、証明書の内容を大きく七つに整理していた。バージョン、シリアル番号、署名、発行者、有効期間、主体、主体公開鍵である。1988年版X.509を土台にしたこの形式は、名前と鍵の結び付きを運べたが、後世の別名、鍵用途、ポリシー、委任制限を一つずつ追加する一般的な棚は持っていなかった。

X.509 v3は拡張の列を加えた。1999年のRFC 2459は、インターネット向けに標準拡張を選びながら、組織や共同体が独自OIDを定義できる余地も残した。外側の形式を変えずに、新しい意味を内側へ加えられる。

しかし拡張性は、受信側に判断を要求する。出荷済みのソフトウェアは、まだ存在しなかったOIDを知らない。未知をすべて拒否すれば進化が止まり、すべて無視すれば新しい制限ほど古い実装で消えてしまう。

criticalは「重要」ではなく失敗条件だった

RFC 5280のExtensionは三要素である。extnIDが意味の種類をOIDで示し、extnValueが拡張固有値のDER符号を格納する。criticalは既定値FALSEのブール値で、理解できない場合の結末を示す。

証明書利用システムがクリティカル拡張を認識できなければ、証明書を拒否する。OIDを知っていても内容を処理できなければ同じである。未知の非クリティカル拡張は無視してよい。ただし認識した非クリティカル拡張まで任意になるわけではなく、処理しなければならない。

このビットは処理順も危険度も表さない。署名を強くせず、発行者の調査が正しいことも保証しない。署名が守るのは発行者が記したOID、値、criticalの選択である。ビットが真なら、その意味を適用できない受信者は成功を返してはならない。

同一種類の拡張を一枚の証明書に複数入れることも禁じられる。検証器が相反する二つの値から都合のよい方を選ぶ余地を残さないためである。

無視すると委任範囲が広がる拡張

主体欄が空で、唯一の識別情報がsubjectAltNameにある場合、その拡張はクリティカルでなければならない。旧式の検証器が無視すれば、誰の鍵なのかを記した唯一の場所を読まずに通過してしまう。

下位証明書の署名検証に使われるCA証明書では、basicConstraintsを含め、クリティカルにする必要がある。cAはその鍵が認証局として使えるかを示し、パス長は委任の深さを制限できる。ここを飛ばすことは補助情報の欠落ではなく、権限境界の消去になる。

nameConstraintsは、その後の証明書が名乗れる名前空間を制限する。準拠CAはこれをクリティカルにする。特定ドメインだけを発行できる中間CAが、制約を知らない実装から無制限に見えてはならない。ポリシー制約やinhibitAnyPolicyも、パスが持ち越せるポリシーを狭めるため、同じ失敗条件を必要とする。

一方、すべての拡張がクリティカルではない。パス構築を助ける識別子や参照先は、知らなくても本来の検証が可能なことがある。判断基準は名前の深刻さではなく、その意味を除いた証明書が同じ権限を表すかどうかである。

IP資源証明書は理解を要求し、TLS Featureは旧実装を残した

RFC 3779は、IPアドレスブロックとAS番号の利用範囲を表す拡張を定め、クリティカルにすることを推奨した。資源証明書を本来の目的で使う依存者は、どのアドレスや番号が委ねられたのかを理解しなければならない。署名だけを確認して資源範囲を捨てると、証明書が答えていない権利まで認めかねない。

TLS Feature拡張のRFC 7633は逆の既定を選んだ。クリティカルにすると、拡張を知らない旧実装が証明書全体を拒否するため、通常は推奨されない。旧クライアントを排除すること自体が意図なら選べるが、無自覚に互換性を壊すべきではない。

非クリティカルは到達範囲を守る代わりに、すべての受信者が新規則を実行したという主張を捨てる。クリティカルは規則の強制性を守る代わりに、未対応実装を切り離す。ビットは移行コストを消さず、どちらが負担するかを明示した。

パス検証コードが最後の「いいえ」を実行した

RFC 3280は2002年、拡張処理を詳細な証明パス検証手順に組み込んだ。RFC 5280も、適用されるクリティカル拡張を認識・処理できなければ失敗するという外部結果を維持した。実装内部の手順が違っても、未知の必須意味を残したまま成功してはならない。

OIDの公開とCAの署名だけでは、依存者の挙動は変わらない。受信側の実行コードが識別し、復号し、条件を検査し、必要なら拒否して初めて、その規則はローカルな現実になる。標準は検査可能な共通語を作るが、採用済みのコードを代行しない。

2024年のRFC 9618にも同じ原則が見える。アプリケーションが不要なポリシー検証を無効にすることはできる。しかしクリティカルなポリシー関連拡張に出会えば、未知として扱い拒否しなければならない。機能を持たない選択はできても、実行したふりはできない。

検証成功は万能な信頼証明ではない

成功が示すのは、選ばれたパス、信頼アンカー、時刻、署名、用途と適用制約がその検証器で成立したことまでである。主体の誠実さ、CAの判断の正しさ、秘密鍵の無事、あらゆる業務権限までは証明しない。

既知OIDでも値が壊れている場合があり、正しく符号化されても制約を満たさない場合がある。同じ末端証明書に複数のパスが存在し、中間CAの制約が異なることもある。criticalは必須意味の黙殺を防ぐが、信頼判断全体を一ビットへ集約しない。

根拠にも限界がある。RFC 1422、RFC 2459、RFC 3280、RFC 5280、RFC 3779、RFC 7633、RFC 9618は構造と規定動作、歴史を示す。現在の製品比率、障害頻度、特定ブラウザやライブラリの準拠状況は示さない。

X.509 v3の功績は、証明書を拡張可能にしただけではない。新しい制約が旧ソフトウェアの無知によって無効化されるなら、その事実を成功の陰に隠さず、拒否として表面化させたことにある。