# 機能設計書 9-crypto

## 概要

本ドキュメントは、Node.jsのcryptoモジュール（暗号化・ハッシュ・署名機能）の機能設計を記載する。cryptoモジュールは、暗号化、ハッシュ化、署名、鍵生成など、セキュリティに関連する暗号学的機能を提供するコアモジュールである。

### 本機能の処理概要

cryptoモジュールは、OpenSSLライブラリをラップし、様々な暗号化アルゴリズム、ハッシュ関数、デジタル署名、鍵交換プロトコルを提供する。Web Crypto APIとの互換性も提供する。

**業務上の目的・背景**：セキュアなアプリケーション開発において、パスワードのハッシュ化、データの暗号化、デジタル署名による認証は不可欠である。cryptoモジュールは、これらの暗号学的処理を標準的かつ安全な方法で実装するための基盤を提供する。

**機能の利用シーン**：
- パスワードのハッシュ化と検証（bcrypt, scrypt, pbkdf2, argon2）
- データの暗号化/復号（AES, ChaCha20等）
- デジタル署名の生成と検証（RSA, ECDSA, Ed25519）
- セキュアな乱数生成（randomBytes, randomUUID）
- 鍵ペア生成（RSA, EC, Ed25519）
- 鍵交換（Diffie-Hellman, ECDH）
- ハッシュ計算（SHA-256, SHA-512等）
- HMAC認証
- X.509証明書操作

**主要な処理内容**：
1. ハッシュ計算（createHash, hash）
2. HMAC認証（createHmac）
3. 暗号化/復号（createCipheriv, createDecipheriv）
4. 署名/検証（createSign, createVerify, sign, verify）
5. 鍵生成（generateKeyPair, generateKey）
6. 乱数生成（randomBytes, randomUUID, randomInt）
7. 鍵導出（pbkdf2, scrypt, hkdf, argon2）
8. 鍵交換（DiffieHellman, ECDH）
9. Web Crypto API（subtle, getRandomValues）

**関連システム・外部連携**：
- OpenSSLライブラリ
- tlsモジュール（TLS/SSL）
- httpsモジュール（HTTPS）
- Web Crypto API

**権限による制御**：特別な権限制御なし。FIPSモードは--force-fipsオプションで制御。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 直接関連する画面なし |

## 機能種別

暗号化 / セキュリティ / ユーティリティ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| algorithm | string | Yes | 暗号化/ハッシュアルゴリズム | getHashes/getCiphers |
| key | Buffer/KeyObject | Yes | 暗号鍵 | - |
| iv | Buffer | 条件 | 初期化ベクトル | - |
| data | Buffer/string | Yes | 処理対象データ | - |
| options | object | No | 各種オプション | - |
| size | number | 条件 | バイト数/ビット数 | validateNumber |

### 入力データソース

- アプリケーションコード：暗号化対象データ、鍵、オプション
- OpenSSL：アルゴリズム実装

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| hash | Buffer/string | ハッシュ値 |
| ciphertext | Buffer | 暗号文 |
| plaintext | Buffer | 復号されたデータ |
| signature | Buffer | デジタル署名 |
| keyPair | object | 生成された鍵ペア |
| randomBytes | Buffer | ランダムバイト列 |

### 出力先

- コールバック関数
- Promiseオブジェクト
- 同期メソッドの戻り値
- ストリーム出力（Hash, Hmac, Cipher等）

## 処理フロー

### 処理シーケンス（ハッシュ計算）

```
1. createHash(algorithm)でHashインスタンス生成
2. hash.update(data)でデータ入力
   └─ 複数回呼び出し可能
3. hash.digest(encoding)でハッシュ値取得
   └─ 'hex', 'base64', Bufferなど
```

### 処理シーケンス（暗号化）

```
1. createCipheriv(algorithm, key, iv)でCipherivインスタンス生成
2. cipher.update(data)でデータ入力
3. cipher.final()で最終ブロック取得
4. 認証付き暗号の場合
   └─ cipher.getAuthTag()で認証タグ取得
```

### 処理シーケンス（鍵生成）

```
1. generateKeyPair(type, options, callback)
   └─ 'rsa', 'ec', 'ed25519'など
2. OpenSSLで鍵ペア生成
3. callback(err, publicKey, privateKey)
```

### フローチャート

```mermaid
flowchart TD
    A[createHash] --> B[Hashインスタンス]
    B --> C[update]
    C --> D{完了?}
    D -->|No| C
    D -->|Yes| E[digest]
    E --> F[ハッシュ値]

    G[createCipheriv] --> H[Cipherivインスタンス]
    H --> I[update]
    I --> J{完了?}
    J -->|No| I
    J -->|Yes| K[final]
    K --> L[暗号文]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | FIPSモード | --force-fipsでFIPS準拠モード強制 | オプション指定時 |
| BR-002 | 非推奨コンストラクタ | Hash/Hmacコンストラクタは非推奨 | DEP0179/DEP0181 |
| BR-003 | timingSafeEqual | タイミング攻撃耐性のある比較 | 秘密値比較時 |
| BR-004 | 初期化ベクトル必須 | ivが必要なアルゴリズムあり | AES-CBC等 |
| BR-005 | 認証付き暗号 | AES-GCM等でauthTag必要 | 認証付き暗号使用時 |

### 計算ロジック

- PBKDF2: iterations回のハッシュ反復
- scrypt: N, r, pパラメータでメモリ/CPU負荷調整
- hkdf: HMAC-based Key Derivation Function

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

本モジュールはデータベースを直接操作しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ERR_CRYPTO_FIPS_FORCED | FIPS | FIPS強制時に無効化試行 | FIPSモードのまま使用 |
| ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE | 鍵エラー | 無効な鍵タイプ | 正しい鍵タイプを使用 |
| ERR_CRYPTO_INVALID_DIGEST | ハッシュエラー | 無効なダイジェストアルゴリズム | getHashes()で確認 |
| ERR_CRYPTO_INVALID_AUTH_TAG | 認証エラー | 無効な認証タグ | 正しい認証タグを使用 |
| ERR_OSSL_* | OpenSSL | OpenSSLエラー | OpenSSLドキュメント参照 |

### リトライ仕様

暗号化処理は決定論的であり、通常リトライは不要。乱数生成のエントロピー不足時はシステム状態待ち。

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

暗号化処理はステートレス。ストリーム系クラスは内部状態を持つ。

## パフォーマンス要件

- ストリーム処理による大容量データ対応
- OpenSSLのハードウェアアクセラレーション活用
- 非同期版（pbkdf2, scrypt等）でイベントループブロック回避
- secureHeapUsed()でセキュアヒープ使用量監視

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

- 弱いアルゴリズム（MD5, SHA-1）は署名に使用しない
- 十分な鍵長を使用（RSA: 2048bit以上、EC: 256bit以上）
- 適切なパスワードハッシュ（scrypt, argon2推奨）
- timingSafeEqual()でタイミング攻撃対策
- FIPSモードでの運用検討
- 秘密鍵の適切な保管

## 備考

- OpenSSLバージョンによってサポートアルゴリズムが異なる
- Web Crypto API（crypto.subtle）はW3C標準準拠
- argon2は最新のパスワードハッシュアルゴリズム
- 一部関数は非推奨（DEP0115等）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | crypto.js | `lib/crypto.js` | エクスポートされるAPIと内部モジュール構成 |

**読解のコツ**: cryptoモジュールは多数の内部モジュール（internal/crypto/*）をラップしている。各機能は専門の内部モジュールに分離されている。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | crypto.js | `lib/crypto.js` | 公開API定義（180-249行目） |

**主要処理フロー**:
1. **36行目**: assertCrypto() - crypto利用可能チェック
2. **144-146行目**: createHash()関数
3. **148-154行目**: createCipheriv(), createDecipheriv()関数
4. **168-178行目**: createHmac(), createSign(), createVerify()関数
5. **180-249行目**: module.exportsでAPI公開

#### Step 3: 内部モジュール構成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | crypto.js | `lib/crypto.js` | 内部モジュールのインポート |

**インポート構成**:
- **49-59行目**: internal/crypto/random - 乱数生成
- **61-63行目**: internal/crypto/argon2 - Argon2パスワードハッシュ
- **64-67行目**: internal/crypto/pbkdf2 - PBKDF2鍵導出
- **68-71行目**: internal/crypto/scrypt - scrypt鍵導出
- **72-75行目**: internal/crypto/hkdf - HKDF鍵導出
- **76-81行目**: internal/crypto/keygen - 鍵生成
- **82-87行目**: internal/crypto/keys - KeyObject管理
- **88-93行目**: internal/crypto/diffiehellman - DH鍵交換
- **94-102行目**: internal/crypto/cipher - 暗号化/復号
- **103-108行目**: internal/crypto/sig - 署名/検証
- **109-113行目**: internal/crypto/hash - ハッシュ/HMAC
- **114-116行目**: internal/crypto/x509 - X.509証明書

#### Step 4: FIPSモードとWebCryptoを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | crypto.js | `lib/crypto.js` | FIPS/WebCrypto実装 |

**主要処理フロー**:
- **251-265行目**: getFips(), setFips() - FIPSモード制御
- **130-134行目**: lazyWebCrypto() - WebCrypto遅延ロード
- **355-377行目**: webcrypto, subtle, getRandomValuesプロパティ

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

```
crypto.createHash(algorithm, options)
    │
    └─ new Hash(algorithm, options)
           │
           └─ internal/crypto/hash.js

crypto.createCipheriv(cipher, key, iv, options)
    │
    └─ new Cipheriv(cipher, key, iv, options)
           │
           └─ internal/crypto/cipher.js

crypto.generateKeyPair(type, options, callback)
    │
    └─ internal/crypto/keygen.generateKeyPair()
           │
           ├─ RSA鍵生成
           ├─ EC鍵生成
           ├─ Ed25519鍵生成
           │
           └─ callback(err, publicKey, privateKey)

crypto.randomBytes(size, callback)
    │
    └─ internal/crypto/random.randomBytes()
           │
           └─ OpenSSL RAND_bytes()

crypto.scrypt(password, salt, keylen, options, callback)
    │
    └─ internal/crypto/scrypt.scrypt()
           │
           └─ OpenSSL EVP_PBE_scrypt()
```

### データフロー図

```
[ハッシュ計算]

data            ───▶  createHash        ───▶  Hash
                           │
                      update(data)
                           │
                      digest(encoding)
                           │
                      ───▶  ハッシュ値

[暗号化]

plaintext       ───▶  createCipheriv    ───▶  Cipheriv
key, iv               │
                      update(data)
                           │
                      final()
                           │
                      ───▶  暗号文 + authTag

[署名]

data            ───▶  createSign        ───▶  Sign
                           │
                      update(data)
                           │
                      sign(privateKey)
                           │
                      ───▶  署名

[鍵導出]

password        ───▶  scrypt            ───▶  導出鍵
salt, options         │
                      OpenSSL EVP_PBE_scrypt
                           │
                      callback(err, derivedKey)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| crypto.js | `lib/crypto.js` | ソース | 公開API定義（メイン） |
| internal/crypto/random.js | `lib/internal/crypto/random.js` | ソース | 乱数生成 |
| internal/crypto/hash.js | `lib/internal/crypto/hash.js` | ソース | ハッシュ/HMAC |
| internal/crypto/cipher.js | `lib/internal/crypto/cipher.js` | ソース | 暗号化/復号 |
| internal/crypto/sig.js | `lib/internal/crypto/sig.js` | ソース | 署名/検証 |
| internal/crypto/keygen.js | `lib/internal/crypto/keygen.js` | ソース | 鍵生成 |
| internal/crypto/keys.js | `lib/internal/crypto/keys.js` | ソース | KeyObject管理 |
| internal/crypto/pbkdf2.js | `lib/internal/crypto/pbkdf2.js` | ソース | PBKDF2鍵導出 |
| internal/crypto/scrypt.js | `lib/internal/crypto/scrypt.js` | ソース | scrypt鍵導出 |
| internal/crypto/hkdf.js | `lib/internal/crypto/hkdf.js` | ソース | HKDF鍵導出 |
| internal/crypto/argon2.js | `lib/internal/crypto/argon2.js` | ソース | Argon2パスワードハッシュ |
| internal/crypto/diffiehellman.js | `lib/internal/crypto/diffiehellman.js` | ソース | DH/ECDH鍵交換 |
| internal/crypto/x509.js | `lib/internal/crypto/x509.js` | ソース | X.509証明書 |
| internal/crypto/webcrypto.js | `lib/internal/crypto/webcrypto.js` | ソース | Web Crypto API |
