Reputation: 39
I have a question about a script I am trying to write that generates a key pair for Bitcoin adreses. I came as far as generating a random private key and generate a public key. I know (or think really much?) that my first part of code is correct. When I go to bitaddress.org and check my generated private keys for details, I always get the correct generated public key.
This is what I have now
import os
import ecdsa
import binascii
private_key = binascii.hexlify(os.urandom(32)).decode()
print("private key = " + private_key)
Private_key = bytes.fromhex(private_key)
signing_key = ecdsa.SigningKey.from_string(Private_key, curve = ecdsa.SECP256k1)
verifying_key = signing_key.get_verifying_key()
public_key = bytes.fromhex("04") + verifying_key.to_string()
print ("public key = " + public_key.hex())
The problem is that for now Im getting the 130 characters public key and I want to transform this to a bitcoin address. I don't understand how to do this. I need to do some encoding/decoding but can't wrap my head around it. This is the explanation from the internet I found but fail to understand:
Bitcoin address explanation png
Could someone maybe help me with this
Upvotes: 2
Views: 6224
Reputation: 454
This code runs both in Python 2 and Python 3. It prints not only the bitcoin address, but also some intermediate values. The public key is the 130 hex char string in pubkey variable.
Please note that there are two possible and valid bitcoin addresses for each public key: the uncompressed and the compressed form. Change compress_key boolean variable to extract each one.
#!/usr/bin/env python
# https://en.bitcoin.it/wiki/Protocol_documentation#Addresses
import hashlib
import base58
# ECDSA bitcoin Public Key
pubkey = '0450863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b23522cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6'
# See 'compressed form' at https://en.bitcoin.it/wiki/Protocol_documentation#Signatures
compress_pubkey = False
def hash160(hex_str):
sha = hashlib.sha256()
rip = hashlib.new('ripemd160')
sha.update(hex_str)
rip.update( sha.digest() )
print ( "key_hash = \t" + rip.hexdigest() )
return rip.hexdigest() # .hexdigest() is hex ASCII
if (compress_pubkey):
if (ord(bytearray.fromhex(pubkey[-2:])) % 2 == 0):
pubkey_compressed = '02'
else:
pubkey_compressed = '03'
pubkey_compressed += pubkey[2:66]
hex_str = bytearray.fromhex(pubkey_compressed)
else:
hex_str = bytearray.fromhex(pubkey)
# Obtain key:
key_hash = '00' + hash160(hex_str)
# Obtain signature:
sha = hashlib.sha256()
sha.update( bytearray.fromhex(key_hash) )
checksum = sha.digest()
sha = hashlib.sha256()
sha.update(checksum)
checksum = sha.hexdigest()[0:8]
print ( "checksum = \t" + sha.hexdigest() )
print ( "key_hash + checksum = \t" + key_hash + ' ' + checksum )
print ( "bitcoin address = \t" + base58.b58encode( bytes(bytearray.fromhex(key_hash + checksum)) ) )
Upvotes: 1