I was looking only for public key generation part
Here's a simplified script that generates compressed public keys from a given range of private keys:
import hashlib, sys
import gmpy2
# Constants as mpz
Gx = gmpy2.mpz('0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798', 16)
Gy = gmpy2.mpz('0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8', 16)
p = gmpy2.mpz('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F', 16)
n = gmpy2.mpz('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141', 16)
def private_key_to_public_key(private_key):
Q = point_multiply(Gx, Gy, private_key, p)
return Q
def point_multiply(x, y, k, p):
result = (gmpy2.mpz(0), gmpy2.mpz(0))
addend = (x, y)
while k > 0:
if k & 1:
result = point_add(result, addend, p)
addend = point_double(addend, p)
k >>= 1
return result
def point_double(point, p):
x, y = point
lmbda = (3 * x * x * gmpy2.powmod(2 * y, -1, p)) % p
x3 = (lmbda * lmbda - 2 * x) % p
y3 = (lmbda * (x - x3) - y) % p
return x3, y3
def point_add(point1, point2, p):
x1, y1 = point1
x2, y2 = point2
if point1 == (gmpy2.mpz(0), gmpy2.mpz(0)):
return point2
if point2 == (gmpy2.mpz(0), gmpy2.mpz(0)):
return point1
if point1 != point2:
lmbda = ((y2 - y1) * gmpy2.powmod(x2 - x1, -1, p)) % p
else:
lmbda = ((3 * x1 * x1) * gmpy2.powmod(2 * y1, -1, p)) % p
x3 = (lmbda * lmbda - x1 - x2) % p
y3 = (lmbda * (x1 - x3) - y1) % p
return x3, y3
def encode_base58(byte_str):
__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
__b58base = len(__b58chars)
long_value = gmpy2.mpz(int.from_bytes(byte_str, byteorder='big'))
result = ''
while long_value >= __b58base:
div, mod = gmpy2.f_divmod(long_value, __b58base)
result = __b58chars[int(mod)] + result
long_value = div
result = __b58chars[int(long_value)] + result
# Add leading '1's for zero bytes
nPad = 0
for byte in byte_str:
if byte == 0:
nPad += 1
else:
break
return __b58chars[0] * nPad + result
def public_key_to_hex(public_key, compressed=True):
x_hex = format(public_key[0], '064x')[2:] # Remove '0x' prefix
if compressed:
# Use '02' prefix if Y coordinate is even, '03' if odd
return ('02' if public_key[1] % 2 == 0 else '03') + x_hex
def public_key_to_address(public_key, compressed=True):
public_key_hex = ('02' if compressed else '04') + format(public_key[0], '064x')
sha256_hash = hashlib.sha256(bytes.fromhex(public_key_hex)).digest()
ripemd160_hash = hashlib.new('ripemd160', sha256_hash).digest()
versioned_hash = (b'\x00' if compressed else b'\x04') + ripemd160_hash
checksum = hashlib.sha256(hashlib.sha256(versioned_hash).digest()).digest()[:4]
address_bytes = versioned_hash + checksum
return encode_base58(address_bytes)
# Define the range
start_range = gmpy2.mpz('36893488147419132058')
end_range = gmpy2.mpz('36893488149419115809')
# Iterate through the range and generate Bitcoin Addresses (Compressed) and their Public Keys
for key in range(start_range, end_range + 1):
public_key = private_key_to_public_key(key)
bitcoin_address = public_key_to_address(public_key, compressed=True)
public_key = public_key_to_hex(public_key)
sys.stdout.write("\033c")
sys.stdout.write("\033[01;33m")
sys.stdout.write(f"\r[+] Private Key (dec): {key}\n[+] Bitcoin Address (Compressed): {bitcoin_address}\n[+] Public Key: {public_key}" + "\n")
sys.stdout.flush()
Mobile phones typically run Android or iOS. Python can be run on both platforms, but there are some differences in compatibility..
For Android, you can use the QPython app or Termux to run Python scripts. On iOS, you might need to use apps like Pythonista or Pyto.
It may require a lot of CPU power and memory. Make sure your mobile phone can handle the computational requirements.
You can even translate this script into a mobile app but I don't see the purpose of it on the phone. Neither the script will work as it should nor the phone.
Lovely. However "def public_key_to_address" behaves not right if "compressed=False". Would you mind taking a look at it?