I made a program that makes Bitcoin Address with random private key. Some variables and methods that do not have a separate description are the fixed values of the SECP256K1 elliptic curve. As they are not related to errors, I omitted them.
get_private_key method returns random 256 bit int private key.
def get_private_key():
while (True):
random_str = os.urandom(256 // 8) + str(random.random()).encode() + str(time.time()).encode()
random_num = hashlib.sha256(random_str).digest()
private_key = int.from_bytes(random_num, 'big')
if private_key < q-1:
break
return private_key
And generate the public key in the following method. (double_and_add method returns tuple that has two add-calculated 256 bit ints.) get_compressed_public_key method returns 33bytes hexadecimal number in string without 0x.
def get_compressed_public_key(key):
public_key = double_and_add(key, G)
if public_key[1] % 2 == 0 :
return "02" + str(hex(public_key[0]))[2:]
else :
return "03" + str(hex(public_key[0]))[2:]
generate_bitcoin_address method returns 25byte btcoin address with hash160 method and returns 25byte bitcoin address.
def hash160(data):
sha256_hash = SHA256.new(data)
ripemd160_hash = RIPEMD160.new(sha256_hash.digest())
return ripemd160_hash.hexdigest()
def generate_bitcoin_address(key):
# Generate compressed public key
hex_val = int(key, 16)
compressed_pkey = get_compressed_public_key(hex_val)
**data = bytes.fromhex(compressed_pkey)**
hash160_val = "00" + hash160(data)
print("Public Key's hash =", hash160_val)
# Get Checksum Value
sha256_first = SHA256.new(bytes.fromhex(hash160_val))
sha256_second = SHA256.new(bytes.fromhex(sha256_first.hexdigest()))
checksum = sha256_second.hexdigest()[:8]
# Returns 25byte Bitcoin Address.
return hash160_val + checksum
When I run code like this,
for i in range(100):
private_key = str(hex(get_private_key()))[2:]
address = generate_bitcoin_address(private_key)
I expected 100 prints of Public key's hash. However, It runs several times sometimes and give me following results.
Public key's hash = 00ededa6d1865639736123207949b0d57dfaf007ed
Public key's hash = 000069e3aabbec21d1332740e1440c651c48709819
Public key's hash = 00afc95e037950b2ea956aa6b53a7a050beb8b0630
Public key's hash = 00e20cb4fe60856bd9201f0ddc65eac5e8df69e6f8
Public key's hash = 00d2b0c84885e9e97df2db00774662ad5fe0aaf3fa
Public key's hash = 0028c2bc126e96eba5a6eee68cee5f1300fe1d87cd
Traceback (most recent call last):
File "c:\Users\asn68\Desktop\a\2.py", line 112, in <module>
address = generate_bitcoin_address(private_key)
File "c:\Users\asn68\Desktop\a\2.py", line 86, in generate_bitcoin_address
data = bytes.fromhex(compressed_pkey)
ValueError: non-hexadecimal number found in fromhex() arg at position 65
compressed_pkey is a 33bytes hex in str. No matter what random privatekey comes in, compressed_pkey must be 33bytes hex in string. I don't know why console says it's non-hexadecimal number.
If i print compressed_pkey together, it gives me values like these.
0344f0ff20daa00ff16e265af78eeba9a77493a889ab211b04135f94f3a8d80962
Public key's hash = 000163aedee962317a67ca493cb8ff69e0f8f417ae
0293079d9372346d0584e364a9cfd696a03046ec08e1d6108ffb0b5ae1aa408d11
Public key's hash = 0076c593b889dbef7e9b97c7a6ef0cf1a766ea1540
03c7a2e36cbe7d5c59ca9b193c87aeef88aa48339b250399c79d2f3035821dc850
Public key's hash = 0032896aff3ef34ecabb558b53e79a69badeac3875
0359a4924371f48435d539ef9a15e6b67a5f7ccdca0b7b585c7bdcd7c954a3ba1a
Public key's hash = 00cc34ab18e0a61d23af3dc7bb43fb5e626b061a80
and occurs same error.