Bitcoin Forum
September 18, 2025, 04:25:19 AM *
News: Latest Bitcoin Core release: 29.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: I created smaller secp256k1 just for testing  (Read 743 times)
jovica888 (OP)
Jr. Member
*
Offline Offline

Activity: 57
Merit: 17


View Profile
January 27, 2025, 10:56:02 PM
Merited by NotATether (5)
 #1

So I am learning about everything and so there is a chance that this post can be lame/noob or something like that

I created a smaller secp256k1, p=43 n=31
I took point G(2, 31) for the generator point and I got the list of all valid points
Code:
G=(2,31)
2G=(7,36)
3G=(35,22)
4G=(21,25)
5G=(12,31)
6G=(29,12)
7G=(25,25)
8G=(32,3)
9G=(20,3)
10G=(42,36)
11G=(40,18)
12G=(37,7)
13G=(13,22)
14G=(34,3)
15G=(38,22)
16G=(38,21)
17G=(34,40)
18G=(13,21)
19G=(37,36)
20G=(40,25)
21G=(42,7)
22G=(20,40)
23G=(32,40)
24G=(25,18)
25G=(29,31)
26G=(12,12)
27G=(21,18)
28G=(35,21)
29G=(7,7)
30G=(2,12)

I printed this and I put it on my wall so when I work (I work from home) sometimes I look into this paper and I tried to find something interesting (interesting for me Smiley )

so this is what I found and also those rules can be applied on regular secp256k1 that Bitcoin is using...

Every Y has 3 different X values... When you calculate G of those points you always get n=31
so G=(2,31) + 5G=(12,31) + 25G=(29,31) = 31G, also for all other points 2G=(7,36) + 10G=(42,36) + 19G=(37,36) = 31G
If you change generator points those positions will remain the same so for n=31 you will always get the same Y on the same sets of points 1 5 25, 2 10 19... there are 10 sets of this points

There are negative points set with 1 5 25 and 6 26 30 (6 26 30 starting from the "end" to start" basically) When you do positive set + negative set of points those point will always return 93G or 3n

I found that if you do for one set of point X1 + X2 +X3 you sometimes get 2P and sometimes get only P I do not know why...

so on original curve where y is 483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
you have 3 X
first   x: c994b69768832bcbff5e9ab39ae8d1d3763bbf1e531bed98fe51de5ee84f50fb
second   x: 79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
third   x: bcace2e99da01887ab0102b696902325872844067f15e98da7bba04400b88fcb

If you do X1 + X2 + X3 in this case you will get 2P in some other cases I found that I only get 1P
Y 4218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee

first   x: 1
second   x: 7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee
third   x: 851695d49a83f8ef919bb86153cbcb16630fb68aed0a766a3ec693d68e6afa40
In this case you get only P when you do X1 + X2 + X3

I found that for symmetrical points if you do Y1+Y2 you always get P
b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777 + 79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 = p
.
.
.

Is there and useful way that we can use those points if we can calculate their G positions? I am testing bigger and bigger curves and always looking for n that number of points mod 6 = 0 (+ infinity point)
p = 937 n = 973
1G 235G 737G

So I am trying to make a connection between 1st and 2nd point for any p and any n....
If I know 1st and 2nd point I can easily calculate 3rd = n - 1st - 2nd
then I can calculate the position of other 3 points that has different Y but same 3 X

If we know the relations between those points maybe we can scan keys faster or see some periodical groups I do not know
iceland2k14
Member
**
Offline Offline

Activity: 70
Merit: 86


View Profile
January 28, 2025, 11:19:07 AM
 #2

secp256k1 curve is
Code:
y² = x³ + 7

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
Code:
6 Pubkeys = [x,y]  [x*beta%p, y]  [x*beta2%p, y] [x,p-y]  [x*beta%p, p-y]  [x*beta2%p, p-y]

These points are related with the Generator through Privatekeys like this
Code:
6 Pvkeys = pvk, pvk*lmda%N, pvk*lmda2%N, N-pvk, N-pvk*lmda%N, N-pvk*lmda2%N

Here the secp256k1 constants are
Code:
p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
# Constants Based on Cube root of 1
beta = 0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee
beta2 = 0x851695d49a83f8ef919bb86153cbcb16630fb68aed0a766a3ec693d68e6afa40      # beta*beta
lmda = 0x5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72
lmda2 = 0xac9c52b33fa3cf1f5ad9e3fd77ed9ba4a880b9fc8ec739c2e0cfc810b51283ce      # lmda*lmda
dexizer7799
Newbie
*
Offline Offline

Activity: 42
Merit: 0


View Profile
January 31, 2025, 09:26:29 AM
 #3

Hola! You can check this one https://amnesia.sh/ctf/2024/03/14/htb-arranged.html
jovica888 (OP)
Jr. Member
*
Offline Offline

Activity: 57
Merit: 17


View Profile
February 04, 2025, 07:55:42 PM
 #4

@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
stwenhao
Hero Member
*****
Offline Offline

Activity: 505
Merit: 1029


View Profile
February 04, 2025, 09:58:47 PM
 #5

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/
Code:
p=7
n=13
K=GF(p)
a=K(0)
b=K(3)
E=EllipticCurve(K,(a,b))
G=E(1,2)
E.set_order(n)
d=1
P=d*G
while d<n:
    print(d,P[0],P[1])
    d+=1
    P=d*G
Table of private and public keys:
Code:
+----+---+---+
|  d | x | y |
+----+---+---+
|  1 | 1 | 2 |
|  2 | 6 | 3 |
|  3 | 2 | 2 |
|  4 | 4 | 5 |
|  5 | 3 | 3 |
|  6 | 5 | 3 |
|  7 | 5 | 4 |
|  8 | 3 | 4 |
|  9 | 4 | 2 |
| 10 | 2 | 5 |
| 11 | 6 | 4 |
| 12 | 1 | 5 |
+----+---+---+
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:
Code:
p=5
while p<100:
    n_values=[]
    b_value=1
    while len(n_values)<6:
        K=GF(p)
        a=K(0)
        b=K(b_value)
        E=EllipticCurve(K,(a,b))
        n=E.order()
        if n == p+1:
            n_values.append(n)
            n_values.append(n)
            n_values.append(n)
            n_values.append(n)
            n_values.append(n)
            n_values.append(n)
        else:
            if n not in n_values:
                n_values.append(n)
            b_value+=1
    if n_values[0] != p+1:
        print(p,n_values)
    p=next_prime(p)
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:
Code:
7 [12, 9, 13, 3, 7, 4]
13 [12, 19, 9, 21, 16, 7]
19 [12, 13, 21, 27, 28, 19]
31 [36, 43, 39, 21, 25, 28]
37 [48, 49, 39, 37, 28, 27]
43 [36, 52, 49, 39, 31, 57]
61 [48, 61, 75, 63, 76, 49]
67 [84, 73, 52, 57, 63, 79]
73 [84, 81, 57, 91, 64, 67]
79 [84, 63, 97, 93, 67, 76]
97 [84, 117, 93, 79, 103, 112]
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.

Proof of Work puzzle in mainnet and testnet4.
OfficialGratejoy
Newbie
*
Offline Offline

Activity: 28
Merit: 2


View Profile
February 05, 2025, 04:06:58 PM
 #6

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/
Code:
p=7
n=13
K=GF(p)
a=K(0)
b=K(3)
E=EllipticCurve(K,(a,b))
G=E(1,2)
E.set_order(n)
d=1
P=d*G
while d<n:
    print(d,P[0],P[1])
    d+=1
    P=d*G
Table of private and public keys:
Code:
+----+---+---+
|  d | x | y |
+----+---+---+
|  1 | 1 | 2 |
|  2 | 6 | 3 |
|  3 | 2 | 2 |
|  4 | 4 | 5 |
|  5 | 3 | 3 |
|  6 | 5 | 3 |
|  7 | 5 | 4 |
|  8 | 3 | 4 |
|  9 | 4 | 2 |
| 10 | 2 | 5 |
| 11 | 6 | 4 |
| 12 | 1 | 5 |
+----+---+---+
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:
Code:
p=5
while p<100:
    n_values=[]
    b_value=1
    while len(n_values)<6:
        K=GF(p)
        a=K(0)
        b=K(b_value)
        E=EllipticCurve(K,(a,b))
        n=E.order()
        if n == p+1:
            n_values.append(n)
            n_values.append(n)
            n_values.append(n)
            n_values.append(n)
            n_values.append(n)
            n_values.append(n)
        else:
            if n not in n_values:
                n_values.append(n)
            b_value+=1
    if n_values[0] != p+1:
        print(p,n_values)
    p=next_prime(p)
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:
Code:
7 [12, 9, 13, 3, 7, 4]
13 [12, 19, 9, 21, 16, 7]
19 [12, 13, 21, 27, 28, 19]
31 [36, 43, 39, 21, 25, 28]
37 [48, 49, 39, 37, 28, 27]
43 [36, 52, 49, 39, 31, 57]
61 [48, 61, 75, 63, 76, 49]
67 [84, 73, 52, 57, 63, 79]
73 [84, 81, 57, 91, 64, 67]
79 [84, 63, 97, 93, 67, 76]
97 [84, 117, 93, 79, 103, 112]
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.
The secp256k1 you created for testing how did it go?
jovica888 (OP)
Jr. Member
*
Offline Offline

Activity: 57
Merit: 17


View Profile
February 20, 2025, 01:32:45 PM
Last edit: May 09, 2025, 07:46:20 AM by mprep
 #7

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

Code:
iteration * 300.000.000 * (some fixed number) + Iteration....
For example

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

Code:
import secp256k1 as ice
import os

# Starting point
P = ice.pub2upub('02145d2611c823a396ef6712ce0f712f09b9b4f3135e3e0aa3230fb9b6d08d1e16')

batch_size = 30_000_000
max_lines = 300_000_000
babystep_file = "babystep.txt"

if os.path.exists(babystep_file):
    with open(babystep_file, "r") as f:
        line_count = sum(1 for _ in f)
else:
    line_count = 0

with open(babystep_file, "a") as f:
    while line_count < max_lines:
        print(f"Generating {batch_size} BSGS points...")
        bsgs_batch = ice.point_sequential_increment(batch_size, P)
       
        for i in range(batch_size):
            hex_string = bsgs_batch[i * 65: i * 65 + 65].hex()
            x_hex = hex_string[2:18] 
            f.write(f"{x_hex}\n")
            line_count += 1
           
            if line_count >= max_lines:
                break
       
        P = ice.pub2upub(bsgs_batch[-65:].hex())
        print(f"Current generating: {line_count}/{max_lines} lines.")

print("Generating of 300.000.000 lines completed.")



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

Code:
import secp256k1 as ice

def ECsubtract(Q1,Q2):# compressed or uncompressed pubkey
    Q1=ice.pub2upub(Q1)
    Q2=ice.pub2upub(Q2)
    sub=ice.point_negation(Q2)# -Q2
    return (ice.point_addition(Q1,sub).hex()) #Q1 - Q2


public_key=ECsubtract('02145d2611c823a396ef6712ce0f712f09b9b4f3135e3e0aa3230fb9b6d08d1e16','02cbb434aa7ae1700dcd15b20b17464817ec11715050e0fa192ffe9c29a673059f')
print(public_key)

02cbb434aa7ae1700dcd15b20b17464817ec11715050e0fa192ffe9c29a673059f = 4000000000000000000000000000000000 * G

I got this point
Code:
04a8c204d9e0cd0e7f6da825d55b5c2b9d0093f96650bf37e67bc802189b3bc47837bbe3fd17f83a190242af1da9673c468f504b37ba276554a9724ea479124d87
Upper region point is
Code:
04a8c204d9e0cd0e7f6da825d55b5c2b9d0093f96650bf37e67bc802189b3bc478c8441c02e807c5e6fdbd50e25698c3b970afb4c845d89aab568db15a86edaea8
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

Code:
priv_key = (n - (G_added - G_at_collision) // 2 - G_at_collision) % n

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

Code:
import ecdsa
from ecdsa.ellipticcurve import Point
import time

# Parameters of the secp256k1 elliptic curve
curve = ecdsa.curves.SECP256k1.curve
G = ecdsa.curves.SECP256k1.generator
n = ecdsa.curves.SECP256k1.order

# Initial point
X = 0x440daba3905488f1b5ad2186f6ce2e9a9fe69327ac975dba1a93f8ed60d7813d
Y = 0x9d656a2ee1049d7bf9c4b48c4df47e92115b0a479c60ba1034c9c2e7a39d2f0c

P = Point(curve, X, Y)

visited_x = {}  # Store X coordinates in RAM
G_added = 0  # Total G added
start_time = time.time()  # Start time
last_print_time = start_time  # Track last print time
iteration = 0  # Track current iteration

while True:
    last5 = X & 0xFFFFF  # Last 5 digits of X-axis
    step = last5 + 1  # Step size
    P = P + step * G  # Jump forward
    X = P.x()
    G_added += step
    iteration += 1
   
    current_time = time.time()
    if current_time - last_print_time >= 5:
        print(f"Total G added: {hex(G_added)}, Current Iteration: {iteration}, Current step: {step}", end="\r")
        last_print_time = current_time
   
    if X in visited_x:
        G_at_collision = visited_x[X]
        priv_key = (n - (G_added - G_at_collision) // 2 - G_at_collision) % n
        end_time = time.time()
        elapsed_time = end_time - start_time
        hours, rem = divmod(elapsed_time, 3600)
        minutes, seconds = divmod(rem, 60)
        print(f"\nPrivate key found: {hex(priv_key)}")
        print(f"Time taken: {int(hours)}h {int(minutes)}m {int(seconds)}s")
        break
    else:
        visited_x[X] = G_added

I know that the code is slow but it finds a solution

Code:
Total G added: 0x11a4b3bb783, Current Iteration: 2312884, Current step: 699786
Private key found: 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25d8a18d30c97
Time taken: 0h 3m 19s

So original private key is
Code:
n - fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25d8a18d30c97
hex 102B76334AA
dec 1111178294442

[moderator's note: consecutive posts merged]
NotATether
Legendary
*
Offline Offline

Activity: 2100
Merit: 8931


Search? Try talksearch.io


View Profile WWW
February 22, 2025, 06:26:19 AM
 #8

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.

██
██
██
██
██
██
██
██
██
██
██
██
██
... LIVECASINO.io    Play Live Games with up to 20% cashback!...██
██
██
██
██
██
██
██
██
██
██
██
██
jovica888 (OP)
Jr. Member
*
Offline Offline

Activity: 57
Merit: 17


View Profile
February 22, 2025, 11:50:49 AM
Last edit: February 22, 2025, 12:15:50 PM by jovica888
Merited by vapourminer (1)
 #9

I was using this website
https://asecuritysite.com/ecc/ecc_points_mult

I was putting random p-prime numbers, then "manually" Smiley 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)

Code:
P	(1,1)   	Point is on curve
2P (2,1)   Point is on curve
3P (4,6)   Point is on curve
4P (4,1)   Point is on curve
5P (2,6)   Point is on curve
6P (1,6)   Point is on curve
7P=0

JackMazzoni
Jr. Member
*
Offline Offline

Activity: 158
Merit: 6


View Profile
March 13, 2025, 10:15:06 AM
 #10

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)

Need Wallet Recovery? PM ME. 100% SAFE
LeTH3knXoDArzm
Newbie
*
Offline Offline

Activity: 11
Merit: 10


View Profile
March 13, 2025, 10:50:11 AM
Last edit: March 13, 2025, 11:34:03 AM by LeTH3knXoDArzm
Merited by JackMazzoni (1)
 #11

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)

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

Code:
from ecdsa.ellipticcurve import Point
from ecdsa.curves import SECP256k1

# secp256k1 parameters
curve = SECP256k1.curve
p = curve.p()
G = SECP256k1.generator

# Compute β = 2^((p-1)/3) mod p
beta   = pow(2, (p - 1) // 3, p)
beta2  = 60197513588986302554485582024885075108884032450952339817679072026166228089408
lmbda  = 37718080363155996902926221483475020450927657555482586988616620542887997980018
lmbda2 = 78074008874160198520644763525212887401909906723592317393988542598630163514319

# print(p)
def parse_pubkey(pubkey: str):
    """Extracts x, y coordinates from an uncompressed '04' format public key."""
    if not pubkey.startswith('04') or len(pubkey) != 130:
        raise ValueError("Invalid uncompressed public key format")
    x = int(pubkey[2:66], 16)
    y = int(pubkey[66:], 16)
    return Point(SECP256k1.curve, x, y, SECP256k1.order)

# beta * P.x == lambda * P (mod p)
def endomorphism(P: Point) -> Point:
    x_new = (beta * P.x()) % p
    return Point(curve, x_new, P.y())
# p - P.y() == inverse of p * G (mod p) (negation of y)
def endomorphism2(P: Point) -> Point:
    # x_new = ( P.x() * beta2) % p
    y_new = ( p - P.y() ) % p
    return Point(curve, P.x(), y_new)

def endomorphism3(P: Point) -> Point:
    x_new = (beta2 * P.x()) % p
    return Point(curve, x_new, P.y())
def endomorphism4(P: Point) -> Point:
    x_new = (beta * P.x()) % p
    y_new = (p - P.y()) % p
    return Point(curve, x_new, y_new)
def endomorphism5(P: Point) -> Point:
    x_new = (beta2 * P.x()) % p
    y_new = (p - P.y()) % p
    return Point(curve, x_new, y_new)



pubkey = "042f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4d8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6"
# compute given public key or P integer, decomment one or another.
P = 6 * G
# P = parse_pubkey(pubkey)

P_endomorph = endomorphism(P)
P_endomorph2 = endomorphism2(P)
P_endomorph3 = endomorphism3(P)
P_endomorph4 = endomorphism4(P)
P_endomorph5 = endomorphism5(P)

print("Original P  :", (P.x(), P.y()))
print(f"Originak P key 04{P.x():x}{P.y():x}")
print('---------------------------------')
print("Endomorph P [beta * P.x == lambda * P (mod p)]:", (P_endomorph.x(), P_endomorph.y()))
print(f"Endomorph φ(P) key 04{P_endomorph.x():064x}{P_endomorph.y():064x}")
print('---------------------------------')
print("Endomorph2 P [p - P.y() == inverse of p * G (mod p) (negation of y)]:", (P_endomorph2.x(), P_endomorph2.y()))
print(f"Endomorph2 φ(P) key 04{P_endomorph2.x():x}{P_endomorph2.y():x}")
print('---------------------------------')
print("Endomorph3 P [beta2 * P.x == 2nd beta iteration]:", (P_endomorph3.x(), P_endomorph3.y()))
print(f"Endomorph3 φ(P) key 04{P_endomorph3.x():x}{P_endomorph3.y():x}")
print('---------------------------------')
print("Endomorph4 P [x*beta%p, p-y == N-pvk*lmda%N]:", (P_endomorph4.x(), P_endomorph4.y()))
print(f"Endomorph4 φ(P) key 04{P_endomorph4.x():x}{P_endomorph4.y():x}")
print('---------------------------------')
print("Endomorph5 P [x*beta2%p, p-y == N-pvk*lmda2%N]:", (P_endomorph5.x(), P_endomorph5.y()))
print(f"Endomorph5 φ(P) key 04{P_endomorph5.x():x}{P_endomorph5.y():x}")
mjojo
Newbie
*
Offline Offline

Activity: 77
Merit: 0


View Profile
March 15, 2025, 05:52:31 AM
 #12

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)

would you share the code or script for above output?
Geshma
Newbie
*
Offline Offline

Activity: 19
Merit: 0


View Profile
March 15, 2025, 01:44:53 PM
 #13

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})")
mjojo
Newbie
*
Offline Offline

Activity: 77
Merit: 0


View Profile
March 16, 2025, 12:50:10 AM
 #14

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})")

Thankyou @Geshma
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!