第 3 章:オフライン認可プロトコル

本章は Authorization_Descriptor の完全なライフサイクルプロトコルフローを定義する。発行、ローカル保管、検証、失効、更新の 5 つの段階を含む。本章のフローはブループリント §2.1 の設計意図に対応する。

3.1 発行フロー(Issuance)

発行フローは Descriptor_Issuer が認可者から明示的な認可を受領した後に実行する。本仕様は発行結果の形式制約を定義するが、認可者と Descriptor_Issuer の間の具体的相互作用方式は規定しない(異なるデプロイで Web フォーム、モバイル App 認可、企業認可管理システム等の異なる形式を採用できる)。

3.1.1 発行入力

Descriptor_Issuer は発行時に MUST 以下の情報を確認済みであること:

  1. 認可者身元(grantor_id)が Descriptor_Issuer 自身の身元検証メカニズムを通過済み
  2. 認可範囲(対象 subject_fay_idterminal_idgrants)が認可者により明示的に指定済み
  3. 有効期間(not_beforenot_after)が認可者により明示的に指定済み、またはデフォルトポリシー採用

3.1.2 発行ステップ

Descriptor_Issuer は MUST 以下のステップで Authorization_Descriptor を生成する:

  1. 識別子生成:新しい descriptor_id(UUID v7)を割り当てる、MUST NOT 既使用の ID を再利用する
  2. ペイロード構築:§2.3.2 に従い DescriptorPayload を埋める、すべての required フィールドは MUST 設定する
  3. 制約検証not_after - not_before ≤ 90 日 等の制約をローカル検証する(§2.3.2 を参照)
  4. CBOR シリアライゼーション:RFC 8949 確定性エンコーディングで payload をシリアライズする
  5. デジタル署名:Descriptor_Issuer 秘密鍵を使用し §8 定義のアルゴリズムで payload バイトを署名する
  6. 構造組み立て:完全な AuthorizationDescriptor を構築、version、payload、signature を含む
  7. 記録登録:Descriptor_Issuer 内部状態ストアに当該クレデンシャルを登録(後続の失効管理用)

3.1.3 発行後の交付

発行完了後、Descriptor_Issuer は Authorization_Descriptor を対象 Fay に交付する。交付方式は本仕様の範囲外であるが、SHOULD 以下を満たす:

  1. 暗号化チャネルを通じて交付し、伝送過程でクレデンシャルが傍受されないようにする
  2. Fay が所属する iFay_Runtime に交付し、iFay_Runtime が代理保有する

3.2 ローカル保管フロー(Local Storage)

Fay は iFay_Runtime を通じて Authorization_Descriptor を対象端末に提出し、ローカル保管を行う。

3.2.1 提出メッセージ

iFay_Runtime は Protocol_Engine に DescriptorSubmit メッセージを送信する:

DescriptorSubmit (body of ProtocolMessage) {
  required descriptor : AuthorizationDescriptor
}

3.2.2 端末処理

端末は DescriptorSubmit 受領後、MUST 以下の順序で処理する:

  1. 構造検証descriptor が §2.3 で定義された構造に適合することを検証
  2. 署名検証:対応する key_id の Verification_Key を使用し signature を検証(§3.3.4 を参照)
  3. 重複チェック:ローカルに同 descriptor_id のクレデンシャルが既に保管されており、新規提出内容と既保管内容がバイトレベルで一致する場合、成功を返却;そうでなければ重複 ID エラーで拒否
  4. 保管:Authorization_Descriptor をローカル安全保管領域に暗号化保管(§3.2.3 を参照)
  5. 結果返却:iFay_Runtime に DescriptorSubmitResult メッセージを返却し、成功またはエラーコードを含める

3.2.3 保管要件

端末は MUST:

  1. Authorization_Descriptor を暗号化保管し、暗号化鍵は未認可プロセスから読み取り不可
  2. 保管媒体は SHOULD 物理的分解防止能力を備える(セキュリティチップ、TEE 等)
  3. 保管容量上限は SHOULD 1024 件以上のクレデンシャル;上限超過時は LRU ポリシーで失効済みクレデンシャルを淘汰

端末は MUST NOT:

  1. Authorization_Descriptor を平文形式で保管する
  2. 保管前に descriptor のいかなるフィールドも変更する(metadata を含む)

3.2.4 エラーコード

エラーコード発動条件
E_INVALID_STRUCTURE構造が §2.3 に適合しない
E_INVALID_SIGNATURE署名検証失敗
E_UNKNOWN_ISSUERkey_id に対応する Verification_Key が端末に未登録
E_DUPLICATE_DESCRIPTOR_ID既保管の descriptor_id と衝突し内容不一致
E_STORAGE_FULL保管容量満杯で淘汰不可
E_VALIDITY_OUT_OF_RANGEnot_after - not_before が制限超過

3.3 検証フロー(Validation)

検証フローはリソースアクセス要求のたびに実行される。本節は検証の完全なステップと判定規則を定義する。

3.3.1 検証発動

iFay_Runtime が AuthRequest を送信してリソースアクセスを要求すると、端末 Protocol_Engine は検証フローを発動する:

AuthRequest (body of ProtocolMessage) {
  required fay_id        : Fay_ID
  required resource_id   : Resource_ID
  required access_mode   : AccessMode
  required credential    : CredentialReference
}

CredentialReference {
  required type : enum["descriptor", "ticket"]
  required id   : string                      // descriptor_id または jti
}

注意:本仕様のオフライン認可シナリオでは、credential が参照するのは端末に既保管の Authorization_Descriptor であり、要求中に完全なクレデンシャルを伝送する必要はない。

3.3.2 検証ステップ(順序実行)

端末は MUST 以下の順序で検証を実行する。任一ステップ失敗時は直ちに対応するエラーコードを返却し、後続ステップを実行しない。

ステップ 1:クレデンシャル存在性

端末はローカル保管中で credential.id に対応する Authorization_Descriptor を検索する。

  • 未発見 → E_DESCRIPTOR_NOT_FOUND を返却

ステップ 2:失効状態

端末はローカル失効リストをチェックし、当該 descriptor_id が未失効であることを確認する。

  • 失効済み → E_DESCRIPTOR_REVOKED を返却

ステップ 3:有効期間

端末は現在時刻が [not_before, not_after] 区間内にあることをチェックする。

  • 現在時刻 < not_beforeE_DESCRIPTOR_NOT_YET_VALID を返却
  • 現在時刻 ≥ not_afterE_DESCRIPTOR_EXPIRED を返却

端末時計の出所:MUST 較正済みのシステム時計を使用する。端末は SHOULD 長時間オフライン時、検証要求を慎重に処理する(§3.6 時計ドリフト処理を参照)。

ステップ 4:主体マッチング

端末は payload.subject_fay_id == AuthRequest.fay_id を検証する。

  • 不一致 → E_SUBJECT_MISMATCH を返却

ステップ 5:端末マッチング

端末は payload.terminal_id == 現在端末 ID を検証する。

  • 不一致 → E_TERMINAL_MISMATCH を返却

ステップ 6:リソースとモードマッチング

端末は payload.grants を巡回し、以下の条件を満たす Grant を検索する:

  1. Grant.resource_pattern が §2.3.5 規則に従い AuthRequest.resource_id にマッチ
  2. Grant.modesAuthRequest.access_mode を含む
  3. Grant.constraints が空でない場合、すべての制約条件を満たす(制約セマンティクスは §7.4 を参照)
  • 満たす Grant が見つからない → E_AUTHORIZATION_INSUFFICIENT を返却

ステップ 7:署名検証

端末は signature.key_id に対応する Verification_Key で payload の署名を再検証する。

注意:ステップ 1–6 の高速検証完了後に署名検証を実行する。これは合理的な失敗セマンティクスを提供するためである(例:「クレデンシャル失効」を「署名失敗」より先に告知)。ただし検証通過の成功返却前に、署名検証は MUST 実行および通過済みであること。

  • 署名検証失敗 → E_INVALID_SIGNATURE を返却
  • 署名鍵が失効または期限切れ → E_VERIFICATION_KEY_INVALID を返却

3.3.3 検証通過後

7 ステップすべて通過後、端末は第 5 章フローに従い Session を作成し、iFay_Runtime に以下を返却する:

AuthResult (body of ProtocolMessage, success) {
  required status         : "granted"
  required session_id     : Session_ID
  required granted_modes  : array<AccessMode>
  required session_expires_at : timestamp
}

session_expires_at は SHOULD min(not_after, 現在時刻 + デフォルトセッション最長時間) に等しい。

3.3.4 署名検証の詳細

署名検証の具体的ステップ:

  1. descriptor.signature.key_id を抽出し、端末 Verification_Key 保管中で対応する公開鍵を検索
  2. 当該 Verification_Key が現在時刻で有効であることを検証(valid_from ≤ 現在時刻 ≤ valid_until、valid_until が設定されている場合)
  3. §2.3.3 規則に従い descriptor.payload を再 CBOR シリアライズ
  4. Verification_Key と descriptor.signature.algorithm を使用してシリアライズバイトの署名を検証
  5. 検証成功後、MUST 結果をキャッシュする(同一 descriptor はライフサイクル内で 1 度のみ署名検証が必要)

3.4 失効フロー(Revocation)

3.4.1 失効発動

認可者は Descriptor_Issuer を通じて失効要求を発動する。失効要求の具体的相互作用形式は本仕様の範囲外。

Descriptor_Issuer は失効要求受領後、MUST:

  1. 失効要求が元の認可者または失効権限を有するエンティティ由来であることを検証
  2. §2.8 に従い RevocationStatement を生成
  3. 元の Authorization_Descriptor と同じ署名鍵で失効声明に署名
  4. 失効声明を Descriptor_Issuer が維持する失効リストに追加

3.4.2 失効配布

失効声明は以下の方法で端末に配布される、端末は MUST 少なくとも 2 種類をサポートする:

  1. プル同期(Pull-based):端末はオンライン時に Descriptor_Issuer または失効サービスから増分失効リストを主動的にプルする。同期頻度は端末ポリシーで決定し、SHOULD 1 時間に 1 回以上(オンライン期間)
  2. プッシュ通知(Push-based):Descriptor_Issuer は Registration_Authority または専用失効配布サービスを通じて失効声明を端末にプッシュ
  3. クレデンシャル埋め込み(In-band):Trusted_Ticket の metadata に最近の失効リストの要約を携帯し、オンライン期間に取得したチケットに自動的に失効情報を付随させる

3.4.3 端末失効リスト維持

端末のローカル失効リストは MUST:

  1. すべての未期限切れ失効声明を永久保管する
  2. クレデンシャルの not_after 時刻経過後、対応する失効声明を MAY 削除(クレデンシャルは自然失効)
  3. 各失効声明の署名を検証し、無効署名の失効声明を拒否

3.4.4 失効発効時刻

失効声明の発効時刻は:

発効時刻 = max(失効声明が端末に到達した時刻, RevocationStatement.revoked_at)

端末は MUST 失効声明到達後の次回検証要求でただちに当該クレデンシャルを拒否することを保証する。端末は MAY すべてのアクティブ Session が失効済みクレデンシャルを参照しているか主動的にチェックし、該当する場合は第 5 章規則に従いこれら Session を強制終了する。

3.4.5 失効遅延ウィンドウ

オフライン配布の固有遅延により、以下の不可避な失効遅延ウィンドウが存在する:

シナリオ最大遅延
端末持続オンライン1 同期周期(デフォルト ≤ 1 時間)
端末短期オフライン再オンライン後の次回同期
端末長期オフライン最長遅延はクレデンシャルの not_after - 失効時刻 だが、90 日(クレデンシャル最長有効期間)を超えない

発行者は SHOULD より短い not_after(例:7 日)を設定することで最長失効遅延を制限する。

3.5 更新フロー(Renewal)

更新は本質的に新しい Authorization_Descriptor を発行して旧版を置き換えるものであり、既存クレデンシャルの修正ではない。

3.5.1 更新ポリシー

認可者または自動継続メカニズムは以下のシナリオで更新を発動できる:

  1. クレデンシャルが not_after に近づき、認可関係が依然として有効
  2. 認可範囲を調整する必要がある(grants の追加/削減)
  3. 認可制約を調整する必要がある(constraints の修正)

3.5.2 更新フロー

更新プロセス:

  1. Descriptor_Issuer は §3.1 フローに従い新しい descriptor_id を使用して新しい Authorization_Descriptor を発行
  2. 新クレデンシャルは §3.2 フローに従い端末に提出および保管
  3. 旧クレデンシャルは MAY 発行者が主動的に失効(§3.4 に従う)、または MAY 自然期限切れで失効

端末は新旧クレデンシャル並存期間中、処理優先順位:

  • 検証要求は MUST 未期限切れクレデンシャルを優先マッチング
  • 複数の未期限切れクレデンシャルがすべてマッチする場合、issued_at が最も近いクレデンシャルを使用

3.5.3 許可されない更新動作

実装は MUST NOT:

  1. 既発行クレデンシャルのいかなるフィールドも修正する(metadata を含む)
  2. 旧クレデンシャルの descriptor_id を再利用する
  3. 旧クレデンシャルが依然有効な期間にそのセマンティクスを修正する(失効 + 新規発行で実現する必要がある)

3.6 時計ドリフト処理

端末時計は長期オフラインまたはハードウェア問題によりドリフトする可能性がある。本節は時計ドリフト状況下の処理規則を定義する。

3.6.1 時計許容差

端末は有効期間を検証する際、MAY 許容差を導入する:

  • not_before に対して:最大 5 分の早期許容差を許可できる(現在時刻 ≥ not_before - 5min を受け入れ)
  • not_after に対して:MUST NOT 許容差を導入する(期限切れは期限切れ)

許容差は短期時計偏差の補償のみに使用し、有効期間制約のバイパスに使用すべきではない。

3.6.2 時計信頼性

端末は SHOULD 以下の時計異常を検出し保護措置を講じる:

  • 時計の顕著な後退(システム時計が過去へ > 1 時間ジャンプ):時計同期まで検証要求を拒否
  • 時計の顕著な前進(システム時計が未来へ > 24 時間ジャンプ):時計同期まで検証要求を拒否

3.7 完全フロー図

[Descriptor_Issuer]                    [Fay/iFay_Runtime]                   [Terminal/Protocol_Engine]
        │                                       │                                       │
        │── AuthorizationDescriptor 発行 ─────→│                                       │
        │   (デジタル署名付き)                │                                       │
        │                                       │                                       │
        │                                       │── DescriptorSubmit ─────────────────→│
        │                                       │                                       │── 署名検証 + 保管
        │                                       │←─ DescriptorSubmitResult ──────────── │
        │                                       │                                       │
        │                                       │── AuthRequest(descriptor_id 付き)─→│
        │                                       │                                       │── 7 ステップ検証
        │                                       │←─ AuthResult(granted)──────────────│
        │                                       │                                       │── Session 作成
        │                                       │                                       │
        │                                       │       【Fay が継続的にリソースアクセス】│
        │                                       │                                       │
        │── RevocationStatement 失効 ──────────────────────────────────────────────────→│
        │                                       │                                       │── 失効リストに追加
        │                                       │                                       │── 関連 Session 強制終了