-
Notifications
You must be signed in to change notification settings - Fork 1
/
base58.py
87 lines (69 loc) · 3.1 KB
/
base58.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#!/usr/bin/python
# coding: utf8
import hashlib
from binascii import hexlify, unhexlify, b2a_hex
from constants import *
alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
len58 = len(alphabet)
def base58_encode(numberic: int) ->str:
ret = ''
numberic = int(numberic)
if numberic < 0:
return ret
while numberic > 0:
ret += alphabet[numberic % len58]
numberic //= len58
# reverse squence
return ret[::-1]
def base58_decode(string: str) ->int:
ret = 0
# reverse string
string = string[::-1]
for i, s in enumerate(string):
index = alphabet.index(s)
ret += index * (len58 ** i)
return ret
#
def base58check_encode(Bytes: bytes):
# 编码的过程
# 2 - Add a 0x80 byte in front of it for mainnet addresses or 0xef for testnet addresses. Also add a 0x01 byte at the end if the private key will correspond to a compressed public key
# 3 - Perform SHA-256 hash on the extended key
# 800C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D
# 4 - Perform SHA-256 hash on result of SHA-256 hash
# 8147786C4D15106333BF278D71DADAF1079EF2D2440A4DDE37D747DED5403592
# 5 - Take the first 4 bytes of the second SHA-256 hash, this is the checksum
# 507A5B8DFED0FC6FE8801743720CEDEC06AA5C6FCA72B07C49964492FB98A714
# 507A5B8D
# 6 - Add the 4 checksum bytes from point 5 at the end of the extended key from point 2
# 800C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D507A5B8D
# 800c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d507a5b8d
# 7 - Convert the result from a byte string into a base58 string using Base58Check encoding. This is the Wallet Import Format
# 5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ
check_sum = hashlib.sha256(hashlib.sha256(Bytes).digest()).digest()
r = Bytes + check_sum[:4]
return base58_encode(int.from_bytes(r, byteorder='big'))
def base58check_decode(string: str) ->bytes:
one_more_times = len(string) - len(string.lstrip('1'))
decimal = base58_decode(string) # type: int
all_bytes = bytes().fromhex(hex(decimal).lstrip('0x').rstrip('L'))
# 4字节的check_sum
ret, check_sum = all_bytes[:-4], all_bytes[-4:]
# @todo 加版本前缀?
ret_check = bytes().fromhex('00') * one_more_times + ret
# 双sha256后的前4个字节
real_check_sum = hashlib.sha256(hashlib.sha256(ret_check).digest()).digest()[:4]
assert(check_sum == real_check_sum)
return ret[one_more_times:]
def address_to_scriptPubKey(b58_str):
assert len(b58_str) == 34
decoded_b58str = base58check_decode(b58_str)
if len(decoded_b58str) > 20:
decoded_b58str = decoded_b58str[1:]
if len(decoded_b58str) > 20:
decoded_b58str = decoded_b58str[:20 - len(decoded_b58str)]
# 测试网络需要去掉\x6f
# 一定是20字节
assert len(decoded_b58str) == 20
return OP_DUP + OP_HASH160 + '14' + decoded_b58str.hex() + OP_EQUALVERIFY + OP_CHECKSIG
if __name__ == '__main__':
print(base58check_decode('2Myz4PFLijNPUquXonEcPMRXjDx6UiJGVbw').hex())