Author

Topic: Script to take convert Hex private key to bitcoin address. (Read 49 times)

sr. member
Activity: 448
Merit: 560
Crypto Casino and Sportsbook
ORIGINAL TOPIC: Converting HEX private key to bitcoin address
AUTHOR:  witcher_sense



Around that kind one week or so, I come decide say na d perfect time for me to start to de learn ho to take program and after i don do some research, i come conclude say na Phyton go be better programming language for me to take start with. For my own opinion, the best way to take learn something na to de practice and many many times, dis na d reason y I think say to de write programs na d best way to take learn how to de write better program. By say I combine my theoretical interest for  Bitcoin come join practical interest for programming, I believe say I fit create things way dem fit use  ( way relate to Bitcoin and other  fields) way I dey read about before and make them  dey "real."

For under here na program way Dey take private key for  hex format, come convert am to WIF (d one way dem compress and and d one way dem no compress), com calculate public keys (d one way dem compress and and d one way dem no compress) and the address dem way follow am . I collect Functions way Dey do elliptic curve calculation (modulo inverse, point addition, doubling and multiplication) and elliptic curve parameters  from here: https://github.com/wobine/blackboard101

Code:
import hashlib
import base58

class PublicKey:
    """Calculating public key from private key"""

    def __init__(self, private_key):
        """Initialize parameters of an elliptic curve"""

        self.private_key = private_key
        self.p_curve = 2**256 - 2**32 - 2**9 - 2**8 - 2**7 - 2**6 - 2**4 - 1 # The proven prime
        self.n_curve = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 # Number of points in the field
        self.a_curve, self.b_curve = 0, 7 # These two defines the elliptic curve. y^2 = x^3 + Acurve * x + Bcurve
        self.gx = 55066263022277343669578718895168534326250603453777594175500187360389116729240
        self.gy = 32670510020758816978083085130507043184471273380659243275938904335757337482424
        self.gpoint = (self.gx, self.gy) # This is generator point.

    def hash(self, key):
        """Function performing SHA-256 hashing"""

        sha = hashlib.sha256()
        sha.update(bytes.fromhex(key))
        return sha.hexdigest()

    def public_address(self, key):
        """Function calculating address"""

        ripemd = hashlib.new('ripemd160')
        sha = hashlib.sha256()
        sha.update(bytes.fromhex(key))
        ripemd.update(sha.digest())
        address = f"00{ripemd.hexdigest()}"
        checksum = self.hash(self.hash(address))[:8]
        address = f"{address}{checksum}"
        address = base58.b58encode(bytes.fromhex(address)).decode("UTF-8")
        return address

    def privatewif(self):
        """Converting a private key to WIF"""

        private_wif = f"80{hex(self.private_key)[2:]}"
        private_wif_comp = f"80{hex(self.private_key)[2:]}01"

        checksum = self.hash(self.hash(private_wif))[:8]
        checksum_comp = self.hash(self.hash(private_wif_comp))[:8]

        private_wif = f"{private_wif}{checksum}"
        private_wif_comp = f"{private_wif_comp}{checksum_comp}"

        private_wif = base58.b58encode(bytes.fromhex(private_wif)).decode("UTF-8")
        private_wif_comp = base58.b58encode(bytes.fromhex(private_wif_comp)).decode("UTF-8")

        print(f"\nWIF - private key\n{private_wif}")
        print(f"Length: {len(private_wif)}\n")
        print(f"WIF compressed - private key\n{private_wif_comp}")
        print(f"Length: {len(private_wif_comp)}\n")

    def modinv(self, a, n):
        """Extended Euclidean Algorithm"""

        lm, hm = 1, 0
        low, high = a%n, n
        while low > 1:
            ratio = int(high/low)
            nm, new = int(hm-lm*ratio), int(high-low*ratio)
            lm, low, hm, high = nm, new, lm, low
        return lm % n

    def ec_add(self, a, b):
        """Point addition"""

        lam_add = ((b[1]-a[1]) * self.modinv(b[0]-a[0], self.p_curve)) % self.p_curve
        x = (pow(lam_add, 2)-a[0]-b[0]) % self.p_curve
        y = (lam_add*(a[0]-x)-a[1]) % self.p_curve
        return x, y

    def ec_double(self, a):
        """EC point doubling"""

        lam = ((3*a[0]*a[0]+self.a_curve) * self.modinv((2*a[1]), self.p_curve)) % self.p_curve
        x = int((lam*lam-2*a[0]) % self.p_curve)
        y = int((lam*(a[0]-x)-a[1]) % self.p_curve)
        return x, y

    def ec_multiply(self, genpoint, scalarhex):
        """EC point multiplication"""

        if scalarhex == 0 or scalarhex >= self.n_curve: raise Exception("Invalid Scalar/Private Key")
        scalarbin = str(bin(scalarhex))[2:]
        q = genpoint
        for i in range (1, len(scalarbin)): #Double and add to multiply point
            q = self.ec_double(q)
            if scalarbin[i] == "1":
                q = self.ec_add(q, genpoint)
        return q

    def public_calc(self):
        """Calculating a public key"""

        public_key = self.ec_multiply(self.gpoint, self.private_key)
        print("\nThe uncompressed public key (not address):")
        print(public_key)
        print("\nThe uncompressed public key (HEX):")
        message = f"04{(hex(public_key[0])[2:]):0>64}{(hex(public_key[1])[2:]):0>64}"
        print(message)
        print(f"Length: {len(message)}\n")
        message = self.public_address(message)
        print(f"Address from uncompressed key\n{message}")
        print("\nThe official Public Key - compressed:")
        if public_key[1] % 2 == 1: # If the Y value for the Public Key is odd.
            message = f"03{hex(public_key[0])[2:]:0>64}"
            print(message)
            print(f"Length: {len(message)}\n")
            message = self.public_address(message)
            print(f"Address from compressed key\n{message}")
        else: # Or else, if the Y value is even.
            message = f"02{hex(public_key[0])[2:]:0>64}"
            print(message)
            print(f"Length: {len(message)}\n")
            message = self.public_address(message)
            print(f"Address from compressed key\n{message}")

prompt = input(f"Please insert your private key in HEX format (0x): ")

try:
    prompt = int(prompt, 16)  # interpret the input as a base-16 number, a hexadecimal.
except ValueError:
    print("You did not enter a hexadecimal number!")
my_key = PublicKey(prompt)
my_key.public_calc()
my_key.privatewif()


Source code also dey available for here: https://github.com/witcher-sense/learning_python/blob/main/PrivateToPublic.py

E go only work with Python 3.6 or d one way pass am , and you go need to make some kind changes to openssl.conf to take make sure say RIPEMD160 hashing go work well.

If you de use Linux, then you fit do the things way De under here:

To take  find where configuration file de , u go need to put the command way follow so:
Code:
openssl version -d

You go Copy the path come change the directory way you de work with, for example:
Code:
cd /usr/lib/ssl/

Open openssl.conf for inside any text editor. You go need super user right to take  edit this file. If you nor get am , ask your administrator for help:

Code:
sudo nano openssl.conf

Add the lines way follow  so join the configuration file (some of them don already dey there and some dey  wait for "uncommenting"):

Code:
openssl_conf = openssl_init

[openssl_init]
providers = provider_sect

[provider_sect]
default = default_sect
legacy = legacy_sect

[default_sect]
activate = 1

[legacy_sect]
activate = 1


After you don do all  these manipulation, RIPEDMD suppose start to dey work.
Jump to: