Python 2.7 Converting Bitcoin Privkey to WIF Privkey
I just went through the tutorial as a newbie to coding. The tutorial was as follows: https://www.youtube.com/watch?v=tX-XokHf_nI . And I wanted to generate my bitcoin / privkeys addresses with one simple, easy-to-read (not cryptic) Python file - just as the code is written right now.
The tutorial ended up in the part where I got a bitcoin address starting with "1" but not with a jury starting with "5". Plus I am missing how BIP38 encrypts the private key (starting at "6"). This is, as you can see, for the main Bitcoin network.
Using https://en.bitcoin.it/wiki/Wallet_import_format as a step-by-step guide after the tutorial. At the end, I commented on my attempts to do it myself, because it was all rubbish. (The part with "SHA256 HASHED EXTENDED PRIVATE KEY THIS IS WRONG ON MANY LEVELS") I think the part where I added 80 bytes to the private key might be correct.
PS: I am using a static private key until now until everything works, so I commented out the non-static private key. It was generated through the part in which I commented on the use of "non-static secret key usage". I also commented out the lines of code of signed messages (at the bottom of the code) because they were shown in the tutorial, which is not important for key / address generation. I also tried to "decorate" the code a bit by placing prints, etc. Only at the bottom of the file and sorting a few things, etc., but it turned out that Python 2.7 didn't like it.
I am using Python 2.7, everything is installed successfully, the code works as it is now, with parts commented out. I checked the results printed with bitaddress.org the same as the bootloader from the tutorial. Tried searching to find a solution, but I couldn't get anything useful from the search results.
If you could help me with a few missing lines of code, I'd be happy! Also maybe explain / comment on the code what to do. Especially for the still missing BIP38 Privkey password encryption. So I can understand what and what can understand.
Running the .py script returns valid results except for the 80 bytes I added - no idea if this was fixed by me. Adding 80 bytes is a necessary step to get the final private key, starting at "5" later.
Start printing:
This is my Private Key: 29a59e66fe370e901174a1b8296d31998da5588c7e0dba860f11d65a3adf2736
This is my 80 Byte Private Key: 8029a59e66fe370e901174a1b8296d31998da5588c7e0dba860f11d65a3adf2736
This is my Public Key: 04d370b77a4cf0078ab9e0ba3c9e78e8dd87cc047fa58d751b3719daa29ac7fbf2c3ba8338f9a08f60a74a5d3a2d10f26afa2f703b8c430eecad89d59a9df00ec5
This is my Bitcoin Address: 1B3wS8dQHtfMpFMSmtT5Fy4kHCYvxejtVo
Here you can see my code commented here and there as far as I could, according to the tutorial: (Forgot to comment "This is my hashed external key checksum", sorry for the confusion. This is the code I need now.)
import os
import ecdsa
import hashlib
import base58
## STATIC KEY USAGE
private_key_static = "29a59e66fe370e901174a1b8296d31998da5588c7e0dba860f11d65a3adf2736"
## PRINTOUT FROM STATIC PRIVATE KEY
print "This is my Private Key: " + private_key_static
## NON STATIC PRIVATE KEY USAGE
#private_key = os.urandom(32).encode("hex")
#print "this is my private key: " + private_key
## 80-BYTE EXTENDED PRIVATE KEY
private_key_plus_80byte = (('80') + private_key_static)
## PRINTOUT 80-BYTE EXTENDED PRIVATE KEY
print "This is my 80 Byte Private Key: " + private_key_plus_80byte
## SHA256 HASHED EXTENDED PRIVATE KEY
## THIS IS WRONG ON SO MANY LEVELS
#hashed_ext_priv_key_checksum = hashlib.sha256(hashlib.sha256(private_key_plus_80byte).digest()).digest()[:4]
#hashed_ext_priv_key_checksum = hashed_ext_priv_key_checksum.decode("hex")
#print "This is my hashed ext priv key checksum: " + hashed_ext_priv_key_checksum
## PRIVATE! SIGNING KEY ECDSA.SECP256k1
sk = ecdsa.SigningKey.from_string(private_key_static.decode("hex"),
curve = ecdsa.SECP256k1)
## PUBLIC! VERIFYING KEY (64 BYTE LONG, MISSING 04 BYTE AT THE BEGINNING)
vk = sk.verifying_key
## PUBLIC KEY
public_key = ('\04' + vk.to_string()).encode("hex")
## PRINTOUT PUBLIC KEY
print "This is my Public Key: " + public_key
## PUBLIC KEY ENCODING (2x RIPEMD160)
ripemd160 = hashlib.new('ripemd160')
ripemd160.update(hashlib.sha256(public_key.decode('hex')).digest())
middle_man = ('\00') + ripemd160.digest()
checksum = hashlib.sha256(hashlib.sha256(middle_man).digest()).digest()[:4]
binary_addr = middle_man + checksum
addr = base58.b58encode(binary_addr)
print "This is my Bitcoin Address: " + addr
## MESSAGE CONTENT
#msg = "hello world"
## SIGN MESSAGE CONTENT
#signed_msg = sk.sign(msg)
## VERIFY MESSAGE CONTENT
#assert vk.verify(signed_msg, "hello world")
## PRINTOUT SIGNED MESSAGE ENCODED TO HEX
#print "This is a HEX encoded signed Message: " + signed_msg.encode("hex")
source to share
What you probably misunderstood from the Bitcoin Wiki steps is that all hashing and stuff should be done on the keys as bytes , not strings.
This means that if you want to get the WIF key from the private key "29a59..."
, you don't need to hash the string "8029a59..."
but the binary data that matches it.
A snippet is missing here that works
# importing binascii to be able to convert hexadecimal strings to binary data
import binascii
# Step 1: here we have the private key
private_key_static = "29a59e66fe370e901174a1b8296d31998da5588c7e0dba860f11d65a3adf2736"
# Step 2: let add 80 in front of it
extended_key = "80"+private_key_static
# Step 3: first SHA-256
first_sha256 = hashlib.sha256(binascii.unhexlify(extended_key)).hexdigest()
# Step 4: second SHA-256
second_sha256 = hashlib.sha256(binascii.unhexlify(first_sha256)).hexdigest()
# Step 5-6: add checksum to end of extended key
final_key = extended_key+second_sha256[:8]
# Step 7: finally the Wallet Import Format is the base 58 encode of final_key
WIF = base58.b58encode(binascii.unhexlify(final_key))
print (WIF)
where binascii.unhexlify(...)
tells us the binary data, represented as a hex string.
The rest of your code works just fine;)
source to share