要約

  • draft-ietf-cose-hpke-27 では、HPKE の暗号文を COSE_Encrypt / COSE_Encrypt0 の外で運び、構造内の ciphertext を nil にできる。その後に付けた COSE 署名や MAC は、分離された暗号文を覆わない。
  • AEAD は分離バイトの完全性を守り得る。しかし AEAD タグは、外側の署名、公開された送信者の本人性、業務認可、処理の完了証明とは別の結果である。
  • 2026年10月1日時点で改訂27は IESG の AD Evaluation::AD Followup にあり、まだ RFC ではない。三つの実装による例の検証は、個々の本番システムの保管設計を保証しない。

署名対象を確認する最も確実な方法は、オブジェクト図を見ることではない。署名 API に渡されたバッファを見ることである。

この原則が必要になるのは、分離コンテンツが「中にあるように見える」からだ。アプリケーションは COSE オブジェクトを一つのレコードとして扱い、暗号文を別のストレージから取得する。UI は両者を同じメッセージとして表示する。だが暗号計算に入った境界は UI の境界と一致しない。

COSE-HPKE 改訂27 は明確に警告する。分離暗号文を使う COSE_Encrypt または COSE_Encrypt0 に、後から COSE_Sign、COSE_Sign1、COSE_Mac、COSE_Mac0 を適用しても、その暗号文は保護範囲に入らない。実装者は分離暗号文にも完全性保護を与えなければならない。

分離は欠落ではなく、別経路である

RFC 9052 では、COSE の内容を別送できる。構造内の場所は nil となり、アプリケーションが必要なバイト列を外部から供給する。大きなファイルを複製せず、制御情報とデータを異なる寿命で管理できるため、実務上の利点は大きい。

統合暗号モードでは HPKE が ct を出力する。改訂27のテキスト によれば、ct は COSE_Encrypt0 に格納しても、別送してもよい。鍵暗号モードでは、レイヤー0が CEK で内容を一度暗号化し、レイヤー1が各受信者向けに CEK を HPKE で保護する。XML 版 も同じ構成を示す。

ここでセキュリティの単位が変わる。COSE オブジェクトだけでなく、外部オブジェクトの不変な版、長さ、ハッシュ、取得経路までが一つの判断材料になる。latest という別名、上書き可能な URL、CDN の範囲結合、透過圧縮は、署名済みの制御情報を変えずに実際の入力を変えられる。

同じ「完全性」という言葉に別の鍵がある

外側の署名または MAC は、Sig_structure / MAC_structure に入った正確な値を検証する。分離暗号文がその入力に含まれなければ、署名の成功は暗号文について何も追加しない。

一方、レイヤー0の AEAD は暗号文自体を守れる。正しい CEK、nonce、追加認証データでタグが検証できれば、その文脈での改変は検出される。これは十分に強い完全性だが、外側の署名と同じ主張ではない。対称鍵のもとで有効であることと、誰が公開的に署名したかは異なる。

さらに HPKE Open は受信者鍵による処理結果を示す。kid の解決は鍵を主体に結び付ける。認可エンジンは現在の操作権限を判断する。コミット記録は外部状態の変化を示す。

証拠 答えられる問い 答えられない問い
外側の署名/MAC 覆われたオブジェクトが鍵のもとで正しいか 分離バイトがその入力だったか
AEAD タグ 暗号文と AAD が CEK のもとで正しいか 公開送信者は誰か
HPKE Open 受信者鍵でカプセル化を処理できたか 送信者に業務権限があるか
本人性判断 鍵がどの主体に属するか その操作が許可されるか
認可 現在の規則が操作を許すか 実際に状態が変わったか
効果記録 外部変化が起きたか 前段の証拠との連続性

Recipient_structure が固定する範囲

COSE-HPKE は Recipient_structure を用い、次の下位レイヤーのアルゴリズムと受信者の保護ヘッダーを HPKE の info に入れる。CEK を保護する鍵合意と、その CEK を使うコンテンツ暗号アルゴリズムを結び付けるためである。

この構造は RFC 8949 の決定的エンコーディングに従う。送信者と受信者は、メッセージに直接載らない同じ入力を独立に作る。表現揺れを許せば、意味が同じでも異なるバイト列になり、検証は失敗する。

決定的エンコードは相互運用性を高めるが、オブジェクトストアの不変性や鍵の所有者、認可までは決めない。一つの曖昧さを解いた制御に、全層の保証を負わせてはならない。

recipient_extra_info は、通信路の外で両者が知る文脈を HPKE に結び付けられる。テナント、セッション、用途などを含められる一方、値そのものはメッセージに載らない。取得方法、版、欠落時の拒否規則を別途監査しなければ、空値へのフォールバックが保護を消す。

kid は検索キーであり、権限証ではない

草案は、送信者が使用した受信者の静的公開鍵を示すため kid を推奨する。保護ヘッダーに置かれれば Recipient_structure 経由で HPKE の鍵スケジュールにも結び付く。これは重要な改善である。

しかし短い kid は、それだけでは主体を表さない。テナントごとに同じ値があり得る。ローテーション後も古いキャッシュが残り得る。復旧鍵は復号できても通常運用の権限を持たないかもしれない。名前空間、鍵版、所有者、用途、有効期間、失効を記録する必要がある。

ek は未保護ヘッダー領域に置かれるが、「未保護」は「何をされても成功する」という意味ではない。改変は通常 HPKE や後段の認証失敗として現れる。フィールド位置から結論を作らず、受信値のハッシュと実際の処理結果を記録するべきだ。

受信者への暗号化と送信者認証を分ける

RFC 9180 は現在広く参照される HPKE の基盤である。後継 HPKE 草案 は承認されれば RFC 9180 を置き換えるが、証拠凍結時点では作業中だ。資産台帳には「HPKE」だけでなく、版、モード、KEM/KDF/AEAD の組合せが必要である。

Base モードの KEM は送信者を認証しない。COSE 署名や MAC を追加できるが、その保護範囲を確認しなければならない。RFC 9338 は、暗号化データへのカウンター署名と平文への主張を区別する。暗号文の存在を証明しても、平文の意味を承認したことにはならない。

RFC 9053、IANA COSE レジストリ、IANA HPKE レジストリ は名称と番号を調整する。登録済み番号は、製品の安全な設定、鍵ローテーション、古い方式の拒否、認可の実施を認証しない。

文書の成熟度と運用保証は別欄に置く

Datatracker は、改訂27を Proposed Standard を目指す COSE WG 文書として示し、2026年10月1日時点で IESG の AD Evaluation::AD Followup に置いていた。履歴 は9月12日の改訂を記録する。RFC 番号はまだない。

shepherd write-up は広い議論と、IETF 125 で三つの独立実装が例の検証に使われたとの報告を記す。実装例は重要だが、特定の製品が外部 Blob の版を固定し、文脈を正しく導出し、認可を実施している証明ではない。

形容詞ではなくカバレッジ・マニフェストを残す

判断ごとに、COSE の全バイト、メッセージ型と tag、保護/未保護ヘッダー、内包/分離状態、不変 Blob ロケーター、暗号文の長さとハッシュ、署名/MAC 入力ハッシュ、AEAD と AAD のハッシュおよびタグ結果、HPKE モードとスイート、ek と Recipient_structure のハッシュ、追加文脈の由来、解決された鍵版、Open 結果、信頼境界内の平文ハッシュ、本人性、認可、コミット、観測効果を残す。

秘密鍵や不要な平文をログに置く必要はない。ハッシュと版付き参照と判断記録で連続性は示せる。外側の署名が Blob を覆わないなら、その不在をそのまま保存する。AEAD が安全に補っていても、曖昧な signed=true に変換してはならない。

Minimum Initial Specification は、この小さな共通マニフェストを定めつつ業務方針を局所に残す。Running-Code Primacy は実際の API 入力を観察する。The Policy Mirror はストレージと鍵解決の既定値が権力を配ることを示す。Reality Layers は構文、バイト、証明、本人性、許可、効果を分離する。

情報源