The recycled numbers inside Certicom’s curve generators
Bitcoin’s curve belongs to a family of late-1990s standard curves whose starting points were never explained. Divided by the cofactor, many of those starting points reduce to short or repeated values. A few were spotted before. What nobody seems to have noticed is how often one curve’s hidden value repeats another’s.
Summary
- Question
- Every standard elliptic curve comes with a published starting point, its generator. None of the documents we could read says how the generators of the Certicom-era curves (SEC 2, 2000, and many of the ANSI X9.62 binary examples) were chosen. People have asked about Bitcoin’s since at least 2013.
- Answer
- Dividing each of 69 generators by its cofactor, or by 2, and keeping every answer gives a structured hidden value on 25 curves. Seven were known. On the other 18, hidden values are shared between sibling curves, reused from earlier curves, or too uneven to be random, which points to one routine that started from stored values.
- How sure
- Every relation is an exact computation, and unrelated curves share at most 6 digits where these share 23 to 56. The single routine is inference. Where the stored values came from is unknown. None of it affects security.
1The question
An elliptic curve used in cryptography comes with three kinds of published numbers: the curve’s equation, the size of the group of points on it, and one fixed point, the generator G, from which every key is computed. Any point of the right order would work equally well as G. For that reason a generator is normally chosen in a way anyone can check, or at least explained, so that nobody has to wonder whether it was picked for a hidden reason.
Many curves of the late 1990s came from one company. Certicom wrote SEC 2, the 2000 standard that names curves such as secp256k1 (now used by Bitcoin), and many of the binary-field examples in ANSI X9.62. In OpenSSL’s copy of these standards, the random seeds of 22 curves contain the ASCII text “MinghuaQu” (in some, shifted by half a byte), the name of a Certicom researcher; they include c2tnb239v3 and c2tnb359v1, two of the curves below. Brian Smith’s gist lists six of them.12 SEC 2 says the curves were chosen “verifiably at random” from those seeds, but none of SEC 2, SEC 1 v1.0 or FIPS 186-2 records how the generators were chosen.1,3 (We could not read X9.62-1998.2) In October 2026 Anthropic reported, and Filippo Valsorda confirmed, that the seeds of the NIST and X9.62 prime curves and four NIST binary curves came from the C library’s lrand48 generator seeded with 1997–98 timestamps. Anthropic also traced six base points (P-192 and five X9.62 prime curves) to the FreeLIP random-number generator.10,11 The Certicom generators were not covered.
One clue was known. Since at least 2015, people have noticed that “half” of secp256k1’s generator, the point P with 2P = G, has an x-coordinate far shorter than chance allows (Section 5 lists who found what). The same was later seen on NIST K-163 and two other binary curves. This note asks whether that pattern is a few curiosities or a trace of how the generators of whole standards were made.
6// secp160k1 7// const unsigned int PRIVATE_KEY_SIZE = 192; 8// const unsigned int PUBLIC_KEY_SIZE = 41; 9// const unsigned int SIGNATURE_SIZE = 48; 10// 11// secp192k1 12// const unsigned int PRIVATE_KEY_SIZE = 222; 13// const unsigned int PUBLIC_KEY_SIZE = 49; 14// const unsigned int SIGNATURE_SIZE = 57; 15// 16// secp224k1 17// const unsigned int PRIVATE_KEY_SIZE = 250; 18// const unsigned int PUBLIC_KEY_SIZE = 57; 19// const unsigned int SIGNATURE_SIZE = 66; 20// 21// secp256k1: 22// const unsigned int PRIVATE_KEY_SIZE = 279; 23// const unsigned int PUBLIC_KEY_SIZE = 65; … 51 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
2The answer
Many curves have a cofactor h: the full group of points is h times larger than the subgroup actually used. Binary-field curves always have an even cofactor (from 2 to 10 for most curves here; one X9.62 curve has 76, and six have between 10,080 and 65,392). The usual way to get a point in the subgroup is to take any point P and multiply it by h. Running that backwards, we divided each published generator by h and by each of its divisors. A division like this has several answers, which differ by small “torsion” points outside the subgroup, so we kept all of them. On curves whose cofactor is 1 we divided by 2. Figure 3 shows what comes out.
A binary curve from SEC 2 (2000). Its generator’s x-coordinate looks random. Halve it and the starting point is the number 3, the smallest nonzero x for which a point exists on this curve.
Three X9.62 curves (1998) with cofactors 2, 4 and 6. Their generators share nothing visible. Divide each by its cofactor and the same 47 digits appear under all three; only the last digit differs. Two larger X9.62 curves carry the same string too (Table 1).
A SEC 2 prime curve with cofactor 4. Divide its generator by 4 and one of the four answers has the same x-coordinate as the published generator of its sibling, secp112r1.
The known case, shown for comparison. Bitcoin’s curve has cofactor 1, yet halving its generator gives a number 90 bits shorter than the field. This has been public since at least 2015.
reproduce.py. A randomly chosen generator would give an unremarkable full-length number.Across the 69 curves, the structured hidden points fall into four overlapping groups (Table 1).
Short numbers. On sect113r1 and sect113r2 the hidden x is 3 and 2, the smallest nonzero values that work on each curve (reading field elements as integers, as the standards print them). On NIST K-163 and X9.62 c2pnb163v1 it is a 32-hex-digit number on a 163-bit field, and on the four secp…k1 curves it is the same 38-digit string, trimmed or extended. On X9.62 c2tnb359v1 (cofactor 76) it is a 33-digit number on a 359-bit field. Apart from sect113r2 and c2tnb359v1, these were known before.
One stored value, several curves. Sibling curves share a hidden value and differ only in the last hex digit. sect131r1 and sect131r2 share a 31-digit body followed by 2 and by 4. sect193r1 and sect193r2 have hidden points with the same x-coordinate. Five X9.62 curves, c2tnb191v1, v2 and v3 and c2tnb239v1 and v2, carry the same 46-digit string, with cofactors 2, 4, 6, 4 and 6; on the two 239-bit curves it is preceded by 5757157563.
An earlier curve’s value, reused. secp112r2’s hidden point has the same x-coordinate as secp112r1’s published generator, and the same holds for secp128r2 and secp128r1. c2pnb163v3’s hidden x is c2pnb163v1’s published generator x, and c2pnb163v2’s is the same number with one digit dropped. The hidden x shared by sect193r1 and sect193r2 contains 44 consecutive digits of c2tnb191v1’s generator, an X9.62 value carried into SEC 2. secp160r2’s hidden x begins with the first 23 digits of secp160r1’s generator. c2tnb359v1’s short hidden x shares 29 digits with c2pnb163v1’s hidden x.
Digits too uneven to be random. The 46-digit string has only four letters, which spell cabe, and 31 of its 46 digits are 1, 4 or 7 (about 9 would be expected). Two more hidden values look similar. One is c2tnb239v3’s (cofactor 10), 12398377777737777a665c55…. The other is one of c2tnb431r1’s 39,311 hidden points (cofactor 10,080), …9234562399235492978123847a777c67666f6f6766a666666b66610. All three look typed by hand rather than generated, but that is an interpretation, not something the numbers can prove.
| Curve (standard) | k | x of hidden point P | Relation |
|---|---|---|---|
| sect113r1 (SEC 2) | 2 | 3 | smallest nonzero x on the curve · known |
| sect113r2 (SEC 2) | 2 | 2 | smallest nonzero x on the curve |
| sect163k1 = NIST K-163 | 2 | 23e21d60…256e97 | 32 digits on a 163-bit field · known |
| c2pnb163v1 (X9.62) | 2 | 13152a6b…4645cb | 32 digits on a 163-bit field · known |
| secp160k1, 192k1, 224k1, 256k1 (SEC 2) | 2 | …8ce563f8…6795f9c6 + 1 digit | one 38-digit core, last digit 2, 6, 3, 3 · known |
| sect131r1 / sect131r2 (SEC 2) | 2 | 10134db2…a787968 + 2 / 4 | shared 31-digit body |
| sect193r1 and sect193r2 (SEC 2) | 2 | 23daf8a2…e1aa04 | same x on both; 44 digits of c2tnb191v1’s G |
| c2tnb191v1 / v2 / v3 (X9.62) | 2 / 4 / 6 | 3·B·4 / d / 0 | B = 38847711…47772771 (46 digits) |
| c2tnb239v1 / v2 (X9.62) | 4 / 6 | 5757157563·B·2 / 4 | same string B |
| secp112r2 (SEC 2) | 4 | 09487239…c2f098 | x of secp112r1’s published G |
| secp128r2 (SEC 2) | 4 | 161ff752…2c5b86 | x of secp128r1’s published G |
| c2pnb163v3 (X9.62) | 2 | 7af69989…be803cb | x of c2pnb163v1’s published G |
| c2pnb163v2 (X9.62) | 2 | 7f699895…be803cb | c2pnb163v1’s G x with one digit dropped |
| secp160r2 (SEC 2) | 2 | 4a96b568…ae4e8422 | first 23 digits of secp160r1’s G |
| c2tnb359v1 (X9.62) | 76 | 152d52a6…24645cb | 33 digits on a 359-bit field; 29 digits of c2pnb163v1’s hidden x |
| c2tnb239v3 (X9.62) | 10 | 12398377…177373ae | full length; digits highly uneven |
| c2tnb431r1 (X9.62) | 10,080 | 38f78976…b66610 | full length; digits highly uneven |
3Verification and controls
The new patterns were found by blind tests, not by looking for particular strings. We took the 69 distinct curves in OpenSSL’s table of the standards (SEC 2, X9.62, NIST, Brainpool and SM2) and listed every hidden point of each. The six curves with cofactors of 10,080 and more were searched separately for short values and for pieces of the main strings above. For the other 63 (299 hidden points), we compared every pair of curves (1,953 pairs) and every hidden point against every other curve’s published generator (18,538 comparisons), recording the longest run of hex digits they share, with leading zeros dropped. We also measured how uneven each value’s hex digits are (a chi-square statistic over the 16 digit counts).
The results separate cleanly (Table 2). Unrelated pairs share at most 6 digits, as chance predicts for strings this long. Every related pair in Table 1 shares between 23 and 56. For two random 40-digit strings, the chance of sharing a 23-digit run is about one in 1025, so even after thousands of comparisons none of these matches is a plausible accident. On the unevenness measure, the hidden values carrying the 46-digit string score 95 to 110, and the other two 93 and 99. The highest of 100,000 random strings of 41, 60 or 108 digits scores 53 to 57, and the next-highest of c2tnb431r1’s 39,311 hidden points scores 49. The search also recovers the known secp…k1 core on its own, which serves as a positive control.
| Comparison | Count | ≤ 6 digits | 23–56 digits |
|---|---|---|---|
| Hidden points of two different curves | 1,953 | 1,933 | 20 |
| Hidden point vs. another curve’s published G | 18,538 | 18,531a | 7 |
Most curves show nothing, which is itself a control: NIST’s B-163 to B-571 and K-233 to K-571, sect163r1, sect239k1, the X9.62 and NIST prime curves, Brainpool, SM2, and five of the six large-cofactor X9.62 curves (c2pnb176w1, c2pnb208w1, c2pnb272w1, c2pnb304w1 and c2pnb368w1). For these, every hidden point (up to 278,783 per curve) was checked for short values and for 9-digit pieces of the main strings in Table 1, and the independent reviewer’s unevenness check of four of them found nothing beyond chance (highest score 67, on c2pnb176w1, among 127,007 points).b One weaker signal is left out of Table 1: the published generator of sect163r1 itself has uneven digits (score 57), which is suggestive but within reach of chance across this many tests.
Every claim in Table 1 is checked by reproduce.py, which is written in plain Python with no libraries, verifies each generator before use, and passes 21 of 21 checks in about a minute. It is a separate implementation from the search code that found the patterns. An independent reviewer recomputed the main values with their own code and checked the curve parameters against the SEC 2 text (198 fields, no differences). An earlier round, covering the short values and the c2tnb191v1/c2tnb239 string, was reimplemented from scratch by a different model, OpenAI’s Codex, which confirmed 19 of 19 claims.
4What it suggests about how the generators were made
Read together, most of the patterns fit one simple procedure. Start from a stored value: a short number, a string kept for the purpose, or a value from a curve already made. If it is not a valid x-coordinate on the new curve, change the last hex digit and try again. Lift it to a point and multiply by the cofactor. Parts of this procedure were proposed before for the secp…k1 curves. Greg Maxwell suggested in 2023 that the intended value “wasn’t on the curve and required modification”. The Bitcointalk user garlonicon treated the final byte as a counter and suggested starting from a small x and incrementing. Thomas Pornin pointed in 2019 to the SEC 1 routine, which tries candidates until a point exists and then multiplies by the cofactor; SEC 1 v2.0 (2009) writes down a routine of that shape.6,8 What the binary curves add is evidence that the procedure crossed curves and standards. A string from X9.62 (1998) reappears under SEC 2’s sect193 curves (2000), several new generators start from older ones, and the final multiplication appears on prime curves with cofactor 1, where it was not needed. That fits Pornin’s guess that a routine written for binary curves, whose cofactor is always even, was reused unchanged for secp256k1.
Not every case fits neatly. secp160r2’s value differs from secp160r1’s generator in its last 17 digits, though secp160r1’s generator is itself valid on secp160r2. c2pnb163v2 drops a digit. The sect193 value replaces the leading 36b of c2tnb191v1’s generator with 2 and changes the last digit, and the 239-bit curves add a prefix. The final digits (2 and 4; 4, d and 0; 2 and 4; 2, 6, 3 and 3) fit no single stopping rule we tried. And the stored strings themselves remain unexplained: the 46-digit string, the 38-digit core under the secp…k1 curves, the two 32-digit values and the two other uneven strings. Earlier checks found no sign of common 1990s random-number generators or of hashes of simple phrases in the first four.13 The strings under c2tnb239v3 and c2tnb431r1, found later, have not yet been tested.
5What was known before
- 2000SEC 2 publishes the curves and their generators without saying how the generators were chosen.1
- 2009Bitcoin launches on secp256k1, one of them.
- 2013Cryptography Stack Exchange: “How were secp*k1 elliptic curve generators chosen?” The answer: the answerer did not know, and it cannot matter, since if one generator were weak, all would be.c
- 2015Greg Maxwell notes that halving the secp224k1 and secp256k1 generators gives the same short string.4
- 2017–22Pieter Wuille, on Bitcoin Stack Exchange: “Nothing is known about how the designers of the curve chose this specific generator.” In 2022: “We don’t know.”d
- 2019
- 2023–25A Bitcointalk thread adds NIST K-163, sect113r1 and c2pnb163v1, and notes a relation between two curves’ seeds.6
- Oct 2026
Greg Maxwell noted in 2015 that secp224k1 and secp256k1 share the same 166-bit string, doubled to make the generator.4 Brengel and Rossow reported secp256k1’s short half-generator in 2018, and fgrieu asked about it on Cryptography Stack Exchange that June. Nadia Heninger, Travis Scholl and Dan Shumow gave a Crypto 2019 rump-session talk titled with secp160k1’s halved-generator x-coordinate.5 Marcus Brinkmann posted candidate values in a 2019 gist, and Johannes Zweng wrote the four-curve pattern up in 2022.7 In a 2019 answer to fgrieu’s question, Thomas Pornin guessed the cofactor explanation, without binary-curve data.8 The DiSSECT project measures the x-coordinate of G/k for small k on prime curves. Its database therefore lists two of the values in Table 1: secp128r2’s, which equals secp128r1’s generator x, and secp160r2’s, which begins with 23 digits of secp160r1’s. It does not remark on either, and its binary-curve rows are empty.9
In a 2023 Bitcointalk thread, garlonicon reported the short hidden points of NIST K-163 and sect113r1 and the layout of the four secp…k1 values, and Greg Maxwell gave the cofactor explanation for binary curves. In 2025 the user stwenhao added c2pnb163v1.6 We found no earlier remark on the values shared across sibling curves, on the x = 2 preimage of sect113r2’s generator, on c2tnb359v1, on the uneven strings under c2tnb239v3 and c2tnb431r1, or on one curve’s value being reused for another. The search covered the sources in the references, Hacker News, Bitcointalk, the DiSSECT and BADA55 papers and the works citing them (via OpenAlex), IACR ePrint, Sourcegraph code search (results capped) and the standards themselves. It could not reach sci.crypt for 1998–2001 or the text of X9.62, so an earlier account may exist in a source we did not reach. Corrections are welcome and will be credited here.
6Discussion
It helps to separate three claims. Established by computation: every hidden point, shared run and unevenness score in Table 1, which anyone can check with the script. Strongly supported, but not proven: that one routine made the generators of at least these Certicom-era curves, in SEC 2 and among the X9.62 binary examples, starting from stored or previously used values, adjusting a final digit and multiplying by the cofactor. Matches of 23 to 56 digits between curves cannot plausibly be chance, and this is the simplest routine that produces them. Not established: the exact rule for the final digit, where the stored strings came from (including whether they were typed by hand), and who ran the routine. The people who wrote these standards may simply know, and we plan to ask them.
None of this affects security. For a prime-order group, every generator is as good as any other, and knowing how one was chosen changes nothing about the curve. What changes is the record: these numbers have been copied into software for 25 years, and now part of how they were made can be read off the numbers themselves.
7A note on method
This result came from the same experiment as an earlier note on RC2’s π table: AI agents assigned to neglected problems whose answers can be checked exactly.14 The agent, Claude, began from the known secp256k1 case. It extended the search to binary curves and to points outside the subgroup, then compared the hidden values across curves, which found the reuse. Codex checked the first round independently. A separate fresh-context review recomputed the numbers, checked the citations against their sources and found the digit-unevenness signal, and its corrections are included here. The script needs no trust in any of that: it recomputes every value from the published curve parameters.
Notes
- aComparisons of a curve’s hidden points with its own generator are excluded.
- bFor the six large-cofactor curves the search script, not
reproduce.py, was used, because their cofactors run to 65,392. The cofactor group of c2pnb304w1 is not cyclic and was handled separately.reproduce.pychecks the patterned c2tnb431r1 point directly. - c.“How Were secp*k1 elliptic curve generators chosen?”, Cryptography Stack Exchange, question 9668, 10 August 2013, answer by poncho.
- d.P. Wuille, answers on Bitcoin Stack Exchange: “How were the secp256k1 base point coordinates decided?”, question 58784, 28 August 2017; “How is the generator point G chosen in the secp256k1 curve used in Bitcoin?”, question 113116, 2 April 2022.
References
- [1]Certicom Research. SEC 2: Recommended Elliptic Curve Domain Parameters, version 1.0. Standards for Efficient Cryptography Group, 20 September 2000. See also SEC 1 v2.0 (2009), §3.1.3.2.
- [2]ANSI X9.62-1998. Public Key Cryptography for the Financial Services Industry: The Elliptic Curve Digital Signature Algorithm (ECDSA). American Bankers Association, 1999. Curve parameters as reproduced in OpenSSL, crypto/ec/ec_curve.c.
- [3]NIST. FIPS 186-2: Digital Signature Standard, 27 January 2000, Appendix 6 (recommended elliptic curves, incl. K-163).
- [4]G. Maxwell. Post #6 in “The most repeated R value on the blockchain”. Bitcointalk, 12 July 2015. M. Brengel, C. Rossow. Identifying key leakage of Bitcoin users. RAID 2018, LNCS 11050.
- [5]N. Heninger, T. Scholl, D. Shumow. Talk titled “48ce563f89a0ed9414f5aa28ad0d96d6795f9c62”. Crypto 2019 rump session, August 2019 (video).
- [6]garlonicon, G. Maxwell, stwenhao and others. “Bounty offered to crack the seeds for NIST curves!” Bitcointalk, posts #5, #11 and #13 (October 2023) and #19 (January 2025, edited 7 February 2025).
- [7]J. Zweng. secp256k1 generator gist, 28 April 2022; M. Brinkmann (lambdafu). gist, 27 August 2019.
- [8]fgrieu. “What does the special form of the base point of secp256k1 allow?” Cryptography Stack Exchange, question 60420, 30 June 2018; answer by T. Pornin, 21 August 2019.
- [9]V. Sedláček, V. Suchánek, A. Dufka, M. Sýs, V. Matyáš. DiSSECT: Distinguisher of Standard and Simulated Elliptic Curves via Traits. AFRICACRYPT 2022, LNCS 13503; online database (accessed 18 October 2026).
- [10]Anthropic. Claude reveals ECDSA curve origins. 16 October 2026.
- [11]F. Valsorda. The NIST Elliptic Curves Seeds Bounty Has Been Claimed. 16 October 2026.
- [12]B. Smith. SECG Curve Seeds. GitHub gist, 2017 (updated 2026).
- [13]K. Hamadeh. Working notes for this note: tests of the stored strings against 1990s random-number generators and hashes (to be published with the script).
- [14]K. Hamadeh. How RC2’s π table was made. 17 October 2026.
Citing this note
Code. reproduce.py recomputes every hidden point and every comparison from the curve parameters (Python 3.8+, standard library only).
Revisions. First version, October 2026, after two independent reviews of every figure and claim.