暇だったので、
秘密鍵は一つのファイルとして存在してるけど、それだと危なくなって思ったので、それを解決する方法をcladecodeとCodexと一緒に考えました。次からはその結果をclaudeがまとめた内容になっています。めちゃAI文章なのでAI文章が嫌いな人がいたらごめんなさい。
Key Swarm
完全な秘密鍵がどこにも存在しない状態を作れるか
二台の実機による検証と、場所の数についての不可能性
Key Swarm Lab / 2026-08-06 / 総括版 v2.0
要旨
秘密鍵は普通、一つの完全な値として一つのファイルに存在する。そのファイルを
読める者は鍵を持つ者である。本研究は「その完全な値を、最初から一度も存在
させないことはできるか」を問い、実機二台で実物を作って答えた。
鍵は生成の瞬間から四つの破片に分かれ、三つ揃わなければ署名できない。破片は
二台の機械に二つずつ置かれ、どちらの機械も三つを持たない。完全な鍵は
生成時にも署名時にも組み立てられない。
実機で確認したのは四つである。作る(二台にまたがる分散鍵生成)、使う
(二台にまたがる署名)、入れ替える(世代交代。古い破片を消さずに無効化
する)、取り戻す(一台を失った状態からの復旧)。加えて猶予窓の三つの
結末——保留・取り消し・通過——をすべて実測した。
同時に、場所の数についての不可能性を全列挙で示した。「一箇所失っても残り
がしきい値に届く」と「どの一箇所も単独ではしきい値に届かない」は、二箇所
では同時に成立しない。しきい値をどう選んでも例外はない。三箇所でも
三-of-四では足りず、四箇所に一つずつ置いて初めて両立する。これは設定の巧拙
ではなく、置き場所の数が決める。
第一部 問い
1.1 出発点
秘密鍵のファイルが一つしかないことが不安である、という素朴な違和感が出発点
だった。バックアップを取れば、鍵は二箇所に存在する。取らなければ、失えば
終わりである。どちらも「完全な鍵が実体として存在する」という前提の上での
選択にすぎない。
そこで前提を外した。完全な値を一度も作らなければ、盗む対象が存在しない。
1.2 問いの形
秘密鍵は一つの完全な値として一つのファイルに作られる。
その単一の完全な秘密を、そもそも一度も存在させないようにできるか。
「できる」と答えるには、次を実物で示す必要がある。
- 鍵を作るとき、完全な値がどこにも現れないこと
- 鍵を使うとき、完全な値がどこにも現れないこと
- 破片が漏れた疑いに答えられること(=入れ替えられること)
- 機械が壊れても戻せること
3 と 4 は 1・2 の帰結として必要になる。バックアップを禁じた以上、その役目を
別の仕組みが引き受けなければならない。
第二部 設計
2.1 破片で作り、破片のまま使う
FROST(RFC 9591、Ed25519 上のしきい値 Schnorr 署名)を用いる。鍵は
**分散鍵生成(DKG)**で作られる。各参加者は自分の破片だけを持ち、完全な鍵は
生成の瞬間にも存在しない。誰かが作って配るのではない。
署名も同様に、各破片が部分署名を出し、それを合成する。合成する側は破片を
知らない。
本研究の構成は 三-of-四。四つの破片のうち三つで署名できる。
2.2 配置——「一緒に取られるもの」で数える
破片の数を数えても意味がない。意味があるのは同時に失われる単位である。
本研究ではこれを **location(場所)**と呼び、運用者が明示的に宣言する。
アドレスやパスから推測しない。同一機械上の二つのノードが片方はループバック、
片方は LAN を待ち受けることもあれば、別々の機械が同じパスを使うこともある。
どちらも機械から自動判定できない。
PC-A : node-1, node-2 (破片2つ)
PC-B : node-3, node-4 (破片2つ)
しきい値 3
どちらの機械も単独では署名できない。 これが分散の実体である。
2.3 鍵の履歴と、名前の分離
identity(身元)と鍵を分離する。identity は創世エントリのハッシュであり、
自己証明的である。鍵はその履歴の中で入れ替わる。
identity ce7cf522… ← 名前。変わらない
epoch 0 鍵 = G1
epoch 1 鍵 = R ← 鍵は替わったが、同じ identity
各エントリは次世代の鍵をハッシュで先に約束する(事前約束)。これにより、
交代先は「その時に選んだ鍵」ではなく「必要になる前から決まっていた鍵」に
限定される。
2.4 世代交代——バックアップの代わり
破片が漏れた疑いに対する答えは、復元ではなく入れ替えである。
交代には二つの定足数が要る。旧世代が「交代してよい」と署名し、新世代が
「自分は確かにその鍵を持っている」と証明する。片方だけでは成立しない。
盗まれた旧破片だけで乗っ取ることも、攻撃者の鍵を勝手に押し込むこともできない。
交代が終わると、古い破片はファイルとして残ったまま、identity に対して
何の権限も持たなくなる。無効にするのは削除ではなく履歴である。だから
「相手の手元にコピーがある」場合でも同じことが起きる。
2.5 復旧——世代交代では届かない場合
一つの機械に二つの破片を置く構成では、機械を一台失うと破片が二つ同時に
消える。残るのは二つで、しきい値三に届かない。署名できないということは、
世代交代もできない(交代には旧世代の署名が要る)。自分で自分を助けられない。
そこで創世の時点で、別系統の権限と別の世代を約束しておく。
三つが揃って初めて復旧が成立する。復旧権限だけでは何もできない。
- 署名するのが創世で名指しした権限であること
- 入れる世代が創世で約束した世代であること
- その世代が自分の鍵を持っていることを証明すること
加えて、創世時に設定した時間錠が満了していること。これが「静かに奪う」
ことを防ぐ。復旧の約束は使い切りで、次のエントリには持ち越されない。
2.6 猶予窓——署名は、それだけでは効力を持たない
定足数が署名しても、その場では使える署名にならない。出るのは「猶予の中の
行動」であり、独立した観測者が「異議がなかった」と証明して初めて効力を持つ。
PENDING 猶予の中。まだ効力がない
VETOED 取り消された。待っても覆らない
EFFECTIVE 誰も異議を出さずに通過した
確定には定足数が要るが、止めるのは一人でよい。 非対称なのは意図的である。
この設計は型で強制されている。効力を持つ署名を表す EffectiveSignature には
公開の構築子がない。猶予窓を経ない限り値が作れないため、窓を飛ばすと
コンパイルが通らない。
第三部 場所の数についての不可能性
3.1 二つの要求
予備の世代(復旧用)が満たすべきことは二つある。
- 一箇所失っても、残りがしきい値に届く(届かなければ復旧できない)
- どの一箇所も、単独ではしきい値に届かない(届けばそこに完全な鍵がある)
後者を落とせば、本研究の前提そのものが崩れる。
3.2 結果
四つの破片を二箇所に配る全ての置き方を列挙した。さらに、計画検証が受け付ける
あらゆる形(破片数 2〜8、しきい値 2〜n、2t > n+1 を満たすもの)について
同じ列挙を行った。
二箇所では、両立する置き方が一つも存在しない。
理由は単純である。一箇所を失って残りがしきい値に届くなら、その残った一箇所は
しきい値を持っている。つまりそこに完全な鍵がある。二つの要求は正面から矛盾する。
三箇所でも足りない場合がある。三-of-四では、一箇所失って三つ残るには
どの箇所も一つしか持てず、四つの破片は三箇所に収まらない。
| 場所の数 | 三-of-四 | 四-of-六 |
|---|---|---|
| 2 | 不可能 | 不可能 |
| 3 | 不可能 | 可能(各2個) |
| 4 | 可能(各1個) | 可能 |
「場所が三つしかない」は分け方を変えれば解ける。「二つしかない」は解けない。
3.3 さらに強い要求を置くと
「二箇所が結託しても乗っ取れない」まで求めると、三箇所では不可能になる。
四箇所に一つずつ置いた三-of-四だけが、三つの要求すべてを同時に満たす。
これは配置の巧拙ではなく、用意できる場所の数が上限を決めるという結論である。
3.4 同じ理屈が猶予窓にも効く
観測者は破片のない場所に置かなければならない。破片のある場所に置けば、
その場所を取った者は署名も確定も両方できてしまう。窓が存在するのは
「すべての破片が取られた」場合のためであり、その場合に観測者も一緒に取られる
なら、窓は文書の上にだけ存在することになる。
本研究の実装はこれを検査し、成立しない配置の計画を書き込む前に拒否する。
第四部 実機での検証
PC-A(192.168.10.103)と PC-B(192.168.10.200)の二台。実ネットワーク、
実ファイル、実プロセス。
4.1 通ったこと
| 段階 | 内容 | 結果 |
|---|---|---|
| Step 4 | 二台で鍵生成、二台で署名、猶予窓の中で取り消し | 成立 |
| Step 5 | 二台目で全ゲート | 13/13 PASS |
| Step 6 | 世代交代(epoch 0 → 1) | 成立 |
| Step 7 | 一台を失った状態からの復旧 | 成立 |
| Step 8 | 猶予窓を通過して EFFECTIVE | 成立 |
4.2 破片の実測
三世代・十二個の破片について、両方の機械が自分の一覧を出し、一覧同士を
突き合わせた。
shares counted: 12
distinct digests: 12
no share appears on both machines, and none is repeated
G0: PC-A holds 2, PC-B holds 2, threshold is 3 -> ok
G1: PC-A holds 2, PC-B holds 2, threshold is 3 -> ok
G2: PC-A holds 2, PC-B holds 2, threshold is 3 -> ok
片方の機械だけでは、この主張は立たない。両方に同じ破片のコピーが置かれて
いても、片側の確認だけなら通ってしまう。この点は共同作業者(PC-B 側)の
指摘によって明確になり、以後は突き合わせを機械が行うようにした。
4.3 世代交代の実測
identity 3a8e9d23…(変わらず)
epoch 0 → 1
key G0 → 6649d91a…fc693a(G1)
交代後、G0 の破片四つはディスク上に残り、ハッシュも一バイト変わっていない。
それでも identity に対して何の権限も持たない。無効にしたのは履歴である。
4.4 復旧の実測
PC-B を起動しない(=失った)状態から。
| 段階 | 結果 |
|---|---|
| PC-A の二ノードは起動している状態で署名を試みる |
cannot reach 192.168.10.200:47103 — 署名不能
|
| 時間錠の満了を待つ | 60秒実際に待った(時刻の上書きは使っていない) |
| 復旧権限+生存三ノードで復旧 | epoch 1、鍵は復旧用世代へ |
「三つ揃わなければ何もできない」ことを、実際に一台落として確かめた。
4.5 猶予窓の実測
直後 PENDING: 54 seconds still to run; this does not count yet
62秒後 EFFECTIVE: the window elapsed without objection
取り消しの側は Step 4 で確認済みである。観測者三人のうち一人が取り消しを
持つだけで全体が VETOED になる。
第五部 実機でしか出なかった欠陥
自動試験が通っていても見つからず、実機で本当に一台落としたときに初めて出た
欠陥がある。記録として残す価値があると考える。
5.1 生き残った側が署名セッションを作れない
一台を失うと、残る破片の番号は連続しない(例:1, 3, 4)。計画の検証が
「ノード数=世代の大きさ」と読んでいたため、番号 4 は「1..=3 の範囲外」として
拒否された。
復旧が必要な状況そのものが、復旧できない状態だった。
試験用の駆動プログラムは常に全ノードを起動する。したがってこの経路は一度も
通っていなかった。世代の大きさを明示できるようにして修正した。
5.2 経路制御が命名規則に依存していた
分散鍵生成の第二ラウンドは秘密のパッケージを特定の相手に送る。その相手を
「ノード名は node-<番号> である」という仮定から導いていた。それまでの全ての
配置がたまたまその命名だったため、動いていた。別の名前を付けた瞬間に、秘密が
存在しない相手に向けて送られる。
名簿から引くように改めた。
5.3 その他
- 権限鍵の生成物を置く木が、除外規則の外にあった(内容は別の規則で守られて
いたが、規則の重なりに依存していた) - 待ち処理が、既に終了した子プロセスを「遅い」として待ち続けていた
- 手作業で数えた試験件数が三度続けて実際と食い違った。数えるのをやめ、
実行が自分で数えて印字するようにした
第六部 守らないもの
正直に列挙する。以下は本研究の構成では守れない。
-
二台の両方に入り込んだ攻撃者。 破片は三つ揃う。猶予窓は本来ここを塞ぐが、
そのためには破片のない場所が要る -
同一 OS アカウントで動く別プログラム。 現状の配置では同一機械上の
プロセスが全ての破片を読める。これは測定して報告するようにしてあり、
再現スクリプトが毎回NOT ISOLATEDと出力する -
量子コンピュータ。 Ed25519 も FROST も離散対数に依存する。破片に
分けても効果はない。公開鍵から直接秘密鍵が計算されるため、破片を集める
必要すらない - 第三者による監査。 行っていない
ただし、次世代の鍵はハッシュでしか公開されていない。ハッシュは量子でも
割れないため、未使用の次世代鍵は Shor の対象にならない。加えて、世代交代の
仕組みそのものがアルゴリズムの乗り換え路になる。量子耐性そのものではないが、
量子に対する移行可能性は設計に含まれている。
第七部 既存研究との関係
本研究に新しい暗号は含まれない。既存の構成要素の組み合わせ方が主題である。
| 要素 | 既存のもの |
|---|---|
| しきい値署名・DKG | FROST(RFC 9591) |
| 破片の定期的な作り直し | Proactive Secret Sharing |
| 鍵の事前約束と履歴 | KERI の pre-rotation |
| 待機期間と観測者 | Bitcoin の vault 構想、Revault の watchtower |
| 権限の隔離 | TUF のオフライン root 鍵 |
MPC ウォレット(ZenGo、Vultisig 等)は分散署名を実用化しているが、多くは
事業者が一方の破片を持つ。本研究は所有者だけで完結する点と、
配置の妥当性を道具自身が検査して拒否する点が異なる。
第八部 結論
答え
できる。 実物を二台の機械で作り、使い、入れ替え、取り戻した。
完全な秘密鍵は、生成時にも署名時にも、どこにも存在しなかった。
限界
実用の水準に達していない点は二つある。ひとつは独立性——現状は同一 OS
アカウントで動いており、分離は OS が保証していない。もうひとつは配置——
猶予窓と機械故障からの復旧には、破片を持たない第三の場所が要る。
後者は本研究が証明したとおり、設定では解決できない。用意できる場所の数が
上限を決める。したがってこれは実装の課題ではなく、運用者の物理的な決定である。
本研究が示したこと
- 完全な秘密鍵を一度も存在させずに、鍵を作り・使い・入れ替え・取り戻せる
- バックアップの禁止は機能の欠落ではない。世代交代と復旧がその役目を負う
- 分散の効果は破片の数ではなく場所の数で決まり、その上限は数学的に決まる
- 「守られていない配置」は、道具自身が拒否できる