Changing curve parameters
import collections
import hashlib
# ...
def point_add(point1, point2):
if point1 is None:
return point2
if point2 is None:
return point1
x1, y1 = point1
x2, y2 = point2
if x1 == x2 and y1 != y2:
return None
if point1 == point2:
m = (3 * x1 * x1 + curve.a) * pow(2 * y1, -1, curve.p)
else:
m = (y2 - y1) * pow(x2 - x1, -1, curve.p)
x3 = (m * m - x1 - x2) % curve.p
y3 = (m * (x1 - x3) - y1) % curve.p
return (x3, y3)
# ... (Rest of your code remains the same)
EllipticCurve = collections.namedtuple('EllipticCurve', 'name p a b g n h')
curve = EllipticCurve(
'secp256k1',
# Field characteristic.
p=0x7027,
# Curve coefficients.
a=0,
b=7,
# Base point.
g=(0x1,
0x2),
# Subgroup order.
n=0x6997,
# Subgroup cofactor.
h=1,
)
# Functions that work on curve points #
def is_on_curve(point):
"""Returns True if the given point lies on the elliptic curve."""
if point is None:
# None represents the point at infinity.
return True
x, y = point
return (y * y - x * x * x - curve.a * x - curve.b) % curve.p == 0
def scalar_mult(k, point):
"""Returns k * point computed using the double and point_add algorithm."""
if k % curve.n == 0 or point is None:
return None
if k < 0:
# k * point = -k * (-point)
return scalar_mult(-k, point_neg(point))
result = None
addend = point
while k:
if k & 1:
# Add.
result = point_add(result, addend)
# Double.
addend = point_add(addend, addend)
k >>= 1
return result
# Private key
private_key = 3
# Generate public key from the private key
public_key = scalar_mult(private_key, curve.g)
print('Curve: ', curve.name)
print('Generator point:\n(0x{:x},\n 0x{:x})'.format(*curve.g))
print('\n\n')
print('Private key:\n', private_key)
print('\n')
print('Public key:\n(0x{:x},\n 0x{:x})'.format(*public_key))
It will print g, private key and new x, y public key coordinates for your input key.
Credit: I just know I changed a few things, but I didn't write equations.
Edit:
Finding prime (P) for 0, 7, a, b curve
This one is much faster in finding prime candidates for a given curve.
import math
def is_prime(n, k=10000):
"""Test if a number is prime using Miller-Rabin test."""
if n < 2:
return False
# Check for small primes
for p in (2, 3, 5, 7, 11, 13, 17, 19, 23, 29):
if n % p == 0:
return n == p
# Perform Miller-Rabin test
s, d = 0, n-1
while d % 2 == 0:
s, d = s+1, d//2
for _ in range(k):
a = random.randint(2, n-2)
x = pow(a, d, n)
if x == 1 or x == n-1:
continue
for _ in range(s-1):
x = pow(x, 2, n)
if x == n-1:
break
else:
return False
return True
def generate_prime(n):
"""Generate a random n-bit prime using Miller-Rabin test."""
while True:
p = random.getrandbits(n)
# Set the MSB and LSB to 1 to ensure n bits and odd number
p |= (1 << n-1) | 1
if is_prime(p):
return p
# Generate any bit prime
p = generate_prime(256)
print("Generated prime:", p)
Ps, I'm working on a theory to speed up the brute force operations by thousands of %s. By using a small p and converting secp256k1 points in to a much more smaller points representing in a new curve in order to compute +, -, *, / faster. God willing when I find a working script, I will share it here.😉