PPCoin: Release alert and checkpoint master public keys
[novacoin.git] / bitcointools / base58.py
1 #!/usr/bin/env python
2
3 """encode/decode base58 in the same way that Bitcoin does"""
4
5 import math
6
7 __b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
8 __b58base = len(__b58chars)
9
10 def b58encode(v):
11   """ encode v, which is a string of bytes, to base58.    
12   """
13
14   long_value = 0L
15   for (i, c) in enumerate(v[::-1]):
16     long_value += (256**i) * ord(c)
17
18   result = ''
19   while long_value >= __b58base:
20     div, mod = divmod(long_value, __b58base)
21     result = __b58chars[mod] + result
22     long_value = div
23   result = __b58chars[long_value] + result
24
25   # Bitcoin does a little leading-zero-compression:
26   # leading 0-bytes in the input become leading-1s
27   nPad = 0
28   for c in v:
29     if c == '\0': nPad += 1
30     else: break
31
32   return (__b58chars[0]*nPad) + result
33
34 def b58decode(v, length):
35   """ decode v into a string of len bytes
36   """
37   long_value = 0L
38   for (i, c) in enumerate(v[::-1]):
39     long_value += __b58chars.find(c) * (__b58base**i)
40
41   result = ''
42   while long_value >= 256:
43     div, mod = divmod(long_value, 256)
44     result = chr(mod) + result
45     long_value = div
46   result = chr(long_value) + result
47
48   nPad = 0
49   for c in v:
50     if c == __b58chars[0]: nPad += 1
51     else: break
52
53   result = chr(0)*nPad + result
54   if length is not None and len(result) != length:
55     return None
56
57   return result
58
59 try:
60   # Python Crypto library is at: http://www.dlitz.net/software/pycrypto/
61   # Needed for RIPEMD160 hash function, used to compute
62   # Bitcoin addresses from internal public keys.
63   import Crypto.Hash.SHA256 as SHA256
64   import Crypto.Hash.RIPEMD160 as RIPEMD160
65   have_crypto = True
66 except ImportError:
67   have_crypto = False
68
69 def hash_160(public_key):
70   if not have_crypto:
71     return ''
72   h1 = SHA256.new(public_key).digest()
73   h2 = RIPEMD160.new(h1).digest()
74   return h2
75
76 def public_key_to_bc_address(public_key):
77   if not have_crypto:
78     return ''
79   h160 = hash_160(public_key)
80   return hash_160_to_bc_address(h160)
81
82 def hash_160_to_bc_address(h160):
83   if not have_crypto:
84     return ''
85   vh160 = "\x00"+h160  # \x00 is version 0
86   h3=SHA256.new(SHA256.new(vh160).digest()).digest()
87   addr=vh160+h3[0:4]
88   return b58encode(addr)
89
90 def bc_address_to_hash_160(addr):
91   bytes = b58decode(addr, 25)
92   return bytes[1:21]
93
94 if __name__ == '__main__':
95     x = '005cc87f4a3fdfe3a2346b6953267ca867282630d3f9b78e64'.decode('hex_codec')
96     encoded = b58encode(x)
97     print encoded, '19TbMSWwHvnxAKy12iNm3KdbGfzfaMFViT'
98     print b58decode(encoded, len(x)).encode('hex_codec'), x.encode('hex_codec')