レッスン0 — Validator 鍵管理(hot 鍵、HSM、MPC、閾値署名)
問い
ステーキングオペレータが午前 3 時にページを受け取る。スタンバイ機で 2 つ目の validator プロセスが誤って起動 — 同じ鍵、両方オンライン、両方が同じ height で attestation 署名。ネットワークは同一アイデンティティから 2 つの valid な署名を観測 — equivocation = $2M ペナルティ。Validator の署名鍵 = 経済的アイデンティティ、本番チームはどう守るか?
原理(最小モデル)
- 5 要件は単一解で満たせない. 署名できる + 同 height/round で絶対に 2 署名しない + 公開インターネット非露出 + オペレータ離職を乗り越える + 災害(HW 障害 / DC 喪失)を乗り越える。
- 4 つの解(洗練度順). 設定ファイル hot 鍵(開発のみ)→ HSM(耐タンパー HW + 鍵が外に出ない)→ MPC(N-of-M デバイスで分割)→ 閾値署名(BLS、暗号的に share、再構築不要)。
- MPC ≠ 閾値署名. MPC = 汎用プロトコル(任意関数を秘密 share で計算)/ 閾値署名 = 特定の暗号プリミティブ(署名 scheme 自体が secret-sharing をネイティブ対応)。
- 「2 鍵」パターン. Withdrawal 鍵(cold、stake 資金支配)+ 署名鍵(hot、投票 / 提案 / slashable)。漏洩時の被害有界化:署名鍵漏洩でも資金は盗まれない(slashable のみ)。
- Slashing 防止 4 ルール. アイデンティティごと署名者 1 つだけ + slashing-protection DB + 不確実なら fail-closed + ネットワーク分断耐性。
- リモート signer パターン. Validator ノードは鍵なし → remote signer に署名要求 → HSM で署名 + slashing-protection 強制。Web3Signer / Eth-Signer / Tetuna が本番例。
- マルチリージョン active-passive. DC1 active + DC2 standby + DC3 cold backup。遷移は手動 + コンセンサス経由のみ(両方同時署名で slash 防止)。
具体例
5 要件:
- リーダ / voter のときに署名できる
- 同 height/round で絶対に 2 署名しない(slashing)
- 公開インターネット非露出
- オペレータ離職を乗り越える(複数 ops 担当)
- 災害を乗り越える(HW 障害、DC 喪失)
4 つの解:
1. 設定ファイル hot 鍵 — 危険な例:
# これは危険
echo "0xabc123..." > /var/lib/validator/key.txt
開発 OK、価値のある本番では使わない(FS アクセス = 鍵掌握、バックアップ = クローン)。
2. HSM(Hardware Security Module) — 耐タンパー HW、鍵が外に出ない:
- Validator が HSM 内で鍵生成
- 公開鍵だけ外に出る、秘密鍵はデバイスから出ない
- 署名は validator software が hash を送る → HSM が署名を返す
- Validator software 侵害でも鍵そのものは盗めない(任意メッセージへの valid 署名は作らせられる)
- Pros: 鍵がディスク・メモリにない / Cons: 物理喪失で鍵消失、バックアップ難
- AWS CloudHSM / YubiHSM / Thales、ETH ステーキングプロ向け
3. MPC(Multi-Party Computation) — 鍵を複数デバイスに分割、N-of-M 協力で署名:
- 例: 3 DC × 3 デバイス、署名に 2/3 協力必要
- 1 デバイス侵害でも鍵の 1/3 のみ取得 → 攻撃 2 施設侵害必要
- Pros: どのデバイスも単独で鍵を持たない / Cons: 署名にレイテンシ、プロトコル複雑
- Fireblocks / Coinbase Cloud などの極大規模ステーキング
4. 閾値署名(MPC の暗号版) — BLS 閾値署名:
- 各 validator が集約署名鍵の share
- 部分署名を 1 つの最終署名に集約
- Verifier 側からは通常の BLS 署名と区別不能
- Pros: 暗号的にクリーン、再構築ステップなし / Cons: セットアップ複雑、鍵生成 ceremony 必要
- Ethereum beacon chain / Aleo / Filecoin
「2 鍵」パターン:
| 鍵 | モデル | 役割 |
|---|---|---|
| Withdrawal 鍵 | cold(オフライン保管) | staked 資金支配、紙 / HW wallet |
| 署名鍵 | hot(オンライン) | 投票 / 提案、slashable |
署名鍵漏洩 → slash されるが資金は盗まれない(withdrawal 鍵が cold)。Ethereum: Withdrawal credentials (0x01...) cold + BLS validator 鍵 attestation 用 online。
Slashing 防止 4 ルール:
- アイデンティティごとに署名者 1 つだけ — 同鍵で 2 プロセス絶対動かさない
- Slashing-protection データベース — 全署名済みメッセージを記録、slashing 起こす署名を拒否
- 不確実なら fail-closed — 直近履歴を検証できないなら署名しない
- ネットワーク分断耐性 — 分断の向こうで sync を失っているなら署名しない(fork 上の可能性)
リモート signer パターン:
[Validator ノード] --API 経由ブロック署名--> [HSM 付きリモート signer]
|
+--署名メッセージを追跡
+--危険な署名は拒否
+--HSM 内に鍵を保持
本番実装:
- Web3Signer(Ethereum、Java)
- Eth-Signer(Rust 代替)
- Tetuna(slashing-protection データベース)
マルチリージョン構成:
- DC1 active(ブロック署名)
- DC2 standby(引き継ぎ準備)
- DC3 cold backup(DR)
遷移は 自動化禁止(両方同時署名リスク)→ 手動オペレータ確認 + コンセンサスプロトコル経由のみ。
- Active が block N に署名
- Active が伝播 + finalized 確認
- 手動オペレータが shutdown 確認
- Standby が署名権限引き取り
- Standby が block N+1 に署名
BFT chain なら 1 slot miss、Nakamoto 系なら更に影響小。
失敗例(誤解)
「バックアップ用に複数マシンに鍵をコピー」— 間違い。バックアップ = 鍵のクローン = 並行プロセスのリスク。両マシン同時起動で双方が同 height 署名 → equivocation → slash。バックアップは withdrawal 鍵のみ(cold)、署名鍵はマルチ active-passive で手動遷移。
「MPC と閾値署名は同じ」— 間違い。MPC は汎用プロトコル(秘密 share 上で任意関数計算、署名も含む)/ 閾値署名は特定暗号プリミティブ(署名 scheme 自体が secret-sharing をネイティブ対応)。閾値署名がクリーン、MPC が柔軟。
「冗長化のため 2 マシンで重複プロセス」— 致命的。両マシンで同鍵 → 両方が同 epoch attestation 署名 → 一方 canonical、もう一方 double-signing → slashed。冗長化のつもりが slashing 違反 → active-passive 厳格 failover(常に 1 ノードのみ署名権限、コンセンサス経由遷移)。
🛑 予測。 ある validator が 100 ノードを稼働。署名鍵のコピーは何個存在するか?「1 + 100」と思ったなら、その状態が許す攻撃は何か?(答え: 「1 + 100」= 危険な実装。各 100 ノード上の鍵コピーは ① ファイルシステム侵害で 1 ノード分の鍵取得可能、② どこか 1 ノードでも誤動作で同 height 2 署名 → 全 100 が equivocation で slashed、③ 鍵ローテーション時に全 100 を一斉更新が必要 = 同期失敗で部分的に古鍵残る → 攻撃面拡大。正しい設計 = ① HSM で鍵が物理デバイスから出ない(1 個のみ)+ ② リモート signer サービスを共有(100 ノードが 1 signer に署名要求)+ ③ active-passive で 1 時点 1 ノードのみ署名権限。「鍵コピー」は本番運用の anti-pattern。)
ステップで組み立てる
Step 1: 5 要件を即答
署名可能 + 同 height/round で 2 署名しない + 公開非露出 + 離職耐性 + 災害耐性。
Step 2: 4 解の洗練度順
設定ファイル(開発のみ)→ HSM(鍵が外に出ない)→ MPC(分割)→ 閾値署名(BLS、暗号的)。
Step 3: MPC vs 閾値署名
MPC = 汎用プロトコル / 閾値署名 = 特定暗号プリミティブ。
Step 4: 2 鍵パターン
Withdrawal(cold、資金)+ 署名(hot、slashable)。漏洩時の被害有界化。
Step 5: Slashing 防止 4 ルール
1 アイデンティティ 1 署名者 + slashing-protection DB + fail-closed + 分断耐性。
Step 6: リモート signer + マルチリージョン
Validator は鍵なし、remote signer に API 経由要求 + HSM 保管 + slashing-protection 強制。Active-passive で手動 + コンセンサス遷移。
Step 7: 自分の chain への適用
Tempo / Hyperliquid validator のローンチ運用チェックリスト:
- 署名鍵 HSM
- 3 リージョン active-passive
- slashing-protection DB 統合
- Withdrawal 鍵は専用 HW wallet オフライン
答え合わせ
- 「鍵コピー」が anti-pattern の理由: ① 攻撃面 N 倍化(各コピー = 侵害ターゲット)、② 並行プロセスで equivocation リスク(1 個誤動作で全コピー slashed)、③ ローテーション困難(同期失敗で旧鍵残る)。正解 = HSM 1 物理 + リモート signer + active-passive(1 時点 1 ノードのみ署名権限)。
- MPC と閾値署名の本質的違い: MPC = 「汎用プロトコル」、秘密 share 上で任意関数を露出させず計算(署名も含む)→ 任意の署名 scheme に適用可能。閾値署名 = 「特定の暗号プリミティブ」、署名 scheme 自体が secret-sharing をネイティブサポート → 部分署名を集約しても通常の BLS 署名と区別不能。閾値署名がクリーン(再構築なし)、MPC が柔軟(既存署名 scheme に適用)。
- 「冗長化のための 2 マシン重複」の slashing: 両マシン同鍵 → 両方が同 epoch attestation 署名 → 一方 canonical、もう一方 double-signing として見える → slashed。冗長化が slashing 違反に化ける。修正 = active-passive 厳格 failover(1 時点 1 ノードのみ署名権限、遷移はコンセンサス経由のみ)。
合格基準
- 5 要件と 4 解(洗練度順)を即答できる。
- MPC ≠ 閾値署名の違いを 1 文で説明できる。
- 2 鍵パターン(Withdrawal cold + 署名 hot)と漏洩時被害有界化を言える。
- Slashing 防止 4 ルールを暗唱できる。
- リモート signer + active-passive 構成を絵で書ける。
まとめ(3行)
- Validator 署名鍵 = 経済的アイデンティティ、5 要件は単一解で満たせない、4 解(設定ファイル → HSM → MPC → 閾値署名)を洗練度順に選ぶ。
- 「2 鍵」パターン(Withdrawal cold + 署名 hot)で漏洩時被害有界化、Slashing 防止 4 ルール(1 署名者 + DB + fail-closed + 分断耐性)。
- リモート signer + HSM + マルチリージョン active-passive(手動 + コンセンサス遷移)= 本番 validator の標準解、「鍵コピー」は anti-pattern。