The elliptic curve P-256, widely used in website certificates and passkeys, contained one number of unknown origin It is the 20-byte seed provided by the US National Security Agency (NSA)

On October 16, Anthropic revealed that this number was a random number seeded with a 1997 timestamp The output of its published reproduction code matched the seed value in the standard

Curve P-256 parameters and SEED value from the FIPS 186-4 appendix, highlighted Curve P-256 parameters and SEED value from the FIPS 186-4 appendix, highlighted — Source: NIST

Why the seed was suspected

Concept shot of examining a mysterious number seed through a magnifying glass Concept shot of examining a mysterious number seed through a magnifying glass — Source: concept shot · self-generated with agy

An elliptic curve is defined by an equation of the form y² = x³ + ax + b In P-256, the coefficient b is made from the value obtained by applying the SHA-1 hash function to the seed

It is hard to work backward from a hash value to the original input So once the seed is fixed, it is hard to choose b arbitrarily

A number that proves there was no tampering by showing its origin is called a nothing-up-my-sleeve number

The problem was that there was no public material explaining how the seed itself was chosen

NIST included the P-192 to P-521 curves in FIPS 186-2 in 2000 The seeds the NSA provided were printed as is, without explanation

By repeatedly changing the seed and computing the hash, you could pick a curve with particular properties This suspicion grew after the 2013 allegations of an NSA backdoor in Dual_EC_DRBG

NSA mathematician Jerry Solinas reportedly said in 2015 that the seeds were hashes of a joke phrase With his death in 2023, it became hard to confirm directly with him

A bounty was even offered to whoever found the seed

A random number generator called lrand48

The answer was not a hash It was the output of lrand48, a random number function provided by C libraries in the 1990s

lrand48 is a linear congruential generator (LCG) It keeps updating a single 48-bit state value with the formula below

Xₙ₊₁ = (25,214,903,917 × Xₙ + 11) mod 2⁴⁸

The starting state is set by srand48(t) It shifts the time t (seconds counted from January 1, 1970) left by 16 bits and fills the low 16 bits with 0x330E

🔢 How the P-256 seed came out

The starting value is 01:52:34 UTC on August 16, 1997 In Korean time, that is 10:52:34 a.m.

That time converted to seconds, 871,696,354, is t

Each time the state is updated, the top 8 bits are taken and used as one byte Collecting 20 bytes gives one seed candidate

The P-256 seed was the 1,842nd candidate of this run, by which point lrand48 had run 36,840 times

Bar chart comparing which candidate in each run the published seeds of the five NIST prime-field curves were Bar chart comparing which candidate in each run the published seeds of the five NIST prime-field curves were — Source: self-rendered based on running Anthropic’s reproduction code

All 10 prime-field curve seeds were seeded with times between May 1997 and April 1998 P-224 was the 7,026th candidate of a run on April 3, 1998

How Claude found it

An Anthropic employee asked an internal research model about the seed’s origin without giving it the joke-phrase clue Claude found the origin of the five NIST prime-field curve seeds in under 30 minutes

🔍 The top bits were all 0

Claude first wrote a scanner looking for traces of 1990s C library random number generator output It checked 34 combinations of generator and output truncation method against the seeds, shifting one bit at a time

Splitting each seed into five 32-bit words, in 4 of the 10 seeds the leading bit of all 20 words was 0 The probability of that happening by chance is 1 in 5,810

lrand48 returns only the top 31 bits of its 48-bit state, so the leading bit of a 32-bit word is always 0

It tried all 2¹⁷ = 131,072 possibilities for the 17 unknown bits The following words then matched the generator’s output

🧮 The LLL lattice algorithm

The prime-field curve seeds kept only some bits of the output, so the method above didn’t work The problem of recovering an LCG’s internal state from truncated output can be solved as a lattice problem

Claude recovered the state with the LLL (Lenstra–Lenstra–Lovász) basis reduction algorithm All 5 NIST seeds and all 5 ANSI X9.62 seeds were of the form lrand48() » 23

Since an LCG can be run backward to earlier states, it traced back to the point where the low 16 bits were 0x330E Reading the upper 32 bits at that point as a date gave times in 1997–1998 for all of them

All 10 seeds matching the same generator with plausible dates is hard to explain as coincidence

Running the reproduction myself

Terminal regenerating the seeds of the five NIST prime-field curves by running Anthropic's published code Terminal regenerating the seeds of the five NIST prime-field curves by running Anthropic’s published code — Source: Anthropic’s published code, run by me

Anthropic released the reproduction code under CC0 (public domain) Running it on Python 3.14 finished in under 0.2 seconds

I compared the printed seeds character by character against the values in the appendix of the NIST standard FIPS 186-4

Curve Compared with FIPS 186-4 seed
P-192, 224, 256, 384, 521 All 5 match
B-233, 283, 409, 571 All 4 match
B-163 Not in the code

The binary-field curves B-233 through B-571 match the case seeded with the time divided by 2 Read as is, it gives February 1984; doubled, it gives April 17, 1998

I also checked, following the FIPS 186-4 appendix procedure, whether the curve coefficient b comes out of the seed The value r made by feeding the P-256 seed into SHA-1 satisfied r × b² ≡ −27 (mod p)

The backdoor suspicion and remaining questions

Anthropic said this result is not a weakness in ECDSA or a new attack Its explanation is that if the seeds were made with a common random number generator seeded with the time, there is less room to pick a curve and hide it

  • Skipped candidate: the 876th candidate of the P-256 run also gave a qualifying curve but was not used
  • B-163 seed: not reproduced by any method
  • Base points: how the base points G of P-224, 256, 384, and 521 were made is unconfirmed
  • Number of runs: how many runs were made with different times can’t be determined from the seed values

The origin of the base points of P-192 and the five ANSI X9.62 example curves was confirmed They came from Arjen Lenstra’s FreeLIP random number generator

The seed bounty of about $36,864 (₩51.61 million) is being donated to ISRG ISRG is the nonprofit that runs the free certificate authority Let’s Encrypt

Where P-256 is used in Korea

Terminal using openssl to check that the www.naver.com certificate's public key is prime256v1 Terminal using openssl to check that the www.naver.com certificate’s public key is prime256v1 — Source: run by me

P-256 is the same curve also called secp256r1 or prime256v1, depending on the standard ES256, the default signature scheme for passkeys (WebAuthn), is also P-256 ECDSA

On October 19, 2026, I checked the certificates of major Korean sites with openssl

Site Certificate public key
www.naver.com P-256 (EC)
www.google.com P-256 (EC)
www.daum.net RSA 2048
www.kakaocorp.com RSA 2048
www.gov.kr RSA 2048
www.kbstar.com RSA 2048
toss.im, www.coupang.com RSA 2048

Naver’s servers use P-256 ECDSA for signatures during the connection For key exchange, Naver, Google, and Coupang all negotiated X25519MLKEM768 rather than P-256

Anthropic said there is nothing readers need to change This result does not lower the security of services that use P-256

Sources