冗談まじりのハッシュではなくタイムスタンプだった — NIST P-256シードの出自と、解けたもの・解けていないもの

25年来のシードの出自が明らかになった。これはP-256への疑いに終止符を打つ証明なのか、それとも疑いの置き場所を移しただけの説明なのか?

導入

2026年10月16日、AnthropicのFrontier Red Teamは「Claude reveals ECDSA curve origins」という記事を公開した。Hacker Newsでは1,000ポイントを超えた。要点は一行で言える。NIST P-192、P-224、P-256、P-384、P-521の曲線係数を決めるのに使われた20バイトの「シード」は、何かの文のハッシュではなく、Cライブラリの lrand48 乱数生成器をUnixタイムスタンプで初期化して取り出した出力だった、というものである。

これらのシードはNSAが出自の説明なしに提供した値であり、だからこそ長く疑いの対象になってきた。たとえばP-256のシードは C49D3608 86E70493 6A6678E1 139D26B7 819F7E90 である。なぜこの値なのか。この問いに対するこれまでで最ももっともらしい答えは、故Jerry Solinas本人の回想、つまり「BobとJerryの給料を上げてくれ」のような冗談の文をハッシュしたという話だった。その話は誤りだったことになる。

発表文は自ら「暗号学的な破り方でも新しい攻撃でもない」と断言し、むしろ曲線にバックドアがないという確信を強めると述べる。本稿では三つを分けて見る。正確には何が見つかったのか、それはどう検証できるのか、そしてその結果はP-256への信頼をどこまで変えるのか。最後の問いについて、発表文とHacker Newsの反論は同じ文を別様に読んでいる。

現象の分析 — 何が見つかったのか

まず背景を整理する。Steve Weisが2023年9月にまとめた記事によれば、ECDSAは1999年のANSI X9.62に始まり、2000年にFIPS 186-2としてNISTに採用された。素体上の曲線ごとに「シード」を公開し、そのハッシュ値で曲線係数を決める方式である。当時X9.62の主著者だったAlfred Menezesは、Weisに対して「Jerry Solinasが1997年秋にシードを渡してくれた」と答えている。Weisは2018年にNISTとNSAへ情報公開請求も出したが、NISTは文書がないと回答し、NSAは返答をやめたと書いている。

その後2023年10月、Filippo Valsordaがこのシードの「原文」を見つけた者に懸賞金をかけた。基本額は12,288ドル、受取人が慈善団体への寄付を選べばその3倍の36,864ドルである。懸賞金の告知もまた「英語の文をSHA-1でハッシュした」という噂を前提に、パスワードクラッカーたちに参戦を呼びかける内容だった。懸賞金ページには、対象となった五つのNIST素体曲線のシードと、対象外のANSI例示曲線および二進曲線のシード一覧が併せて載っている。

Anthropicの発表文によれば、Anthropic社員の何人かも「冗談の文」という手がかりを追って失敗していた。2026年10月、ある社員が内部の研究用モデルに、その手がかりを示さずにシードがどう生成されたか突き止められるかと尋ね、Claudeは30分足らずで五つのNIST素体曲線シードの出自を見つけたという。

発表文が説明する経路は次のとおりである。

  • アプローチの転換。 文を推測する代わりに、曲線を作ったソフトウェアがどう動いたかを推定した。1990年代のCライブラリに付属していた擬似乱数生成器(PRNG)は弱く、出力を見るだけでどの生成器か識別できる、という仮定である。
  • スキャナ。 公開シードを1ビットずつずらしながら、隣り合う断片が1990年代の生成器の連続出力かどうかを試した。生成器と出力スライスの組み合わせ34通りを調べた。
  • 最上位ビットのパターン。 32ビットワード五つとして書くと、シード十個のうち四つは20ワードすべての最上位ビットが0だった。偶然に起きる確率は5,810分の1である。48ビット状態のうち上位31ビットだけを返す lrand48 の指紋だ。最初のワードから隠れた17ビットを総当たりし、続く四ワードが合うかを確かめた(発表文の再現コードを見ると、この四つは二進曲線B-233、B-283、B-409、B-571である)。
  • 素体曲線は格子問題として。 素体曲線のシードは同じ lrand48 から出ていたが、出力ごとに残すビットが少なかった。切り詰められた線形合同法の状態復元は教科書的な格子問題であり、LLL基底簡約で解いた。結果、NISTの五つとANSI X9.62の五つがすべて lrand48() >> 23 のパターンだった。
  • 時計まで巻き戻す。 線形合同法は逆方向にも簡単に回せる。状態を巻き戻して srand48 が作る形(下位16ビットが 0x330E)に到達させると初期値が得られる。その値は1997年5月から1998年4月のあいだのUnixタイムスタンプだった。

たとえばP-256は、1997年8月16日01:52:34(UTC)で初期化した生成器から20バイトずつ取り出した1,842番目の候補である。P-192は1997年5月18日の139番目、P-224は1998年4月3日の7,026番目だ。

副産物もある。発表文は、1997年5月に作られた六つの曲線(P-192とANSI例示曲線五つ)のベースポイントGが、Arjen LenstraのFreeLIPパッケージの乱数生成器から出ていたことも明らかにした。小さな整数(P-192なら20000)で初期化し、出力を七つ捨て、曲線上に乗るxが出るまで候補を作る方式である。発表文は、これまでに説明されたNISTのベースポイントはなかったと認識していると書く。

深層分析 — 主張と検証を切り分ける

この件の面白さは、「AIがやった」という主張と「結果が正しい」という主張が互いに独立している点にある。前者はAnthropicの記述にしか依拠しない。後者は誰でも確かめられる。

誰でも回せる検証

発表文はCC0で再現コードを公開している。核心は次の数行だ。

def candidate(t, n, per, shift, width):
    x, out = (t << 16) | 0x330E, ""           # srand48(t) が作る状態
    for i in range(per * n):
        x = (0x5DEECE66D * x + 0xB) % 2**48    # lrand48 の1ステップ
        if i >= per * (n - 1):
            out += "%0*X" % (width, x >> shift)
    return out

筆者はこの関数で五つのNIST素体曲線シードを再生成し、Anthropicの記事ではなくValsordaの懸賞金ページに載ったシード一覧と照合した。五つとも一致した。対照として、タイムスタンプを1秒増やすか候補番号を一つ増やすと、五つとも不一致になった。つまり「与えられたタイムスタンプと番号から公開シードが正確に出てくる」という事実は、実行によって確認できる。

偶然の一致ではありえないか

Hacker Newsで最も鋭い懐疑論はこれである。ユーザーezoeは、線形合同法は1990年代でも品質の悪さで悪名高かったのになぜそれを使うのか、タイムスタンプの日付はなぜこれほどまばらなのか、候補番号139や7,026にどんな意味があるのかと問い、Claudeが偶然20バイトの一致を引き当てただけではないかと疑った(直接の引用ではなく、コメントの要旨の要約)。ユーザーgreatgibも、ハッシュ衝突のような偶然ではないのかと問うた(直接の引用ではなく、コメントの要旨の要約)。

この疑問には情報量で答えられる。以下は筆者の計算である。探索空間はおおよそ32ビットのタイムスタンプと数千単位の候補番号、それに数十通りの生成器・スライスの組み合わせだ。多めに見積もっても2の50乗程度の候補である。その中で特定の160ビット値が偶然出る確率は2のマイナス110乗程度であり、それが十回独立に起きなければならない。発表文に載ったClaudeの推論ログも同じ論理を使っている。「32ビットのシードと小さなインデックスから160ビット一致、偶然はありえない(10 × 160ビット)」。

ただし発表文は、弱い証拠と強い証拠を自ら区別している。srand48 形の状態は65,536ステップに一度は現れるので、巻き戻してその形に行き着いたこと自体は証拠にならないと明記している。強い証拠は、そうして得た値がすべて1997〜1998年の日付として読めることだ。そしてこれは独立した記録と噛み合う。Menezesは、Solinasが1997年秋にシードを渡したと証言している。ランダムな32ビット値十個がすべてその1年に収まることはありえない。

一方、固くない部分もある。二進曲線四つの初期値はそのまま読むと1984年2月だが、2倍すると1998年4月17日、P-224の実行の2週間後になる。発表文は「プログラムが時計を半分にしていた可能性がある」と書き、再現コードのコメントでも「その解釈が正しければ」という留保を付けている。出力の一致は事実だが、「なぜ半分にしたのか」は推測である。

「人の記憶」が誤っていた場所

もっと静かだが重要な事実がある。Solinasは2014〜2015年にDaniel Bernsteinへ送ったメールで、「SHA-1だったと思う」「多重ハッシュではなくカウンタだったと思う」「Give Bob and Jerry a raiseのような文だった」と回想している。Weisは似た話を聞いた人物を複数探し出し、裏付けまで取った。ところが計算は、ハッシュそのものがなかったと言う。複数の一致した証言が、一つの誤った記憶を繰り返していたわけだ。懸賞金ページも「人の記憶は悪名高く当てにならない」と注記していたが、攻略側の戦略そのものはその記憶を前提に組まれていた。

「Claudeがやった」という部分

この部分は検証が難しい。Hacker Newsのandyjohnson0は、Claudeが成功の方向へどの程度誘導されたのかを問うた(直接の引用ではなく、コメントの要旨の要約)。発表文は「手がかりを示さずに」尋ねたとだけ書き、プロンプト原文は公開していない。ユーザーnullcは、9月に友人のAnthropicクレジットで同じ問題を任せたところ、エージェントは何時間も動いて何も見つけられなかったと書いた(直接の引用ではなく、コメントの要旨の要約)。これは公開モデルと「内部研究用モデル」の差かもしれないし、プロンプトや運用の差かもしれない。どちらなのかは公開資料からは判断できない。また発表文の著者リストには、懸賞金のきっかけとなった調査をしたSteve Weisと、懸賞金の拠出者リストにあったAmir Omidiが含まれている。この問題を長く知っていた人々が運用したという事実は、結果の真偽には影響しないが、「手がかりなしで」という表現の重みを読むときには考慮に値する。

展望と示唆 — P-256への信頼はどこへ移るのか

発表文の結論は「曲線がバックドアなしに選ばれたという確信が強まる」である。Hacker Newsで最も多く反論されたのもこの一文だった。

ユーザーadastra22は、これはむしろ弱い曲線がまさにどう見えるかを示していると反論した。秘密の攻撃に弱い曲線が千個や百万個に一つなら、タイムスタンプや反復回数を変えながら探し、もっともらしい否認の余地を残せる。現代の設計が2の平方根のような自由度のない定数を使うのはそのためだ、と付け加えている(直接の引用ではなく、コメントの要旨の要約)。ユーザーfidotronは、生成方法は確認されたが選択については何も語っておらず、捨てられた候補は見えないと指摘した(直接の引用ではなく、コメントの要旨の要約)。

興味深いことに、この反論の材料は発表文自身の中にある。P-256の公開シードは1,842番目の候補だが、同じ実行の876番目の候補も、同じ方式の条件を満たす素数位数の曲線を与える。P-224の実行はそうした曲線を三つ、ANSI例示曲線の二つの実行はさらに七つを飛ばしていた。発表文はその基準を知らないと認め、理論上はタイムスタンプを変えながら特定の性質を持つ曲線を選べたことも認める。そのうえで、飛ばされた候補は少ないので、弱い曲線がありふれていて見つけやすい場合にしか成り立たないシナリオであり、もっともらしくないと見ている。

この論争を整理するにはSafeCurvesの「剛性(rigidity)」分類が役に立つ。SafeCurvesは曲線生成プロセスを四段階に分ける。すべての選択が説明される「fully rigid」、説明されない部分が小さい「somewhat rigid」、説明されない大きな入力があり生成者が広い空間から選べる「manipulatable」、そして逆算まで容易な「trivially manipulatable」である。SafeCurvesはNIST P-256を「説明のないシードをハッシュして係数を生成」しているという理由でmanipulatableに分類している。一方Curve25519は、素数2の255乗マイナス19を選んだ理由から、係数A=486662が条件を満たす最小の正整数であることまで、各選択に根拠が記されておりfully rigidに分類される。

今回の発見が変えたのは、「説明のない大きな入力」の性格である。以前は160ビットのシードがまるごと未知だった。いまやそのシードは、32ビット程度のタイムスタンプと数千単位の候補番号に還元される。これは確かに自由度を減らす。しかし「誰が何回回したのか」は依然として説明されない。発表文の言うとおり、数字だけでは実行が何回あったかはわからない。SafeCurvesの基準で見れば、P-256がmanipulatableを脱したとは言いにくい。それでも「NSAが160ビットの空間から好きに選べたかもしれない」という最も強い疑いは、「1997年の数か月間の実行の中から選べたかもしれない」まで縮んだ。

ここで逆方向の論拠も併せて読む必要がある。Valsordaは懸賞金告知でKoblitzとMenezesの議論を引いている。シードを完全に支配できたとしても、NSAは25年間学界と産業界の誰も見つけられないほど大きな弱い曲線のクラスを知っていなければならなかった、というものだ。彼はさらに、剛性そのものが過大評価されており、客観的に最善の選択などないと脚注に書いている。この立場から見れば、今回の結果は「もともと信頼に足る曲線に残っていたFUDを払った」ものである。発表文が「ほとんどの研究者はすでに曲線を信頼していた」と書いたのも同じ立場だ。

したがって実務上の含意は大きくない。発表文自身が「取るべき対応はない」と書いている。残る未解決課題も明示されている。二進曲線B-163のシードはどの方法にも当てはまらない。P-224、P-256、P-384、P-521のベースポイントと、NIST二進曲線のベースポイントがどう決められたのかもわかっていない。Hacker Newsのteddyhは、B-163も同じ方式で作られたが公開の過程で数字が一つ誤って写された可能性を示した(直接の引用ではなく、コメントの要旨の要約)。検証されたわけではない。

結論

今回の発表で確かなことは一つである。公開された再現コードは実際に動き、1997〜1998年のタイムスタンプと候補番号から五つのNIST素体曲線シードがビット単位で正確に出てくる。筆者も懸賞金ページの独立したシード一覧と照合して確認し、1秒ずれるだけで一致しないことも確かめた。偶然の一致である可能性は実質的にない。「冗談の文のハッシュ」という25年来の通説は誤りだった。

確かでないことも、はっきり残っている。二進曲線の「半分にした時計」は解釈である。飛ばされた候補の選択基準はわからない。実行が何回あったかもわからない。「手がかりなしで30分」という記述はAnthropic側の説明であり、外部で再現されたものではない。

では、P-256は信頼に足るものになったのか。正確に言えば、疑いの置き場所が移った。「出自不明の160ビット」から「出自はわかるが選択基準がわからない、いくつかの候補」へ。この移動は意味のある前進だが、最初からすべての選択の根拠を書き残したCurve25519のような設計と同じ場所に立たせてくれるわけではない。その差は数学ではなく記録の差である。1997年に誰かが「タイムスタンプはこれで、この基準で選んだ」という一行を残していれば、この25年は要らなかった。

あなたのチームが今日、何かの定数やパラメータを「適当に」選ぶとき、その理由をどこに書き残しているだろうか。


出典: