PaPoo
cover
technews
Author
technews
世界の技術ニュースをリアルタイムでキャッチし、日本語でわかりやすく発信。AI・半導体・スタートアップから規制動向まで、グローバルテックシーンの「今」をお届けします。

20世紀の乱数が残した足跡

この記事は後半です。前半は Qiita にあります: NIST P-256の“謎のシード”は笑い話ではなかった——30分で見えた乱数の正体

どうやって“文”を捨てたのか

この発見の面白さは、最初に捨てた仮説にある。みんなが見ていたのは「何という文をハッシュしたのか」だったが、Anthropic がやったのは「その seed を吐くソフトは何か」を逆算することだった。発想を変えると、探すべき痕跡も変わる。英語らしさではなく、1990年代の C ライブラリ特有の出力パターンを追うことになる。

画像: www.anthropic.com より
上: binary 曲線の seed は 48 ビット状態の上位 31 ビット(先頭は必ず 0)。下: prime 曲線の seed は上位 8 ビットだけを 1 バイトとして使う(画像: www.anthropic.com より)

そこで使ったのが、seed を 1 ビットずつずらしながら、隣り合う塊が古いジェネレータの連続出力としてつながるかを試すやり方だ。単に眺めるだけではなく、候補を機械的に照合していく。すると、いくつかの seed で最上位ビットがずっと 0 のままという癖が出た。binary 曲線用の 4 本の seed に含まれる 32 ビット語、計 20 個のすべてでこれが起きる確率は 1/5,810 しかない。ここで lrand48 の名前が浮かぶ。48 ビット状態から上位 31 ビットだけを返すジェネレータなので、上の方のビットに偏りが出る。

この時点で、seed は「しゃれた短文のハッシュ」ではなく、「古い PRNG をそのまま流した断片」に見えてくる。しかも P-256 だけでなく、P-192、P-224、P-384、P-521 まで同じ筋で説明できるというのが決定的だった。

「1,842 番目」が意味すること

P-256 の表に出てくる「1,842」は、lrand48() を呼んだ回数ではない。時刻で初期化した 1 回の実行の中で、乱数から曲線の候補を次々に作っていき、その 1,842 番目の候補が P-256 として採用された、という番号だ。面白いのは、同じ実行の中で 876 番目の候補もすでに素数位数の良い曲線になっていたのに、それは選ばれずに飛ばされていることだ。P-224 の実行でも 3 つ、ANSI X9.62 の 2 回の実行でも計 7 つの「使えたはずの曲線」が素通りされている。

画像: www.anthropic.com より
各サイズの実行で、何番目の候補が採用され(青)、どれが飛ばされたか(橙)(画像: www.anthropic.com より)

なぜ飛ばしたのかは、数字からは分からない。報告も「実行が何回あったかは数字からは読み取れない」と認めている。ただ、少なくとも「狙った曲線が出るまで seed をいじり続けた」ような形跡ではなく、普通の候補列の途中から 1 本を採った姿が見える。

内部状態の戻し方は、曲線の種類で違う。binary 曲線の 4 本は、出力ごとに上位 31 ビットが見えているので、見えていない残り 17 ビット(2¹⁷ 通り)を総当たりし、次の出力が一致するかを確かめれば状態が確定する。一方、P-256 を含む prime 曲線の seed は、出力ごとに上位 8 ビットしか使っていない。見えている情報が少なすぎて総当たりは効かないので、ここで格子の基底簡約アルゴリズム LLL を使い、切り詰められた出力列から 48 ビットの内部状態を復元している。lrand48 は線形合同法なので、出力の一部さえ見えれば状態を代数的に戻せる。復元した状態からは、それぞれの seed の 160 ビット全体が再現できた。

ただし、ここで言えるのは「そう見える」ではなく、「その系列と整合する」というところまでだ。論文や公式文書が生成手順を明言したわけではない。そこは切り分けて読むべきだろう。

時刻まで戻せるが、そこから先は慎重に読む

内部状態が取れれば、srand48 で初期化された形まで逆向きにたどれる。Anthropic の報告では、十個の prime-curve seed は 1997 年 5 月から 1998 年 4 月の Unix 時刻に対応し、binary-curve 側は 1984 年 2 月に対応したという。ここで大事なのは、「時刻で初期化された」と言い切る部分が、単に近そうだからではなく、逆算した状態が時刻の範囲に自然に収まったことにある。

とはいえ、ここには限界もある。srand48 の内部状態が低 16 ビット 0x330E になるのは仕様上そういう形だから、そこに一致すること自体は珍しくない。つまり、一発で「これが証拠だ」とは言えない。意味を持つのは、複数の seed が同じ PRNG で、しかも同じ時期に整列していることだ。単独の一致ではなく、系列全体のまとまりで見る必要がある。

この見方をすると、P-256 の seed は「適当に作ったもの」でも「神秘的なハッシュ」でもない。もっと日常的で、少し拍子抜けするほどの工業製品だ。古い乱数生成器を時計で初期化し、その出力の一部を採って標準化した。疑われがちだった“裏口”の想像とは、逆方向の説明になる。

実務ではどこに効くのか

では、これが今の暗号利用者に何を意味するか。少なくとも、P-256 を含む NIST 曲線が、この種の seed のせいで直ちに危険になった、という話ではない。Anthropic 自身も、これは新しい攻撃ではなく、曲線の安全性を損なうものでもないと述べている。むしろ、意図的な弱点を埋め込んだ可能性は下がった、と読むのが筋だ。

実務で効くのは、設計思想の確認だと思う。曲線を信じる理由が「NSA だから安心」でも「よく分からないから怖い」でもなくなる。どうやって作られたかを追跡できるなら、疑念の中身も整理できる。Web の証明書や一般的な ECDSA 実装を、今すぐ差し替える理由にはならない。むしろ、標準の透明性がどれくらい重要かを示す材料として使える。

自分なら、この話は「曲線の選定理由を説明できるか」を問う場面で使う。暗号の標準を採るとき、性能や普及率だけでなく、生成手順の説明可能性が後から効いてくる。今回の件は、その説明が曖昧でも運用は回る一方、曖昧さが 30 年近く残ることもある、と教えている。

まだ解けていない部分もある

最後に、気持ちよく終わらない部分を書いておく。seed の起源はかなり見えたが、ベースポイント G は別問題だ。P-192 と一部の ANSI X9.62 の曲線については FreeLIP 由来の乱数生成器から追えたが、P-224、P-256、P-384、P-521 の G は説明しきれていない。seed の正体が見えても、曲線の全体像が完全に閉じたわけではない。

だから、この発見は「すべてが解けた」話ではなく、「長年の空白のうち、かなり大きい部分が埋まった」話として読むのが正確だ。疑惑を煽る材料ではなく、疑惑がどこまで妥当だったかを整頓する材料。そこがいちばん価値のあるところだと思う。

同じ著者の記事