要約

  • RFC 9596は、COSEオブジェクト全体の種類を示す保護ヘッダー typ(ラベル16)を登録した。payloadやciphertextの種類を示すcontent typeとは役割が違う。
  • COSEライブラリは typ の意味を判断せず、アプリケーションへ渡す。期待値、欠落、検証分岐、鍵用途、認可を実装側が結び付けて初めて防御になる。

署名検証を通過したCOSEオブジェクトが届く。保護ヘッダーの型も、その入口で期待していた値である。ディスパッチャーは処理先を選べる。それでも、処理を実行してよいとはまだ言えない。

RFC 9596が追加したのは、この途中の判断材料である。複数のCOSEオブジェクト種別を受け取るアプリケーションが、オブジェクト全体の型を明示し、取り違えを避けられるようにした。汎用COSE実装は、その業務上の意味を裁定しない。値をアプリへ受け渡し、採用する規則はアプリに任せる。

短いラベルが担うのは経路選択であって、権限付与ではない。ここを一つの「有効」表示にまとめると、最も重要な拒否点が見えなくなる。

外側の型と内側の型を混ぜない

RFC 9052のcontent typeは、payloadまたはciphertextに入ったデータの種類を示す。一方、RFC 9596の typ はCOSEオブジェクト全体を分類する。同じメディアタイプ構文を利用しても、指している層は異なる。

たとえば、署名付き受領証と署名付きアテステーション結果が、どちらもCBORのペイロードを運ぶことはあり得る。内側がCBORだという情報だけでは、外側に適用する検証契約を選べない。受領証、イベント、トークン、制御要求では、必要な鍵、claims、audience、再送対策、許される副作用が違う。

typ の値には、CoAP Content-Formatsレジストリの符号なし整数か、パラメーターを含み得るメディアタイプ文字列を使える。相互運用上は便利だが、監査時に数値と文字列を一つの名前へ早々に正規化してはならない。受信時の表現、保護領域のバイト列、比較した期待値を残す必要がある。

「型」という一項目だけを保存すると、外側を検証したのか、ペイロードを検証したのか、両方なのかを後から区別できない。

改ざん不能でも、内容が正しいとは限らない

RFC 9596は typ を非保護ヘッダーに置くことを禁止する。保護ヘッダーが暗号学的に認証されるCOSE構造では、途中で型を変更すれば検証が失敗する。宣言と署名対象が切り離されない点は重要である。

ただし、署名者自身が間違った型を選ぶことはできる。廃止予定の別名、別エンドポイント向けの型、許可されないパラメーター、あるいは正しい外側の型と不適合なペイロードを署名できる。暗号は、間違いを正しい意味へ変換しない。

仕様がCOSE実装に意味判断を求めないのはこのためだ。ライブラリは値をアプリへ渡すだけである。明示的型付けを採るアプリは、期待外の値を拒否し、必要な場面で欠落しているオブジェクトも拒否するべきだとRFCは述べる。

つまり制御の実体は拒否にある。表示画面に typ が見えていても、誤値や欠落を互換モードで通すなら型分離は成立していない。

検証規則まで排他的でなければならない

RFC 9596は、RFC 8725のJWT明示的型付けを安全上の根拠にする。異なるJWT用途が取り違えられる場合、型を分ければ混同を減らせる。ただしRFC 8725は、種類ごとの検証規則を相互排他的にすることも求めている。

COSEでも同じである。二つの型が、用途制限のない同じ鍵、広い既定audience、ほぼ同じ任意claims、共通の認可処理を使うなら、ラベルだけを変えても受理面は重なったままだ。型を見ない旧経路か、両方を満たす寛容な検証器が代入点になる。

一つの分岐は、型、許されるCOSE構造、必須保護フィールド、ペイロード型、必須claims、issuer、audience、鍵用途、鮮度、リプレイ規則、入口、操作をまとめて契約にする必要がある。誤ったオブジェクトは、共通業務ロジックに入る前に落とす。

RFC 8725は、既存の種類が typ を見ないため、明示型だけでは区別できない場合もあると警告する。移行完了を送信側の付与率で測ってはいけない。受信側規則の版と、負の試験が実際に失敗した記録が必要だ。

レジストリは名前を調整し、信頼を決めない

IANAのCOSE Header Parametersには、typ がラベル16として登録されている。値の名前空間はMedia TypesとCoAP Content-Formatsにつながる。独立した実装が衝突せず同じ意味を共有するための基盤である。

しかし登録済みの型だからといって、どのアプリでも許可されるわけではない。IANAは、その入口が型を有効にしたか、署名鍵がその型を発行できるか、パラメーターが許容されるか、ペイロードが準拠するかを判断しない。

公開レジストリ、エンドポイント別の受理ポリシー、個別処理の証拠は別々に保つべきだ。「既知の型」を「信頼する型」へ昇格させると、目録管理者が各サービスの認可を事実上支配する。

これは最小初期仕様の健全な使い方でもある。共通層は保護された場所と値の形式を定める。将来の型と規則は各参加者がローカルに採用する。実装、検証、拒否が起きて初めて採用は現実になる。

受信から副作用までを別々の証拠にする

保存すべき項目は、受信バイトのダイジェスト、COSE構造、保護ヘッダーのバイト列、typ の値と表現、ペイロードcontent type、入口、操作、期待型集合、規則版、暗号検証、鍵IDと用途、構文解析、必須claims、issuer、audience、鮮度、リプレイ判定、認可、選択したハンドラー、観測結果である。

署名は鍵とバイト列の関係を示す。型一致は宣言が期待集合に入ったことを示す。parse成功は形を示す。プロファイル検証は意味上の条件を示す。鍵ポリシーは署名者の権限を示す。ローカル認可は今この操作を行えるかを示す。結果は実際の作用を示す。

汎用ライブラリに最終操作を代弁させてはならない。メディアタイプ登録にも鍵権限を代弁させてはならない。各コンポーネントが観測した範囲だけを記録すれば、問題が起きたとき因果の場所を失わずに済む。

docs/heng-lu-note.md の現実レイヤーは、標準の価値を弱める考えではない。名前、検証、権限、実行を順番どおりに置く考えである。RFC 9596の短い信号は、走っているコードが境界を実行したときにのみ強い。

出典