# 機能設計書 83-暗号化・復号化

## 概要

本ドキュメントは、OpenSearchにおけるデータの暗号化・復号化を行うCrypto機能の設計を記述する。

### 本機能の処理概要

CryptoHandlerRegistryを中心としたデータ暗号化・復号化の基盤機能である。ノード起動時にインストール済みのCryptoKeyProviderプラグインとCryptoPluginをロードし、暗号化ハンドラのレジストリを構築する。暗号化メタデータに基づいてCryptoHandlerを生成・キャッシュし、EncryptedBlobStoreで使用する暗号化・復号化操作を提供する。

**業務上の目的・背景**：リモートストアやスナップショットリポジトリに保存されるデータを暗号化することで、データの機密性を確保する。特にクラウド環境でのデータ永続化においてサーバーサイド暗号化に加えてクライアントサイド暗号化を提供する。

**機能の利用シーン**：リモートストアへのインデックスデータ書き込み時の暗号化、スナップショットリポジトリへのデータ永続化時の暗号化、暗号化されたデータの読み取り時の復号化。

**主要な処理内容**：
1. ノード起動時にCryptoKeyProviderPluginとCryptoPluginのロード・レジストリ初期化
2. CryptoMetadataに基づくCryptoHandlerの生成（遅延生成・キャッシュ）
3. 暗号化・復号化操作のEncryptedBlobStoreへの提供

**関連システム・外部連携**：CryptoKeyProviderPlugin（鍵提供プラグイン、例: crypto-kms）、CryptoPlugin（暗号化実装プラグイン）、EncryptedBlobStore。

**権限による制御**：暗号化設定はクラスタメタデータ（CryptoMetadata）として管理される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 111 | セキュア設定リロード | 補助機能 | 暗号化されたセキュア設定の復号処理 |

## 機能種別

データ連携 / セキュリティ基盤

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| cryptoPlugins | List<CryptoPlugin> | No | 暗号化実装プラグインリスト | 2つ以上の場合はIllegalStateException |
| cryptoKeyProviderPlugins | List<CryptoKeyProviderPlugin> | No | 鍵提供プラグインリスト | typeの重複不可 |
| cryptoMetadata | CryptoMetadata | Yes(Handler取得時) | 暗号化メタデータ（keyProviderType, keyProviderName, settings） | - |

### 入力データソース

- ノード起動時のプラグインロード結果
- インデックス/リポジトリの暗号化メタデータ（CryptoMetadata）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| CryptoHandler | CryptoHandler<?, ?> | 暗号化・復号化操作を実行するハンドラ |
| CryptoKeyProviderPlugin | CryptoKeyProviderPlugin | 指定タイプの鍵提供プラグイン |

### 出力先

EncryptedBlobStoreに暗号化ハンドラが提供され、データの暗号化・復号化に使用される。

## 処理フロー

### 処理シーケンス

```
1. レジストリ初期化（ノード起動時）
   └─ CryptoHandlerRegistry.initRegistry()でシングルトン生成
2. CryptoPlugin登録
   └─ 1つのCryptoPluginのみ許可（複数はIllegalStateException）
3. CryptoKeyProviderPlugin登録
   └─ type別にマップに登録（重複はIllegalArgumentException）
4. CryptoHandler取得（遅延生成）
   └─ fetchCryptoHandler(cryptoMetadata)でキャッシュ or 新規生成
5. CryptoHandler生成
   └─ KeyProviderPlugin.createKeyProvider() -> CryptoPlugin.getOrCreateCryptoHandler()
```

### フローチャート

```mermaid
flowchart TD
    A[ノード起動] --> B[CryptoHandlerRegistry.initRegistry]
    B --> C{CryptoPlugin数}
    C -->|0| D[暗号化なし]
    C -->|1| E[cryptoHandlerPlugin.set]
    C -->|2+| F[IllegalStateException]
    B --> G[loadCryptoFactories]
    G --> H[type別にマップ登録]
    I[fetchCryptoHandler要求] --> J{キャッシュにあるか}
    J -->|Yes| K[キャッシュから返却]
    J -->|No| L[createCryptoHandler]
    L --> M[getCryptoKeyProviderPlugin]
    M --> N{プラグインあるか}
    N -->|No| O[CryptoRegistryException]
    N -->|Yes| P[keyProviderPlugin.createKeyProvider]
    P --> Q[cryptoPlugin.getOrCreateCryptoHandler]
    Q --> R[キャッシュに登録]
    R --> S[CryptoHandler返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | CryptoPlugin単一制約 | CryptoPluginは1つのみ許可される | レジストリ初期化時 |
| BR-02 | KeyProvider type一意制約 | CryptoKeyProviderPluginのtypeは重複不可 | レジストリ初期化時 |
| BR-03 | CryptoHandler遅延生成 | CryptoHandlerは初回要求時に生成されキャッシュされる | fetchCryptoHandler時 |
| BR-04 | シングルトンレジストリ | CryptoHandlerRegistryはシングルトン（double-checked locking） | initRegistry時 |

### 計算ロジック

特になし。暗号化・復号化の具体的なアルゴリズムはCryptoPluginの実装に委譲される。

## データベース操作仕様

### 操作別データベース影響一覧

本機能はインデックスデータを直接操作しない。BlobStoreへの暗号化データの読み書きを間接的に行う。

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 暗号化 | BlobStore | WRITE | データを暗号化して書き込み |
| 復号化 | BlobStore | READ | 暗号化データを読み取り復号 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 500 | IllegalStateException | CryptoPluginが2つ以上 | プラグイン設定を確認し1つのみにする |
| 400 | IllegalArgumentException | KeyProvider typeが重複 | プラグインのtype設定を確認 |
| 404 | CryptoRegistryException | 指定typeのKeyProviderがない | 対応するKeyProviderプラグインをインストール |
| 500 | CryptoRegistryException | CryptoHandler生成に失敗 | プラグイン設定・認証情報を確認 |
| 500 | IllegalStateException | レジストリ未初期化でgetCryptoKeyProviderPlugin呼出 | ノード起動が完了してから操作する |

### リトライ仕様

CryptoHandler生成失敗時は例外をスローし、リトライは呼び出し元に委ねる。

## トランザクション仕様

CryptoHandlerのキャッシュ管理はsynchronizedブロックで排他制御される（double-checked locking）。

## パフォーマンス要件

CryptoHandlerはキャッシュされるため、同一CryptoMetadataに対する繰り返しの暗号化操作はハンドラ生成のオーバーヘッドがない。

## セキュリティ考慮事項

- MasterKeyProviderを通じて暗号化キーが管理される
- 暗号化キーはメモリ内でのみ保持され、永続化されない
- CryptoMetadataを通じて暗号化設定がクラスタメタデータとして管理される
- onCloseコールバックでキャッシュからハンドラが削除される

## 備考

本機能はCrypto基盤であり、具体的な暗号化実装はCryptoPlugin（例: crypto-kms）が提供する。

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | CryptoHandlerRegistry.java | `server/src/main/java/org/opensearch/crypto/CryptoHandlerRegistry.java` | registry(SetOnce<Map>), cryptoHandlerPlugin(SetOnce<CryptoPlugin>), registeredCryptoHandlers(Map)の3つのフィールド構造 |
| 1-2 | CryptoRegistryException.java | `server/src/main/java/org/opensearch/crypto/CryptoRegistryException.java` | name, type, restStatusフィールド。404/400/500のRestStatus分類 |

**読解のコツ**: SetOnceはノード起動時に一度だけ設定されるフィールド。registeredCryptoHandlersは遅延生成されるCryptoHandlerのキャッシュ。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | CryptoHandlerRegistry.java | `server/src/main/java/org/opensearch/crypto/CryptoHandlerRegistry.java` | initRegistry()（72-87行目）がシングルトン初期化のエントリーポイント |

**主要処理フロー**:
1. **50-66行目**: コンストラクタでCryptoPluginの単一制約チェック、KeyProviderPluginのロード
2. **72-87行目**: double-checked lockingでシングルトン初期化
3. **125-142行目**: fetchCryptoHandler()でキャッシュ付き遅延生成
4. **144-167行目**: createCryptoHandler()でMasterKeyProvider生成とCryptoHandler作成

### プログラム呼び出し階層図

```
Node起動
    |
    +-- CryptoHandlerRegistry.initRegistry()
            |
            +-- CryptoHandlerRegistry(cryptoPlugins, keyProviderPlugins, settings)
                    |
                    +-- cryptoHandlerPlugin.set(cryptoPlugins.get(0))
                    +-- loadCryptoFactories(keyProviderPlugins)
                            +-- Map<type, CryptoKeyProviderPlugin>

EncryptedBlobStore利用時
    |
    +-- CryptoHandlerRegistry.fetchCryptoHandler(cryptoMetadata)
            |
            +-- createCryptoHandler(cryptoMetadata, onClose)
                    |
                    +-- getCryptoKeyProviderPlugin(keyProviderType)
                    +-- keyProviderPlugin.createKeyProvider(cryptoMetadata)
                    +-- cryptoPlugin.getOrCreateCryptoHandler(masterKeyProvider, ...)
```

### データフロー図

```
[入力]                        [処理]                           [出力]

CryptoPlugin ────────────> CryptoHandlerRegistry
CryptoKeyProviderPlugin ──>   (初期化時にロード)

CryptoMetadata ──────────> fetchCryptoHandler()
                              |
                              +-- createKeyProvider() ─────> MasterKeyProvider
                              +-- getOrCreateCryptoHandler() ─> CryptoHandler ──> EncryptedBlobStore
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CryptoHandlerRegistry.java | `server/src/main/java/org/opensearch/crypto/CryptoHandlerRegistry.java` | ソース | 暗号化ハンドラレジストリ（メインクラス） |
| CryptoRegistryException.java | `server/src/main/java/org/opensearch/crypto/CryptoRegistryException.java` | ソース | 暗号化レジストリ例外 |
| package-info.java | `server/src/main/java/org/opensearch/crypto/package-info.java` | ソース | パッケージ情報 |
