Skip to content
This repository was archived by the owner on Jan 29, 2025. It is now read-only.

Commit fbeacaf

Browse files
authored
Create address.py
1 parent bd7dcfa commit fbeacaf

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed

address.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#!/usr/bin/env python
2+
# https://pastebin.com/4Lmf25gK
3+
import ctypes
4+
import hashlib
5+
from base58 import encode as base58_encode
6+
7+
################################################################################
8+
################################################################################
9+
ssl_library = ctypes.cdll.LoadLibrary('libssl.so')
10+
11+
def gen_ecdsa_pair():
12+
NID_secp160k1 = 708
13+
NID_secp256k1 = 714
14+
k = ssl_library.EC_KEY_new_by_curve_name(NID_secp256k1)
15+
16+
if ssl_library.EC_KEY_generate_key(k) != 1:
17+
raise Exception("internal error?")
18+
19+
bignum_private_key = ssl_library.EC_KEY_get0_private_key(k)
20+
size = (ssl_library.BN_num_bits(bignum_private_key)+7)//8
21+
#print("Key size is {} bytes".format(size))
22+
storage = ctypes.create_string_buffer(size)
23+
ssl_library.BN_bn2bin(bignum_private_key, storage)
24+
private_key = storage.raw
25+
26+
size = ssl_library.i2o_ECPublicKey(k, 0)
27+
#print("Pubkey size is {} bytes".format(size))
28+
storage = ctypes.create_string_buffer(size)
29+
ssl_library.i2o_ECPublicKey(k, ctypes.byref(ctypes.pointer(storage)))
30+
public_key = storage.raw
31+
32+
ssl_library.EC_KEY_free(k)
33+
return public_key, private_key
34+
35+
def ecdsa_get_coordinates(public_key):
36+
x = bytes(public_key[1:33])
37+
y = bytes(public_key[33:65])
38+
return x, y
39+
40+
def generate_address(public_key):
41+
assert isinstance(public_key, bytes)
42+
43+
x, y = ecdsa_get_coordinates(public_key)
44+
45+
s = b'\x04' + x + y
46+
#print('0x04 + x + y:', ''.join(['{:02X}'.format(i) for i in s]))
47+
48+
hasher = hashlib.sha256()
49+
hasher.update(s)
50+
r = hasher.digest()
51+
#print('SHA256(0x04 + x + y):', ''.join(['{:02X}'.format(i) for i in r]))
52+
53+
hasher = hashlib.new('ripemd160')
54+
hasher.update(r)
55+
r = hasher.digest()
56+
#print('RIPEMD160(SHA256(0x04 + x + y)):', ''.join(['{:02X}'.format(i) for i in r]))
57+
58+
# Since '1' is a zero byte, it won't be present in the output address.
59+
return '1' + base58_check(r, version=0)
60+
61+
def base58_check(src, version=0):
62+
src = bytes([version]) + src
63+
hasher = hashlib.sha256()
64+
hasher.update(src)
65+
r = hasher.digest()
66+
#print('SHA256(0x00 + r):', ''.join(['{:02X}'.format(i) for i in r]))
67+
68+
hasher = hashlib.sha256()
69+
hasher.update(r)
70+
r = hasher.digest()
71+
#print('SHA256(SHA256(0x00 + r)):', ''.join(['{:02X}'.format(i) for i in r]))
72+
73+
checksum = r[:4]
74+
s = src + checksum
75+
#print('src + checksum:', ''.join(['{:02X}'.format(i) for i in s]))
76+
77+
return base58_encode(int.from_bytes(s, 'big'))
78+
79+
def test():
80+
public_key, private_key = gen_ecdsa_pair()
81+
82+
hex_private_key = ''.join(["{:02x}".format(i) for i in private_key])
83+
assert len(hex_private_key) == 64
84+
85+
print("ECDSA private key (random number / secret exponent) = {}".format(hex_private_key))
86+
print("ECDSA public key = {}".format(''.join(['{:02x}'.format(i) for i in public_key])))
87+
print("Bitcoin private key (Base58Check) = {}".format(base58_check(private_key, version=128)))
88+
89+
addr = generate_address(public_key)
90+
print("Bitcoin Address: {} (length={})".format(addr, len(addr)))
91+
92+
if __name__ == "__main__":
93+
test()

0 commit comments

Comments
 (0)