Image ID
zkVM ゲストバイナリの暗号的識別子(Image ID)の管理と検証を解説します。
Image ID はゲストプログラムの ELF バイナリから決定的に導出される 256 ビットのハッシュ値です。レシート検証時に期待値との一致を確認することで、正しいプログラムの実行結果であることを保証します。
概要
RISC Zero zkVM では、ゲストプログラムの ELF バイナリが Image ID と呼ばれる 256 ビットの識別子に変換されます。この変換は決定的であり、同一のバイナリからは常に同一の Image ID が生成されます。
Image ID はレシートのメタデータに記録されるため、検証者は「このレシートがどのゲストプログラムの実行結果であるか」を暗号学的に確認できます。期待する Image ID と一致しないレシートは拒否されます。
flowchart LR ELF["ゲスト ELF バイナリ"] --> HASH["RISC Zero<br/>Image ID 導出"] HASH --> IID["Image ID<br/>(256 ビット)"] IID --> EMBED["ホストバイナリに埋め込み"] IID --> MAP["マッピングファイルに記録"] IID --> VS["検証サービスの期待値"]
Image ID の導出
Image ID は RISC Zero のビルドシステムによってコンパイル時に自動生成されます。
決定論的導出
同一のゲストソースコードであっても、以下の要因により異なる Image ID が生成され得ます:
| 要因 | 影響 |
|---|---|
| ゲストコードの変更 | ロジックの変更は異なるバイナリを生成 |
| コンパイラバージョン | Rust ツールチェインのバージョン差異 |
| ターゲットアーキテクチャ | 同一コードでも x86_64 と ARM64 で異なる Image ID |
| RISC Zero SDK バージョン | SDK の変更がゲストバイナリの構造に影響 |
アーキテクチャによる差異
本システムでは、同一バージョンのゲストに対して ARM64 用 (expectedImageID) と x86_64 用 (expectedImageID_x86_64) の 2 つの Image ID をマッピング上で管理できます。
| アーキテクチャ | 用途 |
|---|---|
| ARM64 | ECS Fargate (Graviton) での本番証明生成 |
| x86_64 | ローカル開発、CI/CD 環境での証明生成 |
ただし、実行時の自動解決は「WSL 環境なら expectedImageID_x86_64 を優先する」というルールです。WSL 以外では expectedImageID が選ばれます。WSL 以外の x86_64 環境で x86_64 用 Image ID を使う場合は、EXPECTED_IMAGE_ID で明示オーバーライドします。
Image ID マッピング
期待される Image ID は、バージョンごとにマッピングファイルで管理されます。
マッピングの構造
マッピングファイルには、各バージョンの Image ID、説明、機能リストが記録されます。
| フィールド | 説明 |
|---|---|
| methodVersion | ゲストプログラムのバージョン番号 |
| expectedImageID | ARM64 環境での Image ID |
| expectedImageID_x86_64 | x86_64 環境での Image ID |
| description | バージョンの説明 |
| features | このバージョンで実装された機能リスト |
| current | 現在有効なバージョン番号 |
| deprecated | 非推奨バージョンの一覧 |
バージョン履歴の管理
マッピングファイルはバージョンの履歴を保持します。current フィールドが現在有効なバージョンを指し、deprecated フィールドが過去のバージョンを列挙します。
flowchart LR
subgraph マッピングファイル
V8["v8<br/>(deprecated)"]
V9["v9<br/>(deprecated)"]
V10["v10<br/>(current)"]
end
V10 --> ARM["ARM64 Image ID"]
V10 --> X86["x86_64 Image ID"]
Image ID の解決
検証時に使用する期待 Image ID は、以下の優先順位で解決されます。
flowchart TD
START[Image ID 解決] --> P1{環境変数<br/>EXPECTED_IMAGE_ID<br/>が設定されている?}
P1 -->|Yes| USE1[環境変数の値を使用]
P1 -->|No| LOAD[マッピングファイルを読み込み]
LOAD --> P2{読み込み成功?}
P2 -->|No| ERR[既定値へフォールバック]
P2 -->|Yes| P3{WSL 実行環境かつ<br/>expectedImageID_x86_64 が存在?}
P3 -->|Yes| X86[expectedImageID_x86_64 を使用]
P3 -->|No| ARM[expectedImageID を使用]
- 環境変数:
EXPECTED_IMAGE_IDが設定されている場合、その値を使用 - マッピングファイル:
currentバージョンの Image ID を取得し、WSL 実行環境かつexpectedImageID_x86_64が存在する場合のみその値を使用(それ以外はexpectedImageID) - フォールバック: マッピングの読み込みに失敗した場合は、実装内の既定値にフォールバック
環境変数によるオーバーライドは、デプロイパイプラインでの柔軟な制御や、テスト時の特定バージョン指定に使用されます。
検証パイプラインにおける役割
Image ID は 4 段階検証モデルの STARK 検証段階で使用されます。
stark_image_id_match チェック
このチェックは、レシートに記録された Image ID と期待値を照合します。
flowchart TD
RID["レシートの Image ID"] --> CMP{一致?}
EID["期待 Image ID<br/>(マッピングから取得)"] --> CMP
CMP -->|一致| NEXT["stark_receipt_verify へ進む"]
CMP -->|不一致| FAIL["検証失敗"]
Image ID が不一致の場合、以下のいずれかの状況を意味します:
| 原因 | 対処 |
|---|---|
| マッピングが古い | ゲストの再ビルド後にマッピングを更新する |
| 異なるゲストで証明が生成された | レシートの出所を調査する |
| アーキテクチャの不一致 | 正しいアーキテクチャの Image ID で照合する |
Image ID の更新手順
ゲストプログラムを変更した場合、Image ID を更新する必要があります。
- ゲストコードを変更する
- zkVM ゲストをビルドし、新しい Image ID を取得する
imageId-mapping.jsonを更新する(必要に応じてexpectedImageID_x86_64も更新)- プローバーイメージとマッピングを同時にデプロイする
更新の同期要件
Image ID の更新は、プローバーイメージのデプロイとマッピングファイルの更新を同時に行う必要があります。
| 不整合の状態 | 結果 |
|---|---|
| 新プローバー + 旧マッピング | 検証時に Image ID 不一致で失敗 |
| 旧プローバー + 新マッピング | 検証時に Image ID 不一致で失敗 |
| 新プローバー + 新マッピング | 正常動作 |
非同期プローバーの場合、デプロイのローリングアップデート中に旧イメージのタスクが残存する可能性があるため、一時的に旧バージョンの Image ID も受け入れる遷移期間が必要になる場合があります。
セキュリティ上の位置づけ
Image ID は、zkVM の信頼モデルにおける重要な信頼アンカーです。
- Image ID を知っている検証者は、ゲストプログラムのロジックを信頼できる: レシートが有効であれば、そのロジックが正しく実行されたことが保証される
- Image ID の管理が破綻すると、検証の信頼性が失われる: 攻撃者が独自のゲストプログラムで有効なレシートを生成し、その Image ID がマッピングに混入すると、不正な集計が「検証済み」として受理される
マッピングファイルは公開リポジトリにコミットされ、変更履歴が追跡可能です。本番環境では、イメージ署名検証と組み合わせることで、承認されたプローバーイメージのみが使用されることを保証します。イメージ署名の詳細は イメージ署名 を参照してください。