I am currently new in Python and cryptography. I am trying to make a public key of SECP256K1 elliptic curve manually(without related library use), from a random generated private key as I learned. The method of generating private key is free. What matters is the process making the public key out of it.
This is what I have.
import random
import os
import time
import hashlib
def generate_private_key():
global P
while(True):
key=str(random.random())+str(os.urandom(100))+str(time.time())
key=hashlib.sha256(key.encode())
key=int(key.hexdigest(),16)
if(P>key):
return key
def generate_public_key(private_key):
global G
global P
bit=list(bin(private_key)[2:])
point=(0,0)
for i in bit:
if i=='0':
point=point_double(point, P)
elif i=='1':
point=point_double(point, P)
point=point_add(point,G, P)
return point
#Extended Euclidean Algorithm
def inverse(b,n):
r1=n
r2=b
t1=0
t2=1
while(r2>0):
q=r1//r2
t=t1-q*t2
t1=t2
t2=t
r=r1-q*r2
r1=r2
r2=r
if t1>0: return t1
else: return t1+t2
def point_double(point, P):
(x,y)=point
lam=3*(x**2)*inverse(2*y,P)
xsum=lam**2-x*2
ysum=lam*(x-xsum)-y
return xsum%P, ysum%P
def point_add(p1, p2, P):
(x1,y1)=p1
(x2, y2)=p2
if x1==x2 and y1==y2:
return point_double(p1)
lam=(y2-y1)*inverse(x2-x1, P)
xsum= lam**2-(x1+x2)
ysum= lam*(x1-xsum)-y1
return xsum%P, ysum%P
P=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
G = (0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,
0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8)
private_key=generate_private_key()
#my private key
print(hex(private_key))
#public key
print(generate_public_key(private_key))
I am comparing my code's result with this website's result: https://paulmillr.com/noble/ However, I can't get a same public key out of the same private key.
This is the process what I think:
- Create a random private key.
- Create a public key using (private key * a fixed point G)
2-1. Use Double-and-Add method to avoid adding up G [private key] times because both numbers are too big to do so.
2-2. All additions are followed by (mod P). P is also a very big number, fixed.
2-3. All divisions are not literally divisions. It is an inverse of (mod P). Solving the inverse of (mod P) is done by using Extended Euclidean Algorithm('inverse' function in code).
Since I wasn't sure where to put the '%P' in code, I tried several places putting '%P', but no luck so far and ended up with the current code. I couldn't actually test the result step by step because the numbers and the amount of process were too big.