暗号の楕円曲線P-256を決める「シード値」は、1997年の時刻を種にした乱数だった|Claudeが突き止めた作り方をMacで再現
Anthropicが、暗号の楕円曲線P-256などを決めた数値の出どころを公表した
AI企業のAnthropicは2026年10月16日、研究記事「Claude reveals ECDSA curve origins」を公開しました。米国の標準規格に載っている暗号用の楕円曲線(P-256など)は、それぞれ「シード値」と呼ばれる20バイトの数値から作られています。このシード値がどうやって選ばれたのかは、規格の公表から25年以上説明がありませんでした。Anthropicによると、同社が社内の研究に使っているAIモデルのClaudeがこの謎を解き明かし、P-256を含む主要な5本のシード値の由来は30分足らずで突き止めました。
答えは、1997〜98年のコンピューターの時計の値(Unix時刻)を種にして、UNIX系のC言語の標準ライブラリにある古い乱数の関数で作った数値でした。P-256の場合は、1997年8月16日の協定世界時1時52分34秒(日本時間10時52分34秒)の時刻を種にして20バイトの数値を次々に作り、1,842番目にできた数値がシード値になっていました。
P-256は、Webサイトの暗号化通信(TLS)の仕様で、すべての実装が対応するよう定められている曲線です(RFC 9846)。この記事では、シード値が謎とされてきた理由、Anthropicが示した作り方とClaudeの調べ方、筆者が手元のMacで、NISTとANSI X9.62という2つの規格に載っている曲線のうち14本のシード値を再現した結果、この発見で変わることを順に説明します。読み終えると、ニュースの意味と、自分のサービスで何をすればよいかを判断できます。
3つの要点
P-256などのシード値は、1997〜98年の時刻を種にした乱数だった
シード値の正体
時刻+古い乱数の関数
C言語の乱数関数lrand48を、1997〜98年のUnix時刻で初期化して作った数値。14曲線で同じ作り方が当てはまった。
見つけたのは
Claudeが主要5本を30分足らずで
古い乱数に特有の偏りから関数を絞り込み、時刻まで逆算した。2023年から懸賞金がかかっていた謎。
利用者への影響
今の設定のまま使える
分かったのは曲線の作り方で、暗号の強さの評価は変わらない。作成者が弱い曲線をこっそり選んだという疑いは大きく薄れた(Anthropicの評価)。候補を飛ばした理由は未解明。
P-256のシード値は、作り方が説明されないまま25年以上使われてきた
楕円曲線は、y² = x³ + ax + b のような式で表される曲線です。電子署名の方式ECDSA(楕円曲線デジタル署名)や鍵の交換では、この曲線上の計算を使います。式の中の係数bの値によって曲線が決まり、選び方によっては安全性の低い曲線も作れてしまいます。
米国立標準技術研究所(NIST)は2000年に、電子署名の規格FIPS 186-2でECDSAを採用し、P-192からP-521までの曲線を定めました。このとき係数bは、20バイトのシード値をハッシュ関数SHA-1で変換して作る方式でした。ハッシュ関数は、入力から決まった出力を作る一方で、狙った出力になる入力を逆算するのが事実上できない計算です。シード値さえ公開すれば誰でもbを計算し直せるため、係数bが作成者の手で直接選ばれず、シード値から機械的に決まったことを確かめられる、という考え方です。
ところが、シード値そのものは米国家安全保障局(NSA)から提供されたもので、どう選んだのかは説明されていませんでした。作成者がシード値を大量に試し、自分だけが知る弱点を持つ曲線を選んだ可能性がある、という疑いが残ったのはこのためです。
シード値をめぐる経緯
1997年5月〜1998年4月
シード値が作られる。今回の分析で、乱数を作り始めた時刻がこの期間に収まると分かった。
2000年
NISTが規格FIPS 186-2でECDSAとP-256などの曲線を採用。シード値の選び方の説明はなかった。
2023年
シード値を作ったとされるNSAのJerry Solinas氏が死去。10月に、暗号技術者のFilippo Valsorda氏らがシード値の元を見つけた人への懸賞金を用意した。
2026年10月16日
Anthropicが、Claudeの特定したシード値の作り方を公表。Anthropicによると、懸賞金はLet's Encryptの運営団体へ寄付される。
2023年の懸賞を企画したFilippo Valsorda氏の告知には、当時有力だった説が書かれています。Solinas氏は英語の文(Anthropicの記事によると冗談めいたフレーズ)をハッシュしてシード値を作ったものの、使っていたパソコンを入れ替えたときにその文を失った、という話です。懸賞は、ハッシュする前の元の入力(シード値の元)を見つけた人に賞金を払う内容で、総額は1万2,288ドル、慈善団体へ寄付する場合は3倍の3万6,864ドルでした。
Anthropicの調査で、元の文をハッシュしたという説は外れていたと分かりました。シード値はハッシュの出力ではなく、乱数の関数がそのまま出した数値でした。
シード値は「時刻を種に乱数を作り、何番目かの候補を選ぶ」方法で作られていた
Anthropicが示した作り方は、次の3段階です。使われた関数lrand48は、UNIX系のC言語の標準ライブラリに含まれる乱数の関数で、同じ種(初期値)から始めると毎回同じ順番で数値を出します。
P-256のシード値ができるまで
1. 時刻を種にする
1997年8月16日 1:52:34(UTC)
その時点のUnix時刻871696354を、関数srand48に渡して乱数の初期値にする。
2. 候補を順に作る
20バイトずつ
lrand48を20回呼び、出力の上位8ビットを1バイトとして並べると、候補が1つできる。これを繰り返す。
3. 候補から選ぶ
1,842番目を採用
1,842番目の候補が、規格に載ったシード値C49D3608…7E90と一致する。これをSHA-1で変換して係数bを作る。
曲線には、計算の土台になる数の種類によって、名前がP-で始まる「素体曲線」とB-で始まる「2進体曲線」の2系統がある。2進体曲線(B-233など)では、出力の31ビットをそのまま4バイトずつ5個並べ、時刻は2で割った値を種にしていた。出典: Anthropic
14曲線のうち、P-192とANSI X9.62規格の例示用の曲線(prime192v2、v3)は同じ1997年5月18日の時刻から、prime239v1〜v3の3本は5月15日の時刻から作られていました。1回の実行で複数の曲線のシード値を取り出していたことになります。採用された候補が1番目ではなく、数十番目から7,000番目以上まで幅がある点は、後半の「まだ説明がつかないこと」で取り上げます。
Claudeは、古い乱数の関数に特有の偏りからシード値の作り方を逆算した
Anthropicの社員が社内の研究用のClaudeに「シード値の元を見つけられるか」と尋ねたところから調査が始まりました。それまで多くの人が試していたのは、元の英文を推測してハッシュする方法です。Claudeは方針を変え、シード値は、出力から内部の状態を逆算できてしまう1990年代の乱数の関数(暗号には向かない種類)の出力そのものだという仮説を立て、その関数に特有の痕跡を探しました。
Claudeが答えにたどり着いた4つの手順
1. 乱数の関数と取り出し方を総当たり
古い乱数の関数と、出力のどの部分を使うかの組み合わせ34通りについて、シード値がその関数を続けて呼んだ出力を並べたものとして説明できるかを調べた。
2. 偏りからlrand48に絞る
NISTの規格の10曲線(P-192〜P-521とB-163〜B-571)のシード値を4バイトずつ5個の値に区切ると、2進体曲線4本(B-233〜B-571)で計20個の値すべての先頭の1ビットが0だった。10本中4本以上がこうなる確率は、Anthropicの計算で偶然なら約5,810分の1。31ビットの値を返すlrand48の特徴と合う。
3. 隠れた内部状態を復元
lrand48は48ビットの内部状態のうち31ビットしか見せない。31ビットがそのまま並ぶ2進体曲線では残る17ビットを総当たりし、上位8ビットしか使わない素体曲線では格子と呼ばれる数学の手法で状態を割り出した。
4. 初期値まで巻き戻す
状態を逆向きにたどると、srand48で初期化した形(下位16ビットが0x330E)に行き着き、上位の値が1997〜98年のUnix時刻になった。
Anthropicによると、NISTの素体曲線5本のシード値の由来を突き止めるまでにかかった時間は30分足らずでした。復元した内部状態からシード値の160ビットすべてを再生成できることが、偶然では起きない一致の根拠になっています。巻き戻した先の種が、どれも1997〜98年の現実的な時刻に収まったことも裏付けの一つです。Claudeはさらに、曲線上の計算の出発点として規格に定められた点(基準点、ベースポイント)について、P-192など6曲線の基準点が、当時の数論ライブラリFreeLIPの乱数で作られたことも突き止めました。
Anthropicの説明によると、この調査では答えにたどり着くまでの方針の切り替えが決め手になりました。人が何年も「失われた英文」を探していたのに対し、Claudeはシード値に残った統計的な偏りを手がかりに、問いを「どの関数のどの出力か」に置き換えました。研究者に問いを渡すと、AIが仮説を立て、総当たりの検査プログラムまで作って確かめる、という研究の進め方が具体的に分かる事例です。
公表された時刻と候補の順番から、手元のMacで14曲線すべてのシード値を再現できた
Anthropicの説明が正しければ、時刻と候補の番号だけでシード値を作り直せるはずです。筆者は2026年10月20日、MacBook(Apple M4、macOS 27.0.1)で、Python 3.9の標準機能だけを使ってlrand48を自作し、確かめました。比べる相手は、暗号ライブラリOpenSSL 3.6.3に収録されている各曲線の公式のシード値です。Anthropicが公開している再現用のコードは使わず、乱数の関数の公開された定義から書き起こしました。
# lrand48 の定義(48ビットの線形合同法)を自作したもの
A, C, M = 0x5DEECE66D, 0xB, 1 << 48
class Rand48:
def __init__(self, seed): # srand48: 上位32ビットに種、下位16ビットに0x330E
self.x = ((seed & 0xFFFFFFFF) << 16) | 0x330E
def lrand48(self):
self.x = (A * self.x + C) % M
return self.x >> 17 # 48ビットの状態の上位31ビットを返す
# P-256: 1997-08-16 01:52:34 UTC = Unix時刻 871696354 から作った1,842番目の候補
r = Rand48(871696354)
for n in range(1, 1843):
cand = bytes((r.lrand48() >> 23) & 0xFF for _ in range(20)).hex().upper()
print(cand) # C49D360886E704936A6678E1139D26B7819F7E90
同じ手順を14曲線すべてに当てはめると(2進体曲線は上の注記の取り出し方と、2で割った時刻を使用)、結果は次の表のとおりで、全件がOpenSSLの値と一致しました。素体曲線10本については、規格に定められた、シード値をSHA-1で変換して係数bを確かめる計算でも、一致したシード値が規格の係数bと整合しました。1曲線あたりの計算は0.01秒程度で終わります。
| 曲線 | 乱数を作り始めた時刻(UTC) | 採用された候補の順番 | OpenSSL収録値との照合 |
|---|---|---|---|
| P-192 | 1997-05-18 14:45:34 | 139 | 一致 |
| P-224 | 1998-04-03 12:52:07 | 7,026 | 一致 |
| P-256 | 1997-08-16 01:52:34 | 1,842 | 一致 |
| P-384 | 1997-08-30 14:50:08 | 2,688 | 一致 |
| P-521 | 1997-08-08 01:12:04 | 1,136 | 一致 |
| B-233 / B-283 / B-409 / B-571 | 1998-04-17 15:24:18 / 15:27:44 / 15:30:18 / 15:32:08(いずれも時刻を2で割って使用) | 155 / 32 / 60 / 73 | 4本とも一致 |
| prime192v2 / v3 | 1997-05-18 14:45:34(P-192と同じ) | 6,013 / 5,228 | 2本とも一致 |
| prime239v1 / v2 / v3 | 1997-05-15 15:49:03 | 2,185 / 2,320 / 3,048 | 3本とも一致 |
時刻と番号はAnthropicの公表値。照合は筆者が2026年10月20日に、自作のlrand48とOpenSSL 3.6.3収録のシード値で実施。
照合のプログラムがどんな入力にも一致を返していないかを確かめるため、条件を少しだけ変えた場合も試しました。
時刻が1秒ずれると、公式のシード値は出てこない
公表どおりの時刻
1,842番目で一致
P-256。それより前の候補に同じ値は現れない。
時刻を±1秒ずらす
2万個中0件
P-256とP-384で、2万番目までの候補に公式の値が一度も現れない。
B-233で時刻を2で割らない
2万個中0件
2で割った時刻を種にした場合だけ、155番目で一致する。
種となる時刻が1秒違うだけで、まったく別の数値の列になります。公表どおりの時刻では公表どおりの番号で一致し、時刻を1秒ずらすと2万番目までの候補に一度も現れないことを、手元の計算でも確かめられました。

この発見で薄れるのは曲線への疑いで、使っている暗号の設定はそのままでよい
Anthropicは、今回の成果を曲線の作り方を明らかにしたものと位置づけ、暗号の破り方や新しい攻撃方法は含まれず、利用者が対応すべきことや変えるべきことはないと書いています。さらにAnthropicは、シード値が誰でも再現できる単純な手順から作られていたことから、曲線に意図的な裏口が仕込まれた可能性は大きく下がったと評価しています。
今回分かったこと
- 14曲線のシード値は、1997〜98年の時刻を種にしたlrand48の出力
- P-192など6曲線の基準点は、数論ライブラリFreeLIPの乱数から作られた
- 利用者が設定を変える必要はない(Anthropicの説明)
まだ説明がつかないこと
- 2進体曲線B-163のシード値
- P-224、P-256、P-384、P-521と2進体曲線の基準点の作り方
- 前の候補が使われなかった理由(P-256では、876番目の候補からも規格に使える曲線を作れる)
疑いの中心は、シード値の用意の仕方を誰も確かめられない点でした。今回、乱数の種になった時刻と採用された順番まで特定でき、作り方そのものは誰でもたどれるようになりました。3つ目の「前の候補が使われなかった理由」は、疑いを完全に消すうえで残る論点です。Anthropicは、弱い曲線を選ぶために候補を選別したとは考えていないとしたうえで、選別の基準や、乱数を何回作り直したかは分かっていないと書いています。暗号の専門家が今後この点をどう評価するかは、続報として注目できます。
Anthropicは、懸賞金3万6,864ドルが、無料の証明書サービスLet's Encryptを運営する非営利団体ISRGへ寄付されると説明しています。Anthropicの研究記事の末尾には再現用のコードが掲載されており、誰でも自由に使えるパブリックドメイン(CC0 1.0)として公開されています。
Webサービスの開発者と、AIの研究利用に関心がある人が次にできること
自分のWebサイトやアプリでP-256を使っている場合、今回の発表を理由に設定を変える必要はありません。TLSの仕様(RFC 9846)でもP-256は引き続き、用途ごとの取り決めで別に定めない限りすべての実装が対応する曲線で、Anthropicも利用者の対応は不要としています。
シード値の作り方を自分の目で確かめたい場合は、この記事のコードのように、時刻と番号から20行ほどのPythonで再現できます。OpenSSLが入ったMacやLinuxなら、openssl ecparam -name prime256v1 -param_enc explicit -text -noout の出力の最後に、比べる相手になるP-256のシード値が表示されます。
AIの研究利用という面では、Anthropicの説明どおりなら、25年以上説明のなかったシード値の由来の大部分を、AIが仮説の立て直しと検査プログラムの作成によって短時間で突き止めた事例として読めます。調査の過程はAnthropicの社内記録に基づくもので、筆者が手元で確かめたのは、公表された時刻と番号からシード値を再現できる点です。調査の詳しい手順と未解明の点は、Anthropicの研究記事にまとまっています。












