Phase 1: Remote Attestation
############################
概要
****
Remote Attestation(RA)では、TEE環境と実行内容を同時に検証します:
- TEE環境の検証: AttesterとWorkerのMRENCLAVE/MRSIGNERを検証
- 実行内容の検証: Work-IDにより関数、ユーザー権限、パラメータを検証
前提:ユーザーの実行状況
************************
ユーザーは ``apc cleanroom deploy`` を実行済みです。
この時点で:
- 計算実行サーバー上にWorkerコンテナが起動済み
- TEE環境の検証はこれから実行
検証の対象
**********
1. Attester(TEE内の常駐コンテナ)
====================================
- Remote Attestation (RA) により検証
- AttesterのMRENCLAVE/MRSIGNERをチェック
- Attesterの検証により、TEE環境の正当性を確認
2. Worker(TEE内の実行環境)
================================
- Local Attestation (LA) でAttesterが検証済み
- WorkerのMRENCLAVEはAttesterにハードコーディング済み
- ユーザーはAttesterを信頼することでWorkerも信頼
.. note::
WorkerのMRENCLAVE検証は、Attesterが内部で行います。
ユーザーが直接Workerを検証するわけではありません。
Worker自体は実行内容(関数)に依らず同一のコンテナイメージであるため、
MRENCLAVEの値は固定です。この固定値をAttesterにハードコーディングすることで、
Attester起動時にWorkerのMRENCLAVEを検証できます。
3. 実行内容(関数、ユーザー、パラメータ)
==========================================
- Work-IDにより検証
- Work-IDはQuoteに含まれ、RAと同時に検証される
なぜWork-ID検証が必要か
************************
動的な情報をMRENCLAVEの対象外とした理由
========================================
RAではMRENCLAVE(初期状態のハッシュ値)を検証しますが、 MRENCLAVEは静的な値です。
実行関数の内容は含まれません。
動的な情報(実行関数、ユーザー権限、パラメータ)をMRENCLAVEの検証対象に含めることも技術的には可能ですが、
その場合、実行関数ごとにMRENCLAVEの値が変わるため、ユーザーは都度MRENCLAVEを計算する必要があります。
MRENCLAVEの計算は非常に複雑で大変な作業です。
そのため、本システムでは静的な部分と動的な部分を分けて検証する方針を採用しています:
- 静的な部分 (MRENCLAVEで検証): AttesterとWorkerのコンテナ
- 動的な部分 (Work-IDで検証): 実行関数、ユーザー権限、パラメータ
Work-IDの構成
=============
Work-IDは以下の情報のハッシュ値であり、サーバー側で計算されます:
.. code-block:: text
work_id = hash(function_id, user_ids, params, nonce)
- function_id: 実行関数のハッシュ値
- user_ids: 入出力データへのアクセスが許可されたユーザーID一覧
- params: 実行パラメータ(encrypted-files.yamlの内容など)
- nonce: リプレイ攻撃防止用(クリーンルームデプロイ時に生成)
.. note::
work_idはクリーンルームデプロイ時にサーバー側で計算され、クライアントに返されます。
クライアントはこのwork_idを使ってQuote検証を行います。
Remote Attestationのフロー
***************************
.. mermaid::
sequenceDiagram
participant Client as クライアント
(APC CLI)
participant Controller as Controller
participant Attester as Attester
(TEE内)
participant Worker as Worker
(TEE内)
Note over Client,Worker: Workerは既にデプロイ済み
rect rgb(230, 240, 255)
Note over Client,Attester: 1. Worker署名用公開鍵の取得
Client->>Controller: Worker公開鍵の取得を要求
Controller->>Attester: Worker公開鍵を要求
Note right of Attester: AttesterはLAで
Workerを検証済み
Attester->>Worker: Worker公開鍵を取得
Worker-->>Attester: Worker公開鍵
Attester-->>Controller: Worker公開鍵
Controller-->>Client: Worker公開鍵を転送
end
rect rgb(240, 248, 255)
Note over Client,Attester: 2. Quote生成と検証
Client->>Controller: Quote生成を要求
(work_idとnonceを含む)
Controller->>Attester: Quote生成要求
Note right of Attester: QuoteにWorker公開鍵、
work_id、nonceをバインド
Attester->>Attester: SGX Quote生成
Attester-->>Controller: Quote
Controller-->>Client: Quoteを転送
Client->>Client: MAA経由でQuote検証
Client->>Client: MRENCLAVE/MRSIGNER検証
Client->>Client: Quote内のwork_idが
期待値と一致するか確認
end
検証内容の詳細
**************
MRENCLAVE検証
=============
Attesterの初期状態のハッシュ値です。
- ユーザーが事前に計算した期待値と比較
- 一致すれば、Attesterのコードが改ざんされていない
- 静的な値 (実行関数の内容は含まれない)
MRSIGNER検証
============
Attesterの署名者です。
- 期待する署名者(Acompany等)かを確認
Work-ID検証
===========
実行内容の整合性を検証します。
検証手順
========
1. work_idを取得: クリーンルームデプロイ時にサーバーから返される work_id を使用
2. Quote取得: サーバーにwork_idを送信してQuoteを取得(Quote内にwork_idが含まれる)
3. Quote検証: MAA経由でQuoteの署名を検証
4. work_id確認: Quote内のwork_idが送信したものと一致するか確認
なぜWork-IDが必要か
- パラメータの改ざん: function-idが同じでも、パラメータが変更される可能性
- リプレイ攻撃: 過去の正当な要求を再送信される可能性
- ユーザーなりすまし: 別のユーザーが実行を要求する可能性
Work-IDは、これら全ての情報を1つのハッシュ値にまとめます。
function-id検証
===============
実行される関数が意図したものか検証します。
- function-id: 関数のハッシュ値
- デプロイ時に指定: ``apc cleanroom deploy --source <関数ディレクトリ>``
- Worker内で検証: 実行前にfunction-idと実際の関数を照合
ユーザー認証検証
================
認証の必要性
------------
複数のユーザーがデータを共有する際、誰がどのデータにアクセスできるかを制御する必要があります。
例えば、ユーザーAの入力データにはユーザーAのみがアクセスでき、ユーザーBがなりすましてアクセスすることを防ぐ必要があります。
アクセス権限の定義
------------------
ユーザーは ``encrypted-files.yaml`` でアクセス可能なユーザーを定義します:
.. code-block:: yaml
# encrypted-files.yaml
inputs:
input_1: &user_a_id a4QGvPmFlDiVqf1_APi1KN5RWSOehhFIRAmkd64JaCY=
input_2: &user_b_id 7WKyA8NxynAw2_v5ZIZnob4wD65mKoY7y7ifY4LL6VQ=
outputs:
output_1: *user_a_id
output_2: *user_b_id
``input_1``、``input_2`` などのキーに対して、user_id(署名用公開鍵のハッシュ値)を指定します。
この定義は work_id に含まれるため、ユーザーはRemote Attestation時に検証できます。
user_idの仕組み
---------------
user_idは署名用公開鍵のハッシュ値です:
.. code-block:: text
user_id = hash(signing_public_key)
なりすまし防止
--------------
他のユーザーがなりすましを試みても、以下の理由で失敗します:
* user_idは公開鍵のハッシュ値なので、誰でも知ることができます
* しかし、その公開鍵に対応する秘密鍵を持っていなければ署名を作成できません
* 公開鍵のハッシュ値がuser_idと一致するような秘密鍵を作ることは暗号学の観点から現実的に非常に困難です
検証の流れ
----------
Workerは実行前に以下を確認します:
1. クライアントから送られた署名を、登録された公開鍵で検証
2. 公開鍵からuser_idを計算
3. user_idが ``encrypted-files.yaml`` で指定されたuser_idと一致するか確認
これにより、正しい秘密鍵を持つユーザーのみがデータにアクセスできます。
コンテナの再現性とMR values
****************************
AttesterとWorkerはコンテナとして実行されます。
MR valuesの特性
===============
- コンテナイメージで一意に決まる
- 実行するマシン(VM)には依存しない
利点
====
- 一度MR valuesを検証すれば、どのマシンでも有効
- サービス提供者がVMを作り直しても再検証不要
- ユーザーはコンテナの内容のみを信頼すればよい
これにより、インフラの変更に対してユーザーの検証作業が不要になります。
Local Attestation(内部処理)
******************************
AttesterとWorker間でLocal Attestation (LA) が行われます:
1. Workerが起動時に公開鍵を生成
2. WorkerがLAでAttesterに公開鍵を登録
3. AttesterがWorkerのMRENCLAVEを検証
4. 検証済みのWorkerの公開鍵をAttesterが保持
ユーザーはこのプロセスを意識する必要はありません。
AttesterがRA済み = Workerも検証済みです。
次のフェーズ
************
TEE環境と実行内容が検証されました。
次は :doc:`key-exchange` で安全な通信路を確立します。