# 機能設計書 45-乱数生成

## 概要

SQLiteにおける擬似乱数生成機能の設計書。ChaCha20ストリーム暗号を基盤とした暗号学的に安全な乱数生成器（CSPRNG）を提供する。

### 本機能の処理概要

SQLiteの乱数生成機能は、データベース内部で必要とされる様々な乱数を生成する基盤機能である。

**業務上の目的・背景**：SQLiteでは一時テーブルのファイル名生成、ROWID自動生成、ハッシュテーブルのシード値など、様々な場面で乱数が必要となる。予測不可能な乱数を生成することで、セキュリティ上の攻撃を防ぎ、衝突を回避する。ChaCha20アルゴリズムを採用することで、暗号学的に安全な乱数生成を実現している。

**機能の利用シーン**：
- 一時ファイル名の生成
- 自動ROWIDの生成
- 内部ハッシュテーブルのランダム化
- random() SQL関数
- アプリケーションからのsqlite3_randomness()呼び出し

**主要な処理内容**：
1. 初期化：VFSのxRandomness経由でOSエントロピーを取得
2. ChaCha20ブロック関数：64バイトの擬似乱数ブロックを生成
3. 乱数出力：要求されたバイト数を出力バッファから返却
4. 状態管理：カウンタをインクリメントして次のブロックを準備
5. テスト支援：状態の保存・復元機能

**関連システム・外部連携**：
- VFSサブシステム（xRandomness経由でOSエントロピー取得）
- ミューテックスサブシステム（SQLITE_MUTEX_STATIC_PRNG）
- SQL関数（random(), randomblob()）

**権限による制御**：特になし（内部機能のためアプリケーションレベルの権限制御は不要）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | （内部機能） | - | random()、randomblob() SQL関数として呼び出し可能 |

## 機能種別

乱数生成 / 暗号プリミティブ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| N | int | Yes | 要求する乱数バイト数 | 0以下でリセット |
| pBuf | void* | Yes | 出力バッファ | NULLでリセット |

### 入力データソース

- アプリケーションからのsqlite3_randomness()呼び出し
- SQLite内部からの呼び出し（random() SQL関数等）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 乱数バイト列 | void* | pBufに書き込まれるNバイトの乱数 |

### 出力先

- 呼び出し元の指定バッファ（pBuf）

## 処理フロー

### 処理シーケンス

```
1. sqlite3_randomness(N, pBuf)呼び出し
   ├─ sqlite3_initialize()で初期化確認
   ├─ SQLITE_MUTEX_STATIC_PRNGミューテックス取得
   ├─ N<=0またはpBuf==NULLの場合
   │   └─ PRNG状態をリセット（s[0]=0）
   └─ 通常処理
       ├─ 初回呼び出し時（s[0]==0）
       │   ├─ ChaCha20初期定数設定（"expand 32-byte k"）
       │   ├─ VFSから44バイトのエントロピー取得
       │   └─ カウンタ初期化
       ├─ 出力バッファに乱数コピー
       │   ├─ 残りバイト（wsdPrng.n）があれば使用
       │   └─ 不足分はchacha_block()で新規生成
       └─ ミューテックス解放

2. chacha_block(out, in)
   ├─ 状態ベクトルをコピー
   ├─ 20ラウンド（10ダブルラウンド）のQuarterRound
   │   ├─ 列ラウンド：(0,4,8,12), (1,5,9,13), (2,6,10,14), (3,7,11,15)
   │   └─ 対角ラウンド：(0,5,10,15), (1,6,11,12), (2,7,8,13), (3,4,9,14)
   └─ 入力状態を加算して出力
```

### フローチャート

```mermaid
flowchart TD
    A[sqlite3_randomness] --> B{N<=0 または pBuf==NULL?}
    B -->|Yes| C[PRNGリセット]
    C --> D[終了]
    B -->|No| E{初期化済み?}
    E -->|No| F[ChaCha20初期化]
    F --> G[OSエントロピー取得]
    G --> H[カウンタ初期化]
    E -->|Yes| I[出力ループ]
    H --> I
    I --> J{残りバイト十分?}
    J -->|Yes| K[バッファにコピー]
    K --> L[残りバイト更新]
    J -->|No| M[残りをコピー]
    M --> N[chacha_block実行]
    N --> O[残りバイト=64]
    O --> I
    L --> D
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-45-01 | 遅延初期化 | 初回呼び出し時にエントロピー取得と初期化 | s[0]==0時 |
| BR-45-02 | スレッドセーフ | SQLITE_MUTEX_STATIC_PRNGで保護 | SQLITE_THREADSAFE有効時 |
| BR-45-03 | リセット機能 | N<=0またはpBuf==NULLでリセット | 明示的リセット要求時 |
| BR-45-04 | 64バイト単位生成 | ChaCha20は64バイトブロック単位で生成 | 常時 |

### ChaCha20アルゴリズム

| 要素 | オフセット | サイズ | 説明 |
|------|-----------|--------|------|
| 定数 | s[0-3] | 16バイト | "expand 32-byte k" |
| 鍵 | s[4-11] | 32バイト | OSエントロピーから |
| カウンタ | s[12] | 4バイト | ブロック毎にインクリメント |
| ノンス | s[13-15] | 12バイト | OSエントロピーから |

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

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

本機能はデータベーステーブルを直接操作しない（乱数生成機能のため）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 初期化失敗 | VFSが見つからない | 状態を0で埋める（NEVER条件） |

### リトライ仕様

乱数生成はリトライ不要（同期処理）

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

乱数生成はトランザクションの対象外（メモリ内処理のため）

## パフォーマンス要件

- 64バイト単位でバッファリングし、小規模要求を効率化
- ChaCha20は高速なストリーム暗号

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

- ChaCha20による暗号学的に安全な乱数生成
- OSエントロピー（xRandomness）をシードとして使用
- 状態はグローバルで共有（全スレッド同一ストリーム）

## 備考

- SQLITE_UNTESTABLEでテスト用状態保存・復元を無効化可能
- sqlite3_test_control()経由でPRNG状態を操作可能

---

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

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

### 推奨読解順序

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

PRNGの状態構造体を理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | random.c | `src/random.c` | struct sqlite3PrngType（24-28行目）：PRNG状態 |

**読解のコツ**: s[16]が512ビットのChaCha20状態、out[64]が出力バッファ、nが残りバイト数。

#### Step 2: ChaCha20ブロック関数を理解する

ChaCha20の核となるブロック関数。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | random.c | `src/random.c` | QRマクロ（34-38行目）：QuarterRound操作 |
| 2-2 | random.c | `src/random.c` | chacha_block（39-54行目）：ブロック関数 |

**主要処理フロー**:
- **33行目**: ROTL - 左ローテート
- **34-38行目**: QR - 4ワードに対するQuarterRound
- **43-51行目**: 20ラウンド（10ダブルラウンド）
- **53行目**: 入力状態を加算

#### Step 3: メイン関数を理解する

乱数取得のエントリポイント。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | random.c | `src/random.c` | sqlite3_randomness（59-130行目）：メイン関数 |

**主要処理フロー**:
- **84行目**: SQLITE_MUTEX_STATIC_PRNGでミューテックス取得
- **88-91行目**: N<=0またはpBuf==0でリセット
- **97-111行目**: 初期化処理（初回のみ）
- **114-128行目**: 出力ループ

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

```
sqlite3_randomness(N, pBuf)
    │
    ├─ sqlite3_mutex_enter(SQLITE_MUTEX_STATIC_PRNG)
    │
    ├─ [初期化（初回のみ）]
    │      ├─ ChaCha20定数設定
    │      └─ sqlite3OsRandomness(pVfs, 44, &s[4])
    │
    ├─ [出力ループ]
    │      ├─ 残りバイトをコピー
    │      └─ chacha_block()
    │             └─ QR() x 80回
    │
    └─ sqlite3_mutex_leave()
```

### データフロー図

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

要求バイト数N ────▶ sqlite3_randomness() ────────────▶ 乱数バイト列
                         │
                         ▼
                  ┌─────────────────┐
                  │ sqlite3PrngType │
                  │ ・s[16] 状態    │
                  │ ・out[64]バッファ│
                  │ ・n 残りバイト  │
                  └─────────────────┘
                         │
                         ▼
                  ┌─────────────────┐
                  │ chacha_block()  │
                  │ ChaCha20演算    │
                  └─────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| random.c | `src/random.c` | ソース | PRNG実装（ChaCha20ベース） |
| sqliteInt.h | `src/sqliteInt.h` | ヘッダ | 関連定数・マクロ |
| os.c | `src/os.c` | ソース | sqlite3OsRandomness（VFS経由エントロピー取得） |
