# 機能設計書 82-ハッシュ生成

## 概要

本ドキュメントは、webpackにおけるハッシュ生成機能の設計を記述する。`createHash`ファクトリ関数と`Hash`抽象基底クラスを中心に、MD4、xxhash64、Node.js暗号モジュールによる各種ハッシュアルゴリズムを抽象化し、モジュールID・チャンクID・コンテンツハッシュ等のビルド成果物識別子の生成を統一的に行う仕組みを提供する。

### 本機能の処理概要

ハッシュ生成機能は、webpackのビルドプロセス全体で使用されるハッシュ計算を抽象化するユーティリティである。

**業務上の目的・背景**：webpackはモジュールID、チャンクID、コンテンツハッシュ、フルハッシュなど、多くの箇所でハッシュ値を利用する。長期キャッシュの安定化、ファイル名の一意性保証、変更検出などに不可欠な機能である。異なるハッシュアルゴリズムを統一的なインターフェースで提供することで、設定によるアルゴリズム切り替えを可能にし、パフォーマンスとセキュリティのバランスを利用者が選択できるようにしている。

**機能の利用シーン**：
- webpack設定の`output.hashFunction`でハッシュアルゴリズムを指定する場面
- モジュールやチャンクのコンテンツに基づくハッシュ値の生成
- キャッシュキーの生成
- 決定的ID生成プラグインでのハッシュ計算

**主要な処理内容**：
1. `createHash`ファクトリ関数がアルゴリズム名またはコンストラクタを受け取り、適切なHashインスタンスを生成する
2. xxhash64アルゴリズム: WebAssembly実装による高速非暗号学的ハッシュ。BatchedHashでラップされる
3. md4アルゴリズム: WebAssembly実装のMD4ハッシュ。BatchedHashでラップされる
4. native-md4: Node.jsのcryptoモジュールを使用したMD4。BulkUpdateHashでラップされる
5. debugアルゴリズム: デバッグ用にハッシュの入力データとスタックトレースを記録するDebugHash
6. その他: Node.jsのcryptoモジュールの任意のアルゴリズム（sha256等）をBulkUpdateHashでラップ
7. BatchedHash: 短い文字列の更新をバッチ処理し、WASM呼び出し回数を削減する最適化ラッパー
8. BulkUpdateHash: 短いデータの更新をバッファリングし、ダイジェストキャッシュ機能を持つ最適化ラッパー

**関連システム・外部連携**：Node.jsのcryptoモジュール、WebAssemblyランタイム

**権限による制御**：特になし。ハッシュアルゴリズムの選択はwebpack設定で行う。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能に関連する画面はなし |

## 機能種別

計算処理（ハッシュ値の生成・管理）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| algorithm | string \| function | Yes | ハッシュアルゴリズム名またはHashコンストラクタ | "xxhash64", "md4", "native-md4", "debug", その他Node.js crypto対応アルゴリズム名、またはHash互換コンストラクタ |
| data | string \| Buffer | Yes | ハッシュ対象データ（update時） | 空文字列も許容 |
| inputEncoding | string | No | 入力データのエンコーディング（update時） | BufferEncoding互換の文字列 |
| encoding | string | No | ダイジェスト出力のエンコーディング | "hex", "base64", "latin1"等 |

### 入力データソース

- webpack設定の`output.hashFunction`オプション（デフォルト: "md4"）
- モジュールコンテンツ、チャンクコンテンツ、ファイルコンテンツなどの各種バイナリ/テキストデータ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Hash | Hash | ハッシュインスタンス（update/digestメソッドを持つ） |
| digest結果 | string \| Buffer | ハッシュダイジェスト値。encodingが指定されれば文字列、なければBuffer |

### 出力先

呼び出し元に返却。モジュールID、チャンクハッシュ、コンテンツハッシュなどの生成に使用される。

## 処理フロー

### 処理シーケンス

```
1. createHash(algorithm)呼び出し
   ├─ algorithmがfunction → BulkUpdateHashで新しいインスタンスをラップして返却
   ├─ algorithm === "debug" → DebugHashインスタンスを返却
   ├─ algorithm === "xxhash64" → xxhash64 WASMインスタンスをBatchedHashでラップして返却
   ├─ algorithm === "md4" → md4 WASMインスタンスをBatchedHashでラップして返却
   ├─ algorithm === "native-md4" → crypto.createHash("md4")をBulkUpdateHashでラップして返却
   └─ default → crypto.createHash(algorithm)をBulkUpdateHashでラップして返却
2. hash.update(data, encoding)
   └─ ラッパーがバッファリング最適化を行い、内部ハッシュに転送
3. hash.digest(encoding)
   └─ バッファ残データをフラッシュし、最終ハッシュ値を計算して返却
```

### フローチャート

```mermaid
flowchart TD
    A[createHash 呼び出し] --> B{algorithm の型}
    B -->|function| C[BulkUpdateHash ラップ]
    B -->|string| D{algorithm 値}
    D -->|debug| E[DebugHash 生成]
    D -->|xxhash64| F[xxhash64 WASM + BatchedHash]
    D -->|md4| G[md4 WASM + BatchedHash]
    D -->|native-md4| H[crypto.createHash md4 + BulkUpdateHash]
    D -->|default| I[crypto.createHash + BulkUpdateHash]
    C --> J[Hash インスタンス返却]
    E --> J
    F --> J
    G --> J
    H --> J
    I --> J
    J --> K[update data]
    K --> L[digest encoding]
    L --> M[ハッシュ値出力]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-82-1 | 遅延ロード | 各アルゴリズム実装は初回使用時に遅延require()される | createHash呼び出し時 |
| BR-82-2 | WASM優先 | md4/xxhash64はデフォルトでWASM実装が使用される | algorithm名指定時 |
| BR-82-3 | BatchedHashバッチ処理 | MAX_SHORT_STRING未満の文字列更新はバッチ結合される | BatchedHash.update時 |
| BR-82-4 | BulkUpdateHashバッファリング | BULK_SIZE(3)以下の短い文字列はバッファに蓄積される | BulkUpdateHash.update時 |
| BR-82-5 | ダイジェストキャッシュ | BulkUpdateHashは短いデータのダイジェスト結果をキャッシュする | hash未初期化状態でdigest呼び出し時 |
| BR-82-6 | Hashインターフェース統一 | すべてのハッシュ実装はHash基底クラスのupdate/digestインターフェースに従う | 全アルゴリズム共通 |

### 計算ロジック

- **xxhash64**: 64ビット非暗号学的ハッシュ。WebAssemblyモジュールで実装。16バイトのメモリを使用。
- **md4**: 128ビット暗号学的ハッシュ。WebAssemblyモジュールで実装。32バイトのメモリを使用。
- **BatchedHash最適化**: 短い文字列（MAX_SHORT_STRING未満）はJavaScript側で結合してからWASMに一度に渡す。base64エンコーディングの入力はバッチ対象外。
- **BulkUpdateHash最適化**: BULK_SIZE(3文字)以下の文字列をバッファに蓄積し、閾値を超えるかdigest時に一括でハッシュに渡す。短いデータについてはハッシュキー+エンコーディングをキーとしたMapキャッシュを使用。

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

本機能にデータベース操作は含まれない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | AbstractMethodError | Hash基底クラスのupdate/digestを直接呼び出した場合 | サブクラスで必ずオーバーライドする |
| - | Error | Node.jsのcryptoモジュールがサポートしないアルゴリズムを指定した場合 | サポート対象のアルゴリズムを使用する |

### リトライ仕様

リトライ処理は不要。

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

トランザクション処理は不要。

## パフォーマンス要件

- xxhash64とmd4のWASM実装は、Node.jsのcryptoモジュールによるネイティブ実装と同等以上のパフォーマンスを提供する
- BatchedHash/BulkUpdateHashによる短い文字列のバッチ処理で、高頻度のupdate呼び出しのオーバーヘッドを最小化する
- BulkUpdateHashのダイジェストキャッシュにより、同一入力に対する重複計算を回避する

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

- md4は暗号学的に脆弱とされるが、webpackでは衝突耐性が必要ないコンテンツハッシュ用途で使用している
- セキュリティが重要な用途にはsha256等の暗号学的に安全なアルゴリズムを指定できる

## 備考

- webpackのデフォルトハッシュ関数はmd4であるが、xxhash64がパフォーマンス面で推奨される
- DebugHashはデバッグ専用で、ハッシュ入力データとスタックトレースを記録する特殊実装

---

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

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

### 推奨読解順序

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

Hash基底クラスが定義するインターフェースを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Hash.js | `lib/util/Hash.js` | update()とdigest()の2つの抽象メソッドがハッシュのインターフェースを定義。AbstractMethodErrorを投げるプレースホルダー |

**読解のコツ**: Hash.jsは非常にシンプルな抽象基底クラスである。Node.jsのcrypto.Hashインターフェースに準拠した`update(data, inputEncoding)`と`digest(encoding)`の2メソッドが核となる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | createHash.js | `lib/util/createHash.js` | ファクトリ関数。アルゴリズム名に応じて適切なHashサブクラスのインスタンスを生成する |

**主要処理フロー**:
1. **12-22行目**: 遅延ロード用の変数宣言（crypto、createXXHash64、createMd4、DebugHash、BatchedHash、BulkUpdateHash）
2. **29-36行目**: algorithmがfunctionの場合 → BulkUpdateHashでラップ
3. **39-43行目**: "debug" → DebugHashインスタンス
4. **44-53行目**: "xxhash64" → xxhash64 WASMモジュールをBatchedHashでラップ
5. **54-63行目**: "md4" → md4 WASMモジュールをBatchedHashでラップ
6. **64-76行目**: "native-md4" → cryptoモジュールのmd4をBulkUpdateHashでラップ
7. **77-89行目**: default → cryptoモジュールの任意アルゴリズムをBulkUpdateHashでラップ

#### Step 3: BatchedHashの最適化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | BatchedHash.js | `lib/util/hash/BatchedHash.js` | WASM実装のハッシュを効率的に呼び出すためのバッチ処理ラッパー |

**主要処理フロー**:
- **48-82行目**: update()メソッド。短い文字列はthis.stringにバッチ蓄積し、MAX_SHORT_STRING超過時またはBuffer入力時にフラッシュしてWASMに転送
- **100-112行目**: digest()メソッド。残存バッファをフラッシュしてからダイジェストを計算

#### Step 4: BulkUpdateHashの最適化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | BulkUpdateHash.js | `lib/util/hash/BulkUpdateHash.js` | cryptoベースのハッシュをバッファリングとキャッシュで最適化するラッパー |

**主要処理フロー**:
- **14行目**: BULK_SIZE = 3（バッファリング閾値）
- **19行目**: digestCachesオブジェクト（アルゴリズム+エンコーディングごとのダイジェストキャッシュ）
- **26-43行目**: コンストラクタ。hashFactoryまたは直接hashインスタンスを受け取る
- **64-93行目**: update()メソッド。短い文字列をbufferに蓄積し、BULK_SIZE超過時にフラッシュ
- **111-142行目**: digest()メソッド。hashが未初期化なら短いデータとしてキャッシュを活用

#### Step 5: WASM実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | xxhash64.js | `lib/util/hash/xxhash64.js` | xxhash64のWASMバイナリモジュール。create関数をバインドして返す |
| 5-2 | md4.js | `lib/util/hash/md4.js` | md4のWASMバイナリモジュール。create関数をバインドして返す |
| 5-3 | wasm-hash.js | `lib/util/hash/wasm-hash.js` | WASMモジュールのインスタンス化とHashインターフェースの実装 |

**読解のコツ**: xxhash64.jsとmd4.jsはWASMバイナリがBase64エンコードで埋め込まれている。`create`関数（wasm-hash.jsから提供）にWASMモジュール、初期化引数、メモリサイズ情報をバインドして公開する。

#### Step 6: DebugHashを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | DebugHash.js | `lib/util/hash/DebugHash.js` | デバッグ用ハッシュ。入力データとスタックトレースを記録する |

**主要処理フロー**:
- **38-51行目**: update()メソッド。入力データとスタックトレース（2行目）を記録文字列に追記
- **70-72行目**: digest()メソッド。記録文字列全体をhexエンコードして返す

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

```
createHash(algorithm)
    |
    +-- [algorithm === function]
    |   +-- new BulkUpdateHash(() => new algorithm())
    |
    +-- [algorithm === "debug"]
    |   +-- new DebugHash()
    |
    +-- [algorithm === "xxhash64"]
    |   +-- require("./hash/xxhash64")
    |   +-- require("./hash/BatchedHash")
    |   +-- new BatchedHash(createXXHash64())
    |       +-- wasm-hash.create(xxhash64Module)
    |
    +-- [algorithm === "md4"]
    |   +-- require("./hash/md4")
    |   +-- require("./hash/BatchedHash")
    |   +-- new BatchedHash(createMd4())
    |       +-- wasm-hash.create(md4Module)
    |
    +-- [algorithm === "native-md4" | default]
        +-- require("crypto")
        +-- require("./hash/BulkUpdateHash")
        +-- new BulkUpdateHash(() => crypto.createHash(algorithm))
```

### データフロー図

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

algorithm名/関数     -->  createHash()                      -->  Hashインスタンス
  "xxhash64"              ファクトリ分岐
  "md4"
  "native-md4"
  "debug"
  他 or function

data (string/Buffer) -->  hash.update(data, encoding)       -->  Hash (チェーン)
                          BatchedHash: バッチ蓄積
                          BulkUpdateHash: バッファリング

encoding             -->  hash.digest(encoding)             -->  ハッシュ値
                          キャッシュ参照                           (string | Buffer)
                          残データフラッシュ
                          最終計算
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| createHash.js | `lib/util/createHash.js` | ソース | ハッシュファクトリ関数。アルゴリズムに応じたHashインスタンスを生成 |
| Hash.js | `lib/util/Hash.js` | ソース | ハッシュ抽象基底クラス。update/digestインターフェース定義 |
| BatchedHash.js | `lib/util/hash/BatchedHash.js` | ソース | WASM向けバッチ処理ラッパー |
| BulkUpdateHash.js | `lib/util/hash/BulkUpdateHash.js` | ソース | cryptoベース向けバッファリング＋キャッシュラッパー |
| DebugHash.js | `lib/util/hash/DebugHash.js` | ソース | デバッグ用ハッシュ。入力データとスタックトレースを記録 |
| xxhash64.js | `lib/util/hash/xxhash64.js` | ソース | xxhash64 WASMバイナリモジュール |
| md4.js | `lib/util/hash/md4.js` | ソース | md4 WASMバイナリモジュール |
| wasm-hash.js | `lib/util/hash/wasm-hash.js` | ソース | WASMハッシュモジュールのインスタンス化と共通処理 |
| hash-digest.js | `lib/util/hash/hash-digest.js` | ソース | WASMハッシュのdigest/update共通ヘルパー |
