要約

  • 保護されたcritに、検証側が理解・対応していない拡張名が一つでもあれば、暗号署名が一致していても、そのJWSは無効である。
  • この仕組みは、古い実装が新しい意味を黙って無視し、従来の規則でメッセージを受理することを防ぐ。
  • 署名演算、JOSEの意味処理、業務上の受理には別々の責任者と証跡が必要である。

「署名OK」の先にある不合格

あるAPIゲートウェイがJWSを受け取る。アルゴリズムを特定し、正しい鍵を選び、署名入力を再構成する。演算結果は一致した。監視画面に緑の印を付けるだけなら、ここで処理は終わったように見える。

しかし、保護ヘッダーには追加のパラメーターがあり、その名前はcritにも列挙されている。ゲートウェイはその拡張を実装していない。RFC 7515の答えは明確だ。この実装にとってJWSは無効であり、未知の項目を飛ばして通常の意味で扱ってはならない。

矛盾しているのではない。署名の成功は、特定の鍵と手順に対してバイト列が対応したという事実を示す。一方、クリティカルな拡張は、そのバイト列の構成や解釈に追加の規則が不可欠だと宣言する。受信者が規則を知らなければ、何が真正であるかは確かめられても、真正なものが何を意味するかは確かめられない。

critの値はヘッダーパラメーター名の配列である。そこにある各拡張はJOSEヘッダーに実在し、受信者が理解して対応していなければならない。空の配列、重複名、存在しないパラメーターの指定は認められない。JWSやJWAですでに定義された通常の名前を改めて並べる場所でもない。

また、critは必ず保護ヘッダーに置かれる。必要な意味の一覧だけが改ざん可能なら、攻撃者は理解されない名前を削り、古い受信者に処理を続けさせられるからだ。未知でも非クリティカルなパラメーターは一般に無視できる。この差が、任意の拡張性と安全な意味変更を両立させる。

Sakimuraらが設けた能力確認

RFC 7515には、Michael B. Jones、John Bradley、Nat Sakimuraの三人が著者として記載されている。Sakimuraはデジタルアイデンティティ標準に長く関わり、OpenID Foundationでも指導的役割を担う。ただし、ここで扱う設計を一人の発明とするのではなく、共同著者と標準化コミュニティによる仕事として捉える必要がある。

この設計が解くのは、長寿命の分散システム特有の問題だ。発行者と受信者は同時には更新されない。新しい拡張を全員の更新まで待てば進化が止まる。逆に、未対応の受信者が新しい規則を無視して受理すれば、相互運用しているように見えながら意味は分裂する。

critは未来の拡張を一つずつ予言しない。誰が先へ進めるかを決める。発行者は、そのJWSで欠かせない拡張を保護された形で宣言する。受信者は、名前を見たことがあるだけでなく、定義どおり処理できる場合に限って先へ進む。署名の成功はこの能力確認を免除しない。

「critical」は危険度のラベルでもない。無視すると意味や安全特性が変わるかどうかが焦点である。目立つ業務メタデータが任意である一方、小さなエンコード設定が署名入力を変えることもある。拡張の設計者とプロファイルの管理者には、その差を明示する責任がある。

b64:falseが作る互換性の防火壁

RFC 7797の非エンコードペイロードは、critの働きを具体化する。通常のJWSはペイロードをbase64urlでエンコードした値から署名入力を作る。保護パラメーターb64をfalseにすると、エンコードされていないペイロードを用いる。署名対象となる正確なバイト列と、シリアライゼーション上の条件が変わる。

このオプションを使うJWSは、b64をcritにも含めなければならない。RFC 7797を知らない古い検証側は、未知のクリティカル拡張を検出して拒否する。従来のbase64url規則を当てはめて処理したり、自分が組み立てた別の入力についての演算成功を、メッセージ全体の成功と呼んだりできない。

実装能力と利用許可も別である。アプリケーションプロファイルでは、エンコード有無を一貫して使うことが推奨され、コンパクトシリアライゼーションではペイロードの文字に注意が要る。さらにJWTではb64:falseの利用そのものが禁じられている。汎用JWSライブラリが正しく理解していても、JWTアプリケーションは拒否しなければならない。

ここには三つの問いがある。暗号演算は正しかったか。必須の拡張をすべて理解して適用したか。そのメッセージ型と用途で組み合わせが許されるか。一つ目の成功を残りへコピーする設計は、層ごとの権限を失わせる。

アルゴリズムを知ることと許すこと

RFC 7518はJOSEのアルゴリズムと識別子を定義する。しかし、ライブラリがあるアルゴリズムを計算できることと、アプリケーションが採用してよいことは同義ではない。RFC 7515は、許容するアルゴリズムの判断をアプリケーションに残している。数理的に正しい署名でも、ポリシーで禁止された方式なら拒否される。

RFC 8725はJWTについて、この境界を運用規則にする。受理するアルゴリズムを制限し、送信者が制御できる入力だけで検証方法を選ばない。発行者、主体、オーディエンス、用途固有のクレームを検証する。異なる種類のJWTには互いに排他的な規則を設け、別目的のトークンが混同されないようにする。

critは発行者を信頼済みにせず、オーディエンスを確認せず、操作を承認しない。拡張名を双方が知っていることも、その設定が安全だという審査ではない。これは「理解していなければ進めない」という前提条件であり、理解した後の評価を肩代わりするものではない。

複数署名では、どの成功かを残す

JWSのJSONシリアライゼーションは複数の署名を格納できる。RFC 7515の一般的な手順では少なくとも一つが有効であることを求めるが、何を受理条件にするかはアプリケーションが決める。より厳しい閾値も選べる。

各署名は独自の保護ヘッダーを持ち、異なるクリティカル拡張を要求し得る。移行中、新しい署名が新アルゴリズムや拡張を用い、古い署名が互換性を支えることがある。「どれか一つ」の規則を期限なく残せば、古い道が恒久的なダウングレードになる。「すべて」を突然要求すれば、未更新の正当な受信者が停止する。

必要なのは、対象となる署名、許容する鍵と拡張、対象オーディエンス、並存期間、旧経路の終了条件を明文化することだ。ログも、全体が成功したという一行ではなく、どの署名がどの規則を満たしたかを残す。そうしなければ、移行の進捗と依存先を測れない。

証跡を三つの判定に分ける

検証記録の第一層は暗号情報である。アルゴリズム、鍵の参照、署名入力の構成、演算結果を持つ。第二層はJOSE処理で、保護ヘッダーの構文、遭遇したクリティカル名、各拡張を処理した実装、未知・不正な項目による拒否を記録する。第三層はアプリケーションで、プロファイル、発行者、オーディエンス、クレーム制約、認可判断、要求された効果を結び付ける。

秘密鍵やトークン全文をログに置く必要はない。安定した相関IDと理由コードが重要だ。署名は一致したのに拡張未対応だった事象を「署名不正」と呼べば、担当者は誤って鍵を調べる。JOSE処理が通っただけのものを「有効なトークン」と呼べば、オーディエンスや業務認可の拒否が見えなくなる。

critが守るのは、技術的な後方互換性だけではない。「署名できた」と「内容を理解した」を同じ言葉で報告しないための責任境界である。Sakimuraらの規則は、知らないことを認めて拒否する振る舞いを、相互運用の一部にした。

情報源