# 機能設計書 10-tls

## 概要

本ドキュメントは、Node.jsのtlsモジュール（TLS/SSL通信プロトコル機能）の機能設計を記載する。tlsモジュールは、OpenSSLをベースにしたTLS（Transport Layer Security）およびSSL（Secure Sockets Layer）プロトコルによる暗号化通信を提供するコアモジュールである。

### 本機能の処理概要

tlsモジュールは、TCPソケット上にTLS/SSL暗号化レイヤーを提供する。サーバー証明書の検証、クライアント証明書認証、ALPNプロトコルネゴシエーションなど、セキュアな通信に必要な機能を包括的にサポートする。

**業務上の目的・背景**：インターネット上の通信を暗号化し、盗聴や改ざんから保護するためにTLS/SSLは不可欠である。tlsモジュールは、httpsモジュールやhttp2モジュールの基盤として、また直接利用することでカスタムセキュアプロトコルの実装を可能にする。

**機能の利用シーン**：
- HTTPSサーバー/クライアントの基盤
- セキュアなTCPサーバー/クライアント
- 相互TLS認証（mTLS）
- ALPNによるプロトコルネゴシエーション
- 証明書検証
- TLSセッション再開
- SNI（Server Name Indication）対応

**主要な処理内容**：
1. TLSサーバーの作成（createServer, Server）
2. TLSクライアント接続（connect）
3. セキュアコンテキスト管理（createSecureContext, SecureContext）
4. サーバー証明書検証（checkServerIdentity）
5. 暗号スイート管理（getCiphers, DEFAULT_CIPHERS）
6. CA証明書管理（rootCertificates, getCACertificates, setDefaultCACertificates）
7. ALPNプロトコル変換（convertALPNProtocols）
8. TLSバージョン管理（DEFAULT_MIN_VERSION, DEFAULT_MAX_VERSION）

**関連システム・外部連携**：
- OpenSSLライブラリ
- cryptoモジュール（暗号化基盤）
- netモジュール（TCP基盤）
- httpsモジュール（HTTPS）
- http2モジュール（HTTP/2）

**権限による制御**：特別な権限制御なし。証明書ファイルへのアクセス権限が必要。

## 関連画面

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

## 機能種別

暗号化通信 / セキュリティ / ネットワーク

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| key | string/Buffer/Array | Yes(サーバー) | 秘密鍵 | - |
| cert | string/Buffer/Array | Yes(サーバー) | 証明書 | - |
| ca | string/Buffer/Array | No | CA証明書 | - |
| ALPNProtocols | Array/Buffer | No | ALPNプロトコル | convertALPNProtocols |
| minVersion | string | No | 最小TLSバージョン | validateString |
| maxVersion | string | No | 最大TLSバージョン | validateString |
| ciphers | string | No | 暗号スイート | - |
| rejectUnauthorized | boolean | No | 証明書検証 | - |
| servername | string | No | SNI用サーバー名 | - |
| requestCert | boolean | No | クライアント証明書要求 | - |

### 入力データソース

- アプリケーションコード：証明書、鍵、TLS設定
- ファイルシステム：証明書ファイル、CA証明書
- システム：システムCA証明書ストア

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| server | Server | TLSサーバーインスタンス |
| socket | TLSSocket | TLSソケットインスタンス |
| secureContext | SecureContext | セキュアコンテキスト |
| ciphers | Array | 利用可能な暗号スイート |
| certificates | Array | CA証明書一覧 |

### 出力先

- サーバー：クライアントへの暗号化接続
- クライアント：イベント（'secureConnect'）

## 処理フロー

### 処理シーケンス（サーバー）

```
1. createServer(options)でServerインスタンス生成
   └─ createSecureContext()でセキュアコンテキスト生成
2. server.listen(port)でポートバインド
3. クライアント接続
   └─ TLSハンドシェイク
   └─ 証明書検証
   └─ ALPNネゴシエーション
4. 'secureConnection'イベント発火
5. TLSSocket経由でデータ送受信
```

### 処理シーケンス（クライアント）

```
1. connect(options)でTLSSocket生成
2. TCPコネクション確立
3. TLSハンドシェイク開始
   └─ ClientHello送信
   └─ ServerHello受信
   └─ 証明書検証（checkServerIdentity）
   └─ 鍵交換
4. 'secureConnect'イベント発火
5. 暗号化通信開始
```

### フローチャート

```mermaid
flowchart TD
    A[createServer] --> B[SecureContext生成]
    B --> C[server.listen]
    C --> D{クライアント接続?}
    D -->|Yes| E[TLSハンドシェイク]
    E --> F[証明書検証]
    F --> G{検証OK?}
    G -->|Yes| H[ALPNネゴシエーション]
    G -->|No| I[接続拒否]
    H --> J[secureConnectionイベント]
    J --> K[暗号化通信]
    K --> D
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | デフォルト最小バージョン | TLSv1.2（--tls-min-* オプションで変更可） | デフォルト |
| BR-002 | デフォルト最大バージョン | TLSv1.3（--tls-max-* オプションで変更可） | デフォルト |
| BR-003 | クライアント再ネゴシエーション制限 | 600秒あたり3回まで | サーバー側 |
| BR-004 | ALPN最大長 | 各プロトコル名は255バイト以下 | ALPNProtocols指定時 |
| BR-005 | ワイルドカード証明書 | *.tld形式は不許可 | checkServerIdentity |
| BR-006 | CA証明書優先順位 | bundled → system → extra | --use-openssl-ca未指定時 |

### 計算ロジック

- CLIENT_RENEG_LIMIT: 3（再ネゴシエーション制限回数）
- CLIENT_RENEG_WINDOW: 600（秒、制限ウィンドウ）
- DEFAULT_ECDH_CURVE: 'auto'

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ERR_TLS_CERT_ALTNAME_INVALID | 証明書エラー | ホスト名が証明書と不一致 | 証明書/ホスト名を確認 |
| ERR_TLS_CERT_ALTNAME_FORMAT | 証明書エラー | altname形式エラー | 証明書を確認 |
| UNABLE_TO_VERIFY_LEAF_SIGNATURE | 検証エラー | 証明書チェーン検証失敗 | CA証明書を確認 |
| CERT_HAS_EXPIRED | 検証エラー | 証明書期限切れ | 証明書を更新 |
| DEPTH_ZERO_SELF_SIGNED_CERT | 検証エラー | 自己署名証明書 | CA設定またはrejectUnauthorized |
| ERR_OUT_OF_RANGE | バリデーション | プロトコル名が長すぎ | 255バイト以下に |

### リトライ仕様

TLSハンドシェイク失敗時はアプリケーション層でリトライ。セッション再開によるハンドシェイク高速化をサポート。

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

TLSはセッションベースのプロトコル。セッションチケットによる再接続最適化をサポート。

## パフォーマンス要件

- バックグラウンドでの証明書ロード（startLoadingCertificatesOffThread）
- セッション再開による接続高速化
- ALPNによるプロトコル決定の最適化
- 暗号スイートのキャッシュ（cachedResult）

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

- TLSv1.2以上の使用推奨
- 弱い暗号スイートの無効化
- 証明書検証の有効化（rejectUnauthorized: true）
- 最新のCA証明書の使用
- クライアント証明書認証の検討（mTLS）
- SNIによる適切な証明書選択

## 備考

- OpenSSLバージョンによってサポート機能が異なる
- NODE_EXTRA_CA_CERTS環境変数で追加CA証明書を指定可能
- --use-system-caでシステムCA証明書ストアを使用
- スナップショット機能に対応（シリアライズ/デシリアライズ）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | tls.js | `lib/tls.js` | 定数定義とCA証明書管理 |

**読解のコツ**: TLSバージョン設定（92-108行目）、再ネゴシエーション制限（85-86行目）、CA証明書キャッシュ関数（116-181行目）が重要。

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

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

**主要処理フロー**:
1. **85-86行目**: CLIENT_RENEG_LIMIT, CLIENT_RENEG_WINDOW定数
2. **88-108行目**: DEFAULT_CIPHERS, DEFAULT_MIN_VERSION, DEFAULT_MAX_VERSION
3. **111-113行目**: getCiphers() - 暗号スイート一覧取得
4. **122-127行目**: rootCertificatesプロパティ
5. **184-200行目**: getCACertificates() - CA証明書取得
6. **202-220行目**: setDefaultCACertificates() - CA証明書設定

#### Step 3: 証明書検証を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | tls.js | `lib/tls.js` | サーバー証明書検証の実装 |

**主要処理フロー**:
- **283-295行目**: unfqdn(), toLowerCase(), splitHost() - ホスト名正規化
- **297-359行目**: check() - ワイルドカードマッチング
- **364-397行目**: splitEscapedAltNames() - altname解析
- **399-457行目**: checkServerIdentity() - サーバー証明書検証

#### Step 4: ALPN処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | tls.js | `lib/tls.js` | ALPNプロトコル変換 |

**主要処理フロー**:
- **246-266行目**: convertProtocols() - プロトコル配列をOpenSSL形式に変換
- **268-281行目**: convertALPNProtocols() - ALPN設定

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

```
tls.createServer(options, secureConnectionListener)
    │
    └─ tlsWrap.createServer()
           │
           ├─ createSecureContext(options)
           │      │
           │      └─ tlsCommon.createSecureContext()
           │             └─ OpenSSL SSL_CTX
           │
           ├─ new Server(options)
           │      └─ net.Server継承
           │
           └─ secureConnectionListener登録

tls.connect(options, callback)
    │
    └─ tlsWrap.connect()
           │
           ├─ net.connect() [TCP接続]
           │
           ├─ new TLSSocket(socket, options)
           │      │
           │      ├─ SecureContext設定
           │      │
           │      └─ OpenSSL SSL
           │
           └─ TLSハンドシェイク
                  │
                  ├─ ClientHello
                  │
                  ├─ ServerHello + 証明書
                  │
                  ├─ checkServerIdentity(hostname, cert)
                  │      │
                  │      ├─ altname解析
                  │      │
                  │      ├─ DNS名チェック
                  │      │
                  │      └─ IPアドレスチェック
                  │
                  └─ 'secureConnect'イベント

tls.getCACertificates(type)
    │
    ├─ 'default' → cacheDefaultCACertificates()
    │      │
    │      ├─ getBundledRootCertificates()
    │      │
    │      ├─ getSystemCACertificates()
    │      │
    │      └─ getExtraCACertificates()
    │
    ├─ 'bundled' → cacheBundledRootCertificates()
    │
    ├─ 'system' → cacheSystemCACertificates()
    │
    └─ 'extra' → cacheExtraCACertificates()
```

### データフロー図

```
[サーバー側]

options         ───▶  createServer        ───▶  Server
(key, cert)           │
                      createSecureContext
                           │
                      listen()
                           │
                      クライアント接続
                           │
                      TLSハンドシェイク
                           │
                      'secureConnection'イベント

[クライアント側]

options         ───▶  connect             ───▶  TLSSocket
(host, port)          │
                      TCP接続
                           │
                      TLSハンドシェイク
                           │
                      checkServerIdentity(hostname, cert)
                           │
                      ┌────┴────┐
                      │         │
                    OK│         │NG
                      │         │
              'secureConnect'  'error'

[CA証明書管理]

証明書ソース    ───▶  getCACertificates   ───▶  CA証明書配列
                           │
                      ┌────┼────┬────┐
                      │    │    │    │
                   bundled system extra default
                      │    │    │    │
                      └────┴────┴────┘
                           │
                      ObjectFreeze()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| tls.js | `lib/tls.js` | ソース | 公開API定義（メイン） |
| internal/tls/common.js | `lib/internal/tls/common.js` | ソース | SecureContext実装 |
| internal/tls/wrap.js | `lib/internal/tls/wrap.js` | ソース | TLSSocket/Server実装 |
| net.js | `lib/net.js` | ソース | TCP基盤 |
| crypto.js | `lib/crypto.js` | ソース | 暗号化基盤 |
