鍵が小さすぎると、何が壊れるのか
暗号鍵は「長さ」が命だ、とよく言われる。だが今回の件は、長さ以前の話だった。P-384 のはずの秘密鍵が、実際には 256 未満の整数しか取っていなかった。言い換えると、384 ビットの世界を想定して置いた扉に、8 ビットぶんの南京錠を掛けていたようなものだ。しかもそれが 1 本ではない。影響したのは 8 本の中間 CA 証明書で、しかもそれぞれが実際に署名に使われていた。
最初にこの話を見たとき、私は「秘密鍵が漏れた」のだと思った。だが違う。盗まれたのではなく、最初から弱かった。Mozilla のコメントには、影響鍵は 2025 年 4 月 30 日に作成された 24 本の中間 CA の一部で、B 系列と C 系列の P-384 鍵が該当するとある。さらに、P-384 の秘密鍵は本来 1 から群の位数までのランダムな整数であるべきなのに、該当した 8 本はすべて 256 未満だった。つまり、最上位側はほぼ全部 0 で、最後の 1 バイトだけに値が入っていた。
Scott Helme の解説では、実際に復元された値の例として 4 が挙がっている。ほかに 56 や 115 もあった。ここで重要なのは、「数字が小さかった」こと自体ではない。P-384 の秘密鍵としては、ほとんどあり得ないくらい小さいという点だ。P-384 は 384 ビットの楕円曲線鍵で、正しく生成された秘密鍵は 2 の 384 乗に近い広大な空間から選ばれる。そこから 256 通りしかない領域に落ちてしまえば、総当たりの難易度は激変する。
256 通りしかない世界
楕円曲線暗号の入り口だけ押さえると、秘密鍵 d から公開鍵を作るのは d × G という計算で行う。G は決まった基準点で、公開鍵はその繰り返し足し算の結果になる。順方向は簡単だが、公開鍵から d を逆算するのは難しい。だからこそ秘密が守れる。ところが d が 384 ビットどころか 1 バイトに収まるなら話は変わる。候補は 0 から 255 までしかない。公開鍵と照合しながら 1、2、3……と試せば終わる。
Mozilla のコメントには、もっと露骨な表現がある。8 本の影響鍵は「実質的に最後の 1 バイト以外が 0」と説明され、baby-step giant-step のような離散対数アルゴリズムを使うまでもなく、最初の 256 個の P-384 鍵を順に生成していけば回収できる、と書かれている。Scott Helme は実際に手元のノート PC で復元し、1 秒もかからなかったと報告している。測定条件の細部までは別として、少なくとも「人間の手で、普通の端末で、即座に割れた」という事実は重い。
この事件が厄介なのは、証明書の見た目が壊れていないことだ。公開鍵は楕円曲線上の正しい点として成立してしまう。証明書のエンコードも正しい。曲線も正しい。構造検査は全部通る。失敗の痕跡がないのに、鍵だけが弱い。だから外から見ただけでは気づけない。しかもこの失敗は、署名アルゴリズムの欠陥ではなく、鍵生成そのものの欠陥だった。署名結果が変でもないのに、元の鍵が根本から壊れていた。
何が本当に怖いのか
この種の事故は、鍵が「誰かに盗まれた」場合よりも扱いが難しい。盗難なら、いつ、どこで、誰に奪われたかをある程度推測できる。だが今回のように鍵生成が最初から弱ければ、鍵は証明書が公開された時点で実質公開情報になっていた可能性がある。Mozilla 側の文面では、8 本の鍵は 2025 年 4 月以降にいつでも回収可能だったことになりうる。つまり、問題は「失効させたかどうか」だけではない。どれだけ長く、この弱い鍵が使われ得たかだ。
この点で Chrome と Firefox の対応は意味がある。両者は影響中間証明書を直接ブロックし、Chrome は CRLSet、Firefox は OneCRL で素早く止めた。Chrome 側は、証明書透明性が強制されるため、そもそもこの中間 CA にぶら下がる TLS 証明書が CT ログに載っていなかった以上、ブラウザ既定の保護では偽造証明書が通らないと説明している。ただし、それはブラウザの話だ。TLS を使うソフトウェアはブラウザだけではない。
Mozilla のコメントや eMudhra の公開ページが繰り返し触れているのは、ここだ。curl、Python、Node、Go、Java、git、各種パッケージマネージャー、CI/CD のランナー、組み込み機器、古い機器、Windows のコード署名。こうした世界では、失効情報をきちんと見ない実装が珍しくない。CA バンドルをディスクから信頼して、revocation を見ず、CT も見ない。そういうクライアントは、失効済みだから安全、とはならない。しかも中間 CA は、1 本でも通ってしまえば任意のサイトに見せかけた証明書を発行できる。HTTPS の対話だけでなく、更新スクリプトや依存取得、社内 API、ファームウェア更新まで影響しうる。
Mozilla が「wider ecosystem」と繰り返すのはそのためだ。ブラウザの外側では、更新されない信頼ストア、固定された CA バンドル、revocation を見ないデフォルト設定が山ほどある。ここに 1 本の弱い中間 CA が刺さると、被害は「Web サイトの偽装」に留まらない。
事件が示した、証明書運用の盲点
eMudhra 側の説明も、火元の輪郭を少しだけ見せている。公開声明では、対象は 2025 年 4 月の Key Generation Ceremony で作られた特定の中間 CA に限られ、root CA の秘密鍵や他の中間 CA には影響しないとしている。Bugzilla のコメントでは、KGC スクリプトに欠陥があり、ある日だけ弱い ECC 鍵が生成され、それが誤って CSR の作成に使われた可能性が示されている。さらに、ラベルが似ていたために誤った鍵を使った、という説明まで出ている。
ここで見えてくるのは、暗号そのものより運用の脆さだ。HSM は FIPS 140-2 Level 3 対応とされ、装置自体は別に壊れていない。問題は、装置の中で何をどう作るか、どの鍵がどの用途か、どのタイミングでどの CSR を使うか、という工程管理にある。もし同じ日に 24 本の中間 CA を作り、その一部だけが極端に弱い鍵になり、しかもそれが本番のチェーンに入ってしまうなら、実害は「鍵長のミス」以上だ。生成、検証、ラベル付け、交差署名、失効、そのどれか 1 個でも抜けると、証明書基盤そのものが崩れる。
では、なぜ 8 本だけが 256 未満だったのか。なぜ 4 のような値まで混ざったのか。どうして P-384 なのにそんな値が通ってしまったのか。Mozilla は「鍵生成の欠陥」とまでは踏み込んでいるが、その内訳はまだ別の話だ。コードのどこで、どの処理が、どういう条件でそうなったのか。ここを見ないと、同種の事故はまた起きる。
そして、1 秒で割れたという数字も、ただの印象では終わらない。実際にどの手順で、どの計算で、どこまで自動化できて、どこに限界があるのか。8 本のうち何が同じで何が違ったのか。そこまで見て初めて、この事故が「たまたま見つかった脆弱さ」なのか、「もっと広く潜んでいる失敗様式」なのかが分かる。次はその中身だ。
👉 続き(核心はここから)は PaPoo で読めます: https://papoo.work/doc/ba21c3a6de6dce52
