Khalid Hamadeh
Research note · Cryptography

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.

Khalid HamadehOctober 2026Code: github.com/khalid-hamadeh/certicom-generators
Three published starting points, divided

Generator x-coordinates in hexadecimal, as published in ANSI X9.62 (1998) and SEC 2 (2000), and the points that, multiplied by each curve’s cofactor, give them. The three X9.62 curves are a new result; Bitcoin’s is the known case, shown for comparison. How the division works

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.

Bitcoin 0.1.0January 2009src/key.h
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);
Figure 1. The first release of Bitcoin, by Satoshi Nakamoto. A comment lists key sizes for four curves from SEC 2 before the code settles on secp256k1. Halving the generators of exactly these four gives the same 38-digit core, a pattern noticed on two of them in 2015 and on all four by 2022 (Section 5). Source: the 0.1.0 archive kept by the Satoshi Nakamoto Institute; MIT licence, © 2009 Satoshi Nakamoto.

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.

What doubling and halving a point mean

Figure 2. Bitcoin’s curve, y² = x³ + 7, over the ordinary numbers. To double P, take the tangent at P; it meets the curve again, and that point’s mirror image is 2P. Halving runs this backwards. The standards apply the same rule to a finite set of points, where dividing by an even cofactor gives several answers.
Divide the published generator by the cofactor

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.

published G09d73616f35f4ab1407d73562c10f
÷ 2
hidden P00000000000000000000000000003

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).

191v1 G36b3daf8a23206f9c4f299d7b21a9c369137f2c84ae1aa0d
191v2 G3809b2b7cc1b28cc5a87926aad83fd28789e81e2c9e3bf10
191v3 G375d4ce24fde434489de8746e71786015009e66e38a926dd
÷ 2, ÷ 4, ÷ 6
191v1 P3388477117474774774375771981418781cabe0477727714
191v2 P3388477117474774774375771981418781cabe047772771d
191v3 P3388477117474774774375771981418781cabe0477727710

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.

published G4ba30ab5e892b4e1649dd0928643
÷ 4
hidden P09487239995a5ee76b55f9c2f098
secp112r1 G09487239995a5ee76b55f9c2f098

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.

published G79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
÷ 2
hidden P00000000000000000000003b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63
leading zerosshared or reused digitslast digit (varies)
Figure 3. Each published generator’s x-coordinate (top) and the x-coordinate of a point that, multiplied by the cofactor, gives it (bottom), in hexadecimal, padded to the field size. The values come from OpenSSL’s copy of the standards and are recomputed by reproduce.py. A randomly chosen generator would give an unremarkable full-length number.
Which curves share or reuse a hidden value
Same hidden valueReuses another curve’s valueKnown before
Figure 4. Hidden values are the points that, multiplied by each curve’s cofactor (or by 2), give its published generator. Select a group or arrow to see the digits. Curves whose hidden value stands alone (very uneven digits, or the smallest value that works) are left out here; Table 1 lists all 25. How the division works

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.

Table 1. Hidden points with structure, out of 69 standard curves. G = k·P. “Known” marks values published before this note (Section 5). Hex values are shortened in the middle; reproduce.py prints them in full.
Curve (standard)kx of hidden point PRelation
sect113r1 (SEC 2)23smallest nonzero x on the curve · known
sect113r2 (SEC 2)22smallest nonzero x on the curve
sect163k1 = NIST K-163223e21d60…256e9732 digits on a 163-bit field · known
c2pnb163v1 (X9.62)213152a6b…4645cb32 digits on a 163-bit field · known
secp160k1, 192k1, 224k1, 256k1 (SEC 2)2…8ce563f8…6795f9c6 + 1 digitone 38-digit core, last digit 2, 6, 3, 3 · known
sect131r1 / sect131r2 (SEC 2)210134db2…a787968 + 2 / 4shared 31-digit body
sect193r1 and sect193r2 (SEC 2)223daf8a2…e1aa04same x on both; 44 digits of c2tnb191v1’s G
c2tnb191v1 / v2 / v3 (X9.62)2 / 4 / 63·B·4 / d / 0B = 38847711…47772771 (46 digits)
c2tnb239v1 / v2 (X9.62)4 / 65757157563·B·2 / 4same string B
secp112r2 (SEC 2)409487239…c2f098x of secp112r1’s published G
secp128r2 (SEC 2)4161ff752…2c5b86x of secp128r1’s published G
c2pnb163v3 (X9.62)27af69989…be803cbx of c2pnb163v1’s published G
c2pnb163v2 (X9.62)27f699895…be803cbc2pnb163v1’s G x with one digit dropped
secp160r2 (SEC 2)24a96b568…ae4e8422first 23 digits of secp160r1’s G
c2tnb359v1 (X9.62)76152d52a6…24645cb33 digits on a 359-bit field; 29 digits of c2pnb163v1’s hidden x
c2tnb239v3 (X9.62)1012398377…177373aefull length; digits highly uneven
c2tnb431r1 (X9.62)10,08038f78976…b66610full 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.

Table 2. Longest run of hex digits shared, over all comparisons among the 63 curves with cofactor up to 76.
ComparisonCount≤ 6 digits23–56 digits
Hidden points of two different curves1,9531,93320
Hidden point vs. another curve’s published G18,53818,531a7

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

  1. 2000
    SEC 2 publishes the curves and their generators without saying how the generators were chosen.1
  2. 2009
    Bitcoin launches on secp256k1, one of them.
  3. 2013
    Cryptography 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
  4. 2015
    Greg Maxwell notes that halving the secp224k1 and secp256k1 generators gives the same short string.4
  5. 2017–22
    Pieter 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
  6. 2019
    A Crypto 2019 rump-session talk and Thomas Pornin’s answer on Stack Exchange extend the pattern and suggest a reused binary-curve routine.5,8
  7. 2023–25
    A Bitcointalk thread adds NIST K-163, sect113r1 and c2pnb163v1, and notes a relation between two curves’ seeds.6
  8. Oct 2026
    The NIST seeds are traced to a 1990s random-number generator. Certicom’s generators are not covered.10,11

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

  1. aComparisons of a curve’s hidden points with its own generator are excluded.
  2. 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.py checks the patterned c2tnb431r1 point directly.
  3. c.“How Were secp*k1 elliptic curve generators chosen?”, Cryptography Stack Exchange, question 9668, 10 August 2013, answer by poncho.
  4. 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. [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. [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. [3]NIST. FIPS 186-2: Digital Signature Standard, 27 January 2000, Appendix 6 (recommended elliptic curves, incl. K-163).
  4. [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. [5]N. Heninger, T. Scholl, D. Shumow. Talk titled “48ce563f89a0ed9414f5aa28ad0d96d6795f9c62”. Crypto 2019 rump session, August 2019 (video).
  6. [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. [7]J. Zweng. secp256k1 generator gist, 28 April 2022; M. Brinkmann (lambdafu). gist, 27 August 2019.
  8. [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. [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. [10]Anthropic. Claude reveals ECDSA curve origins. 16 October 2026.
  11. [11]F. Valsorda. The NIST Elliptic Curves Seeds Bounty Has Been Claimed. 16 October 2026.
  12. [12]B. Smith. SECG Curve Seeds. GitHub gist, 2017 (updated 2026).
  13. [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. [14]K. Hamadeh. How RC2’s π table was made. 17 October 2026.

Citing this note

Hamadeh, K. (2026). The recycled numbers inside Certicom’s curve generators. https://khalidhamadeh.com/writing/certicom-generators

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.