# 機能設計書 92-sysrand（暗号学的乱数）

## 概要

本ドキュメントは、Nim標準ライブラリの`sysrand`モジュールの機能設計を記述する。このモジュールは、オペレーティングシステムが提供するセキュアなソースから暗号学的に安全な乱数を生成する機能を提供する。

### 本機能の処理概要

sysrandモジュールは、各プラットフォームのOSが提供する暗号学的乱数生成機能をラップし、統一的なAPIでアクセスできるようにする。Windows、Linux、macOS、iOS、FreeBSD、OpenBSD、Webブラウザ、Node.jsなど多様なプラットフォームに対応している。

**業務上の目的・背景**：セキュリティが要求されるアプリケーション（認証トークン生成、暗号化キー生成、セッションID生成など）では、予測不可能な乱数が必要である。標準のrandomモジュールは擬似乱数であり暗号用途には不適切なため、OSカーネルレベルのエントロピーソースから取得する暗号学的乱数生成機能が必要となる。

**機能の利用シーン**：
- 暗号化キーの生成
- セッションIDやトークンの生成
- 暗号学的に安全なソルトの生成
- セキュアなランダムパスワードの生成
- 暗号プロトコルにおけるナンス（nonce）の生成

**主要な処理内容**：
1. `urandom(dest: var openArray[byte]): bool`: 指定バッファに乱数を充填
2. `urandom(size: Natural): seq[byte]`: 指定サイズの乱数シーケンスを生成
3. プラットフォーム別の実装分岐（Windows: BCryptGenRandom、Linux: getrandom、macOS: SecRandomCopyBytes等）

**関連システム・外部連携**：
- Windows: BCrypt.dll（BCryptGenRandom API）
- Linux: getrandomシステムコール
- macOS/iOS: Security.framework（SecRandomCopyBytes）
- OpenBSD: getentropy
- FreeBSD: getrandom
- その他POSIX: /dev/urandom
- ブラウザ: Web Crypto API（getRandomValues）
- Node.js: crypto.randomFillSync

**権限による制御**：特になし（OSのセキュリティポリシーに依存）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面関連なし（ライブラリモジュール） |

## 機能種別

計算処理 / セキュリティライブラリ / システムAPI連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| dest | var openArray[byte] | Yes | 乱数を格納するバッファ（urandom proc版） | なし（空でも可） |
| size | Natural | Yes | 生成する乱数のバイト数（urandom func版） | 0以上 |

### 入力データソース

- オペレーティングシステムのエントロピープール
- カーネルレベルの乱数生成器

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result (proc版) | bool | 成功時true、失敗時false |
| result (func版) | seq[byte] | 生成された乱数バイト列。失敗時はOSErrorを発生 |

### 出力先

- 呼び出し元への戻り値
- 引数として渡されたバッファ（proc版）

## 処理フロー

### 処理シーケンス

```
1. urandom呼び出し
   └─ サイズが0の場合は即座に成功を返す

2. プラットフォーム判定
   ├─ Windows: BCryptGenRandom呼び出し
   ├─ Linux (getrandom有効): SYS_getrandom syscall
   ├─ macOS/iOS: SecRandomCopyBytes呼び出し
   ├─ OpenBSD: getentropy呼び出し（256バイト単位）
   ├─ FreeBSD: getrandom呼び出し（256バイト単位）
   ├─ Zephyr: sys_csrand_get呼び出し
   ├─ その他POSIX: /dev/urandom読み取り
   ├─ Node.js: crypto.randomFillSync呼び出し
   └─ ブラウザ: window.crypto.getRandomValues呼び出し

3. 結果判定
   ├─ 成功: バッファに乱数が格納され、true/seq[byte]を返す
   └─ 失敗: false返却またはOSError例外発生
```

### フローチャート

```mermaid
flowchart TD
    A[urandom 呼び出し] --> B{size == 0?}
    B -->|Yes| C[即座に成功を返す]
    B -->|No| D{プラットフォーム判定}

    D -->|Windows| E[BCryptGenRandom]
    D -->|Linux| F[getrandom syscall]
    D -->|macOS/iOS| G[SecRandomCopyBytes]
    D -->|OpenBSD| H[getentropy 256バイト単位]
    D -->|FreeBSD| I[getrandom 256バイト単位]
    D -->|Node.js| J[randomFillSync]
    D -->|Browser| K[getRandomValues 256バイト単位]
    D -->|Other POSIX| L[/dev/urandom読み取り]

    E --> M{結果判定}
    F --> M
    G --> M
    H --> M
    I --> M
    J --> M
    K --> M
    L --> M

    M -->|成功| N[true / seq返却]
    M -->|失敗| O[false / OSError]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 空バッファの扱い | サイズ0の要求は即座に成功を返す | dest.len == 0 または size == 0 |
| BR-02 | バッチ処理 | OpenBSD/FreeBSD/ブラウザでは256バイト単位で処理 | 対象プラットフォーム |
| BR-03 | エラーハンドリング | proc版はfalse返却、func版はOSError例外発生 | OS APIエラー時 |
| BR-04 | ブロッキング | Linuxではエントロピープール初期化まで待機 | getrandom使用時 |

### 計算ロジック

特になし（OS APIへの委譲のため）

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

該当なし（本モジュールはデータベース操作を行わない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| OSError | 例外 | OS APIが失敗した場合（func版） | エラーメッセージを確認し、システム状態を確認 |
| false | 戻り値 | OS APIが失敗した場合（proc版） | 再試行またはフォールバック処理 |
| STATUS_SUCCESS以外 | Windows固有 | BCryptGenRandomが失敗 | Windowsイベントログを確認 |
| 負の戻り値 | POSIX固有 | システムコールエラー | errnoを確認 |

### リトライ仕様

- Linuxのgetrandom: EINTR/EAGAINの場合は内部で自動リトライ
- その他: 呼び出し元でのリトライは推奨されない（根本的なシステム問題の可能性）

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

該当なし（データベース操作を行わない）

## パフォーマンス要件

- レスポンス時間: OSのエントロピープール状態に依存
- Linux: エントロピープール未初期化時はブロッキングの可能性あり
- 大量のバイト要求時: チャンク処理により若干のオーバーヘッドが発生

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

- 本モジュールは暗号学的用途を想定しているが、セキュリティ専門家による監査は未実施
- OS実装の品質に依存するため、本番システムでは外部監査を推奨
- エントロピー枯渇時の挙動はOS依存
- 仮想環境やコンテナ環境ではエントロピー品質が低下する可能性がある

## 備考

- Nim 1.6で追加されたモジュール
- `-d:nimNoGetRandom`でLinuxのgetrandomを無効化し、/dev/urandomを使用可能
- ブラウザ環境ではgetRandomValuesの制限（65536バイト/呼び出し）により内部で分割処理

---

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

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

### 推奨読解順序

#### Step 1: モジュールの概要を理解する

まず、モジュールのドキュメントコメントで全体像を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sysrand.nim | `lib/std/sysrand.nim` | 10-45行目: 対応プラットフォームの一覧表とリンク |

**読解のコツ**: ドキュメントコメント内のテーブルで各プラットフォームの実装APIが確認できる。

#### Step 2: 公開APIを理解する

外部から呼び出される2つのurandom関数を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sysrand.nim | `lib/std/sysrand.nim` | 296-315行目: `urandom(dest: var openArray[byte]): bool`の実装 |
| 2-2 | sysrand.nim | `lib/std/sysrand.nim` | 317-327行目: `urandom(size: Natural): seq[byte]`の実装 |

**主要処理フロー**:
- **296-315行目**: proc版は内部実装を呼び出し、Windowsでは戻り値をSTATUS_SUCCESSと比較
- **317-327行目**: func版はproc版を呼び出し、失敗時にraiseOSErrorを発生

#### Step 3: プラットフォーム別実装を理解する

各プラットフォームのOS API呼び出し実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sysrand.nim | `lib/std/sysrand.nim` | 139-168行目: Windows（BCryptGenRandom）実装 |
| 3-2 | sysrand.nim | `lib/std/sysrand.nim` | 170-202行目: Linux（getrandom syscall）実装 |
| 3-3 | sysrand.nim | `lib/std/sysrand.nim` | 235-256行目: macOS/iOS（SecRandomCopyBytes）実装 |
| 3-4 | sysrand.nim | `lib/std/sysrand.nim` | 204-211行目: OpenBSD（getentropy）実装 |
| 3-5 | sysrand.nim | `lib/std/sysrand.nim` | 223-233行目: FreeBSD（getrandom）実装 |
| 3-6 | sysrand.nim | `lib/std/sysrand.nim` | 90-137行目: JavaScript（Node.js/ブラウザ）実装 |
| 3-7 | sysrand.nim | `lib/std/sysrand.nim` | 258-287行目: その他POSIX（/dev/urandom）実装 |

**読解のコツ**:
- `when defined()`による条件コンパイルでプラットフォーム分岐している
- `template urandomImpl`でプラットフォーム固有の実装を定義している

#### Step 4: バッチ処理の仕組みを理解する

256バイト制限のあるプラットフォームでのチャンク処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | sysrand.nim | `lib/std/sysrand.nim` | 68-70行目: batchImplOSとbatchSizeの定義 |
| 4-2 | sysrand.nim | `lib/std/sysrand.nim` | 72-88行目: batchImplテンプレートの実装 |

**主要処理フロー**:
- **72-88行目**: 大きなバッファを256バイトのチャンクに分割して処理

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

```
urandom(size: Natural): seq[byte]
    │
    └─ urandom(dest: var openArray[byte]): bool
           │
           └─ urandomInternalImpl(dest)
                  │
                  ├─ [Windows] urandomImpl → BCryptGenRandom
                  │
                  ├─ [Linux] urandomImpl → syscall(SYS_getrandom)
                  │      └─ EINTRでループ継続
                  │
                  ├─ [macOS/iOS] urandomImpl → SecRandomCopyBytes
                  │
                  ├─ [OpenBSD] batchImpl → getentropy (256バイト単位)
                  │
                  ├─ [FreeBSD] batchImpl → getrandom (256バイト単位)
                  │
                  ├─ [Node.js] urandomImpl → randomFillSync
                  │
                  ├─ [Browser] urandomImpl → getRandomValues (256バイト単位)
                  │
                  └─ [Other POSIX] urandomImpl → /dev/urandom read
```

### データフロー図

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

size: Natural ──────────▶ newSeq[byte](size) ───────────────▶
                              │
                              ▼
                         urandom(result)
                              │
                              ▼
                         urandomInternalImpl
                              │
                    ┌─────────┴─────────┐
                    ▼                   ▼
              [Windows]           [Linux/POSIX]
                    │                   │
                    ▼                   ▼
           BCryptGenRandom      getrandom/urandom
                    │                   │
                    └─────────┬─────────┘
                              ▼
                         OSバッファ
                              │
                              ▼
                         dest[0..size-1] ───────────────────▶ seq[byte]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sysrand.nim | `lib/std/sysrand.nim` | ソース | 暗号学的乱数生成のメイン実装 |
| oserrors.nim | `lib/std/oserrors.nim` | 依存元 | OSエラーハンドリング |
| posix.nim | `lib/posix/posix.nim` | 依存元 | POSIXシステムコールラッパー |
| jsutils.nim | `lib/std/private/jsutils.nim` | 依存元 | JavaScript環境ユーティリティ |
| random.nim | `lib/pure/random.nim` | 関連 | 擬似乱数生成（非暗号用途） |
