I made a smaller secp256k1 for testing purposes

13 replies 494 views
Posts: 20 · Reputation: 150
#1Jul 24, 2024, 08:53 AM
I'm diving into this whole crypto thing and I know this might come off as a bit amateurish. So, I created a smaller version of secp256k1, where p=43 and n=31. I picked the point G(2, 31) as my generator point and managed to list all the valid points. I printed this out and stuck it on my wall. While I work from home, I glance at it now and then, hoping to spot something intriguing (at least for me). Here’s what I found, which also applies to the regular secp256k1 that Bitcoin uses... Every Y value has three distinct X values. When you calculate G for these points, you always end up with n=31. For instance, G=(2,31) + 5G=(12,31) + 25G=(29,31) results in 31G. The same goes for other points, like 2G=(7,36) + 10G=(42,36) + 19G=(37,36) = 31G. If you switch up the generator points, the positions stay the same, so for n=31, you’ll consistently see the same Y for sets of points like 1 5 25 or 2 10 19... There are 10 sets of these. There are also negative point sets, like 1 5 25 and 6 26 30 (the last one counting backward). When you combine a positive set with a negative one, you always get 93G or 3n. I noticed that when you sum up X1 + X2 + X3 for one set of points, sometimes it results in 2P and other times just P. Not sure what’s going on there... On the original curve where y equals 483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8, there are three X values: first x: c994b69768832bcbff5e9ab39ae8d1d3763bbf1e531bed98fe51de5ee84f50fb second x: 79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 third x: bcace2e99da01887ab0102b696902325872844067f15e98da7bba04400b88fcb If you take X1...
5 Reply Quote Share
eric.maxiMember
Posts: 35 · Reputation: 232
#2Jul 24, 2024, 11:34 PM
secp256k1 curve is With the help of cuberoot of Unity, we can say that each value of Y there will be 3 values of X. (Endomorphism Points) In a similar way For each X there will be 2 values of Y. (symmetry Points) The relationships between them are well known and already used in various tools for faster scanning (example VanitySearch from JLP). In a very simple way if you have a Pubkey points (x, y) you can get in total 6 pubkeys easily through These points are related with the Generator through Privatekeys like this Here the secp256k1 constants are
4 Reply Quote Share
ericn0v4Member
Posts: 19 · Reputation: 106
#3Jul 25, 2024, 12:49 AM
Hola! You can check this one https://amnesia.sh/ctf/2024/03/14/htb-arranged.html
2 Reply Quote Share
Posts: 20 · Reputation: 150
#4Jul 25, 2024, 03:23 AM
@dexizer7799 Thank you but I think this is an example for different type of curve... I do not know I did not understand the content of that link for small secp256k1 I found that if you do addition of all X values for all points and do mod p you get 0 So if P=97 I get n=79 if I do the addition of all valid points Gx+2Gx+3Gx+4Gx....+78Gx Where Generator point is P   (1,69) then I get 3880 mod 97 = 0 Maybe this can be usefull
4 Reply Quote Share
byte2019Senior Member
Posts: 270 · Reputation: 1836
#5Jul 25, 2024, 09:03 AM
The smallest valid example I can come up with: Curve p=7, n=13, y^2=x^3+3, generator=(1,2) Server to execute code: https://sagecell.sagemath.org/ Table of private and public keys: And then, everything can be rotated just like in a clock, with additional 13th point at infinity. Later, you can try to go into bigger and bigger curves, and get for example everything below 100: It is just slightly modified example from vjudeu's code: https://github.com/vjudeu/curves1000/wiki/Six-n%E2%80%90values-when-changing-b%E2%80%90value As you can probably see, you can get these results: Another similar topic, which may be useful: https://bitcointalk.org/index.php?topic=5459153.0 Here, Garlo Nicon was trying just y^2=x^3+7, and checked only values, where p-value and n-value can be swapped, but as it is not the case in secp192k1 and secp224k1, and works only for secp160k1 and secp256k1, then probably other b-values should be considered as well.
4 Reply Quote Share
markchainMember
Posts: 30 · Reputation: 198
#6Jul 25, 2024, 11:46 AM
The secp256k1 you created for testing how did it go?
1 Reply Quote Share
Posts: 20 · Reputation: 150
#7Jul 25, 2024, 02:41 PM
I do not want to create a new thread I just want to continue here... I tried to figure out how BSGS works for scanning points and how it maybe can be improved... Many BSGS scanners makes babystep file where you take starting point and the add +G+G+G+G+G+G to get for example 300.000.000 consecutive points Then scanner will jump 300M per iteration and check if the current point is on the list... But I think that there is no need for all points to be consecutive. You can spread them all over the range just make sure that when you generating the babystep file have the rule where For every point in theory if you do mod 300.000.000 of distance between start point and any generated point you will get all posible remainings for 300.000.000... so that means when you scan you can still jump regular jumps even if there is huge gap between points and you will find a solution sooner because points are not at the same place I think this can be improved more.... -------------------------------------------------------- Also, for example, in puzzle 135 we have our goal point X: 145D2611C823A396EF6712CE0F712F09B9B4F3135E3E0AA3230FB9B6D08D1E16 Y: 667A05E9A1BDD6F70142B66558BD12CE2C0F9CBC7001B20C8A6A109C80DC5330 From this point we can do subtraction 0x4000000000000000000000000000000000 * G we will get some point and then we take simetrical point - the point in upper region Then we make a list (babystep file) of all X values from 1G to 300.000.000G So we can start scanning from a symmetrical point and we go UP... but then we can jump 600.000.000 keys per jump so we can double the speed - when we hit some X value we have 2 solutions and one of them is correct I am not sure about the method where we put gaps between points in the babystep file because there is infinity point so after infinity point all points are moved by 1 so if you jump 600.000.000 keys per jump and you have only 300.000.000 points in BS file I am not sure that it will find a solution because other half of points are moved by 1 In regular BSGS that must work - it does not work only in case if you hit the infinity point when you jump for 600.000.000 keys... But I think the chances for that are small I have only this code for generating lines When I generate 300.000.000 keys I take only first 16 characters for matching. It is a simple code and can be improved on many ways. I am not so good at python I was working with PHP like 15 years my idea is to create ONE babystep file and count that file twice because you can double the number of consecutive X values because they are going in one direction then in the reverse direction (with 0 point in the middle) Our goal point 02145d2611c823a396ef6712ce0f712f09b9b4f3135e3e0aa3230fb9b6d08d1e16 I have this code for subtraction of points so I used it 02cbb434aa7ae1700dcd15b20b17464817ec11715050e0fa192ffe9c29a673059f = 4000000000000000000000000000000000 * G I got this point Upper region point is From this point we can start. Make babystep file from 1G to XG (how much RAM do you have) and then start scanning... You are creating Babystep file from 1G to 10G in babystep file you only put X values (or part of it or I do not know) You are jumping from 264G ----> inverse point n - 264 And you can jump 20G in one jump and try to match X values of the point... number of line you hit is for example 3... you have 2 solutions ... private key = n - nuber of jumps * 20 - 3 private key = n - nuber of jumps * 20 - 3 * 2 - 1(because of infinity point) I mean this is something I am thinking about not sure I also have another Idea like a Kangaroo that will use the infinity point as a referent point so the kangaroo will jump from the public key up and we will save X values of those points when the code jumps over the infinity point then the kangaroo will basically start jumping back because X values now have order in backward... and then when you find collision with itself you can calculate the private key So in my code I was looking for private key of 03440daba3905488f1b5ad2186f6ce2e9a9fe69327ac975dba1a93f8ed60d7813d I know that private key is < n/2 so I took the even Y value to have a point > n/2 here is the code I know that the code is slow but it finds a solution So original private key is [moderator's note: consecutive posts merged]
3 Reply Quote Share
LuckyCoinLegendary
Posts: 832 · Reputation: 4795
#8Jul 25, 2024, 03:05 PM
That is very interesting. How did you know that G = (2, 31) would produce a curve that models secp256k1's properties, if I may ask? Is there any theorem in say group theory that describes this kind of construction? I'm particularly interested in if there's the process with which cryptographers use to select prime numbers for a curve can be expressed as an algorithm.
1 Reply Quote Share
Posts: 20 · Reputation: 150
#9Jul 25, 2024, 03:49 PM
I was using this website https://asecuritysite.com/ecc/ecc_points_mult I was putting random p-prime numbers, then "manually" bruteforce X value to get valid point Then if you get rule (n-1)mod 6 = 0 then you basically got the smaller version of standard secp256k1 - you will get the sets of 2 Y values with 3 X values just like in regular curve The smallest example is  p = 7 G=(1, 1)
3 Reply Quote Share
BasedApeMember
Posts: 41 · Reputation: 202
#10Jul 25, 2024, 09:43 PM
I learn many things from this smaller secp256k1. Uncompressed public key: 042f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4d8ac222636e5e 3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6 Three x values: x1 = 21505829891763648114329055987619236494102133314575206970830385799158076338148 x2 = 23285849548026170226712523888619559634478006467037872208296602441247713932904 x3 = 71000409797526377082529405132449111724689844884027484860330595767503044400611 Two y values: y1 = 98003708678762621233683240503080860129026887322874138805529884920309963580118 y2 = 17788380558553574189887744505607047724243097342766425233927699087598871091545 Enter private key for (x1, y1) = (21505829891763648114329055987619236494102133314575206970830385799158076338148, 98003708678762621233683240503080860129026887322874138805529884920309963580118): 5 Six public keys with private keys: Public key 1: 042f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4d8ac222636e5e 3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6 [Private key: 5]   Validated: k1 matches Public key 2: 04337b52e3acda49dff79f54fbccb94671a045693ee0d097cc138c694695a83668d8ac222636e5e 3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6 [Private key: 72798312578463789091060122408687194401800723498338030560477939572921828405753]   Validated: k2 matches Public key 3: 049cf8cecf391e958cb2ac03df28ea6865772f120342cdcd7c20cac14eb816d5e3d8ac222636e5e 3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6 [Private key: 42993776658852406332510862600000713451036840780736873822127223568596333088579]   Validated: k3 matches Public key 4: 042f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe42753ddd9c91a1 c292b24562259363bd90877d8e454f297bf235782c459539959 [Private key: 115792089237316195423570985008687907852837564279074904382605163141518161494332]   Validated: k4 matches Public key 5: 04337b52e3acda49dff79f54fbccb94671a045693ee0d097cc138c694695a836682753ddd9c91a1 c292b24562259363bd90877d8e454f297bf235782c459539959 [Private key: 42993776658852406332510862600000713451036840780736873822127223568596333088584]   Validated: k5 matches Public key 6: 049cf8cecf391e958cb2ac03df28ea6865772f120342cdcd7c20cac14eb816d5e32753ddd9c91a1 c292b24562259363bd90877d8e454f297bf235782c459539959 [Private key: 72798312578463789091060122408687194401800723498338030560477939572921828405758]   Validated: k6 matches Sum of private keys for y1 = 115792089237316195423570985008687907852837564279074904382605163141518161494337 (should be n or 2n) Sum of private keys for y2 = 231584178474632390847141970017375815705675128558149808765210326283036322988674 (should be n or 2n)
2 Reply Quote Share
diamond365Full Member
Posts: 136 · Reputation: 744
#11Jul 26, 2024, 02:18 AM
Endomorphism! public key 2 = beta * P.x || lambda * P (mod p) public key 3 = beta2 * P.x public key 4 = p - P.y() == inverse of p * G (mod p) public key 5 = x*beta%p, p-y == N-pvk*lmda%N public key 6 = x*beta2%p, p-y == N-pvk*lmda2%N python script that compute all of them in one shot (if helpful to anyone):
4 Reply Quote Share
Posts: 13 · Reputation: 149
#12Jul 26, 2024, 05:47 AM
would you share the code or script for above output?
4 Reply Quote Share
ryan23Member
Posts: 5 · Reputation: 117
#13Jul 26, 2024, 11:58 AM
from ecdsa.ellipticcurve import Point from ecdsa.curves import SECP256k1 # Secp256k1 parameters curve = SECP256k1.curve p = curve.p() n = SECP256k1.order G = SECP256k1.generator # Endomorphism constants beta = 0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee lmbda = 0x5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72 beta2 = (beta * beta) % p lmbda2 = (lmbda * lmbda) % n def endomorphism(P, beta_val):     """Apply x-coordinate endomorphism with given beta"""     return Point(curve, (beta_val * P.x()) % p, P.y(), order=n) def negate_point(P):     """Negate point by flipping y-coordinate"""     return Point(curve, P.x(), (-P.y()) % p, order=n) def format_key(P):     """Format point as uncompressed public key"""     return f'04{P.x():064x}{P.y():064x}' # Input private key k = 5 # Base point P = k * G # Generate all 6 keys keys = [     # Original y group     (P, k),     (endomorphism(P, beta), (k * lmbda) % n),     (endomorphism(P, beta2), (k * lmbda2) % n),         # Negated y group     (negate_point(P), (n - k) % n),     (negate_point(endomorphism(P, beta)), (n - (k * lmbda)) % n),     (negate_point(endomorphism(P, beta2)), (n - (k * lmbda2)) % n) ] # Print results print(f"Uncompressed public key: {format_key(P)}\n") print("Three x values:") print(f"x1 = {P.x()}") print(f"x2 = {endomorphism(P, beta).x()}") print(f"x3 = {endomorphism(P, beta2).x()}\n") print("Two y values:") print(f"y1 = {P.y()}") print(f"y2 = {negate_point(P).y()}\n") print("Six public keys with private keys:") for i, (point, priv) in enumerate(keys, 1):     print(f"Public key {i}: {format_key(point)} [Private key: {priv}]")     print(f"  Validated: {point == priv * G}") sum_y1 = sum(keys[1] for i in range(3)) sum_y2 = sum(keys[1] for i in range(3,6)) print(f"\nSum for y1: {sum_y1} (n = {n})") print(f"Sum for y2: {sum_y2} (2n = {2*n})")
2 Reply Quote Share
Posts: 13 · Reputation: 149
#14Jul 27, 2024, 05:59 AM
Thankyou @Geshma
4 Reply Quote Share

Related topics