You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

base58.py 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. # Copyright (c) 2012-2017 The Starwels developers
  2. # Distributed under the MIT software license, see the accompanying
  3. # file COPYING or http://www.opensource.org/licenses/mit-license.php.
  4. '''
  5. Starwels base58 encoding and decoding.
  6. Based on https://bitcointalk.org/index.php?topic=1026.0 (public domain)
  7. '''
  8. import hashlib
  9. # for compatibility with following code...
  10. class SHA256:
  11. new = hashlib.sha256
  12. if str != bytes:
  13. # Python 3.x
  14. def ord(c):
  15. return c
  16. def chr(n):
  17. return bytes( (n,) )
  18. __b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
  19. __b58base = len(__b58chars)
  20. b58chars = __b58chars
  21. def b58encode(v):
  22. """ encode v, which is a string of bytes, to base58.
  23. """
  24. long_value = 0
  25. for (i, c) in enumerate(v[::-1]):
  26. long_value += (256**i) * ord(c)
  27. result = ''
  28. while long_value >= __b58base:
  29. div, mod = divmod(long_value, __b58base)
  30. result = __b58chars[mod] + result
  31. long_value = div
  32. result = __b58chars[long_value] + result
  33. # Starwels does a little leading-zero-compression:
  34. # leading 0-bytes in the input become leading-1s
  35. nPad = 0
  36. for c in v:
  37. if c == '\0': nPad += 1
  38. else: break
  39. return (__b58chars[0]*nPad) + result
  40. def b58decode(v, length = None):
  41. """ decode v into a string of len bytes
  42. """
  43. long_value = 0
  44. for (i, c) in enumerate(v[::-1]):
  45. long_value += __b58chars.find(c) * (__b58base**i)
  46. result = bytes()
  47. while long_value >= 256:
  48. div, mod = divmod(long_value, 256)
  49. result = chr(mod) + result
  50. long_value = div
  51. result = chr(long_value) + result
  52. nPad = 0
  53. for c in v:
  54. if c == __b58chars[0]: nPad += 1
  55. else: break
  56. result = chr(0)*nPad + result
  57. if length is not None and len(result) != length:
  58. return None
  59. return result
  60. def checksum(v):
  61. """Return 32-bit checksum based on SHA256"""
  62. return SHA256.new(SHA256.new(v).digest()).digest()[0:4]
  63. def b58encode_chk(v):
  64. """b58encode a string, with 32-bit checksum"""
  65. return b58encode(v + checksum(v))
  66. def b58decode_chk(v):
  67. """decode a base58 string, check and remove checksum"""
  68. result = b58decode(v)
  69. if result is None:
  70. return None
  71. if result[-4:] == checksum(result[:-4]):
  72. return result[:-4]
  73. else:
  74. return None
  75. def get_bcaddress_version(strAddress):
  76. """ Returns None if strAddress is invalid. Otherwise returns integer version of address. """
  77. addr = b58decode_chk(strAddress)
  78. if addr is None or len(addr)!=21: return None
  79. version = addr[0]
  80. return ord(version)
  81. if __name__ == '__main__':
  82. # Test case (from http://gitorious.org/bitcoin/python-base58.git)
  83. assert get_bcaddress_version('15VjRaDX9zpbA8LVnbrCAFzrVzN7ixHNsC') is 0
  84. _ohai = 'o hai'.encode('ascii')
  85. _tmp = b58encode(_ohai)
  86. assert _tmp == 'DYB3oMS'
  87. assert b58decode(_tmp, 5) == _ohai
  88. print("Tests passed")