Claude Traced the NIST P-256 Curve Seeds to 1997 Timestamps

Executive Summary
- The mystery: the NIST elliptic curves in FIPS 186-2 (2000), including P-256, were generated from "seeds" the NSA supplied with no explanation. That gap fed 26 years of backdoor suspicion.
- The answer: on October 16, 2026, Anthropic's Frontier Red Team reported that Claude traced the seeds of all five prime curves in under half an hour. They are not hashes. They are output of the C library's
lrand48generator, seeded with Unix timestamps from May 1997 to April 1998. - P-256: candidate #1842 from a run seeded at 1997-08-16 01:52:34 UTC.
- I checked it: Anthropic published the code under CC0. I ran it, and it reproduces all five published prime-curve seeds byte for byte.
- What it means: it is not a break of ECDSA or a new attack. Anthropic says it makes a hidden backdoor much less plausible. Some parts are still unexplained.
I made a short video of this on X; this post has the details and the code.

A 26-year crypto mystery, solved in under 30 minutes
Where the mystery came from
Each NIST prime curve is defined by a few numbers. One of them, b, was derived from a 160-bit SEED run through SHA-1, so that anyone could check the curve was not hand-picked. The catch: nobody explained where the seeds themselves came from. They were supplied by the NSA, and the long-standing rumour was that Jerry Solinas had hashed a humorous passphrase. Anthropic's post says that theory turned out to be wrong. Solinas died in 2023, and the seeds stayed a mystery, with a public bounty of $36,864 for anyone who could explain them.

Illustration: the P-256 SEED in FIPS 186-2, with the open theories
How Claude found it
From Anthropic's write-up, the steps were:
- A hunch: an internal research model was asked how the seeds were made, without being given the passphrase story. It guessed a weak pseudorandom generator from a 1990s C library.
- A scanner: it wrote a scanner that slid along each seed one bit at a time and tested whether neighbouring chunks could be consecutive outputs of such a generator, across 34 generator and output-slice combinations.
- The tell: in four of the ten NIST seeds, the top bit of every 32-bit word was 0. That is the signature of
lrand48, which returns only the top 31 bits of a 48-bit state. - Recovering the state: for those seeds it brute-forced the 17 hidden bits of the first word and checked the next four words. The prime-curve seeds keep fewer bits per output, so it used LLL lattice reduction to recover the hidden state.
- Back to a timestamp: stepping each recovered state backwards until it had the shape
srand48produces (low 16 bits0x330E) gave a Unix time. The prime seeds landed between May 1997 and April 1998. The binary-curve seeds read as February 1984, and doubled they give April 17, 1998, so the program may have halved the clock.

Illustration: the top bit is 0 in every word of the B-233 seed
Reproduce it yourself
lrand48 is a 48-bit linear congruential generator: x = 0x5DEECE66D * x + 0xB mod 2^48, and srand48(t) sets the state to (t << 16) | 0x330E. For the prime curves each candidate seed is 20 calls, keeping the top 8 bits of the state each time (lrand48() >> 23).
This is Anthropic's function (CC0). I added the loop and the published seeds:
import calendar, time
def candidate(t, n, per, shift, width):
x, out = (t << 16) | 0x330E, "" # the state srand48(t) sets
for i in range(per * n):
x = (0x5DEECE66D * x + 0xB) % 2**48 # one step of lrand48
if i >= per * (n - 1):
out += "%0*X" % (width, x >> shift)
return out
CURVES = [ # curve, seeding time (UTC), candidate, published FIPS 186-2 SEED
("P-192", "1997-05-18 14:45:34", 139, "3045AE6FC8422F64ED579528D38120EAE12196D5"),
("P-224", "1998-04-03 12:52:07", 7026, "BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5"),
("P-256", "1997-08-16 01:52:34", 1842, "C49D360886E704936A6678E1139D26B7819F7E90"),
("P-384", "1997-08-30 14:50:08", 2688, "A335926AA319A27A1D00896A6773A4827ACDAC73"),
("P-521", "1997-08-08 01:12:04", 1136, "D09E8800291CB85396CC6717393284AAA0DA64BA"),
]
for name, when, n, published in CURVES:
t = calendar.timegm(time.strptime(when, "%Y-%m-%d %H:%M:%S"))
seed = candidate(t, n, per=20, shift=40, width=2)
print(name, t, seed, "match" if seed == published else "NO MATCH")python3 nist_seeds.pyAll five lines print match. For P-256 the seeding call is srand48(871696354), which is 1997-08-16 01:52:34 UTC.
The binary curves use the full 31-bit output in five 32-bit words and a halved timestamp. B-233, for example, is candidate(446413329, 155, per=5, shift=17, width=8), where 446413329 is half the Unix time of 1998-04-17 15:24:18 UTC. It returns 74D59FF07F6B413D0EA14B344B20A2DB049B50C3, the published seed.

Illustration: the clock rewinds to 1997 and candidate #1842 matches the P-256 seed

Anthropic's code reproduces all five prime-curve seeds
What it means, and what it does not
- Not a break. Anthropic is explicit: this is not a cryptographic break, a new attack or a weakness in the ECDSA curves. Nothing changes for your P-256 keys or TLS certificates.
- Less room for a backdoor. A seed that comes out of a plain, reproducible process leaves much less room for a hidden, hand-picked weakness.
- Still open. The B-163 seed is unexplained. So are the base points of P-224, P-256, P-384, P-521 and the binary curves. Some valid candidates were skipped (for P-256, candidate #876 also gives a valid curve) and nobody knows why. Anthropic says the number of skips is small, but it cannot tell how many runs there were.
- The bounty. The $36,864 goes to the Internet Security Research Group, the nonprofit behind Let's Encrypt.
My take: the interesting part for security teams is not the answer, it is the method. A model formed a hypothesis, wrote its own scanner, spotted a statistical tell and reached for lattice reduction, in under half an hour. That is the same loop we run on firmware, protocols and leaked keys.

What it means: not a break, a backdoor far less plausible
Sources
- Claude reveals ECDSA curve origins (Anthropic Frontier Red Team, October 16, 2026), with the CC0 code
- Claude traces NIST P-256 seed to a 1997 random number generator run (Crypto Briefing)
- Unite.AI coverage
- Internet Security Research Group, the bounty's recipient
Comments
Share your thoughts and join the conversation



