pax_global_header00006660000000000000000000000064134115222230014505gustar00rootroot0000000000000052 comment=5e2b2295186d541e4fa71e919dd5961b0f6864e2 base58-1.0.3/000077500000000000000000000000001341152222300125755ustar00rootroot00000000000000base58-1.0.3/.travis.yml000066400000000000000000000003631341152222300147100ustar00rootroot00000000000000language: python sudo: false python: - "2.7" - "3.4" - "3.5" - "3.6" - "pypy" - "pypy3" install: - pip install -r test-requirements.txt script: pytest --pep8 --flakes --cov=base58 . after_success: coveralls base58-1.0.3/CHANGELOG.md000066400000000000000000000031261341152222300144100ustar00rootroot00000000000000## Changelog ### v1.0.3 / 2018-12-28 - [#37](https://github.com/keis/base58/pull/37) Update base58.py (@pdelteil) ### v1.0.2 / 2018-09-27 - [#34](https://github.com/keis/base58/pull/34) Add bumpversion config (@keis) ### v1.0.1 / 2018-09-25 - [#31](https://github.com/keis/base58/pull/31) Include tests in PyPI tarball (@dotlambda) ### v1.0.0 / 2018-04-20 - [#27](https://github.com/keis/base58/pull/27) Use bytes for both input and output (@keis) - [#25](https://github.com/keis/base58/pull/25) Do not strip newline from input to cli (@keis) - [#26](https://github.com/keis/base58/pull/26) Use tox and pytest to run tests (@keis) - [#22](https://github.com/keis/base58/pull/22) Add the packaging metadata to build the base58 snap (@elopio) - [#17](https://github.com/keis/base58/pull/17) improved error message (@fametrano) - [#21](https://github.com/keis/base58/pull/21) clearer padding (@fametrano) ### v0.2.5 / 2017-04-04 - [#14](https://github.com/keis/base58/pull/14) Slight optimization, version increment (@gappleto97) - [#12](https://github.com/keis/base58/pull/12) Add integer support (#12) (@gappleto97) - [#10](https://github.com/keis/base58/pull/10) Add more test systems (@gappleto97) ### v0.2.4 / 2016-10-28 - [#8](https://github.com/keis/base58/pull/8) Package metadata (@keis) ### v0.2.3 / 2016-06-14 - [#6](https://github.com/keis/base58/pull/6) Improve error message when the type is not bytes (@keis, @zkanda) ### v0.2.2 / 2015-04-09 - [#3](https://github.com/keis/base58/pull/3) test round trips (@oconnor663) - [#2](https://github.com/keis/base58/pull/2) fix encoding of empty string (@keis) base58-1.0.3/COPYING000066400000000000000000000020411341152222300136250ustar00rootroot00000000000000Copyright (c) 2015 David Keijser Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. base58-1.0.3/MANIFEST.in000066400000000000000000000000151341152222300143270ustar00rootroot00000000000000include *.py base58-1.0.3/README.md000066400000000000000000000031171341152222300140560ustar00rootroot00000000000000# base58 [![PyPI Version][pypi-image]](https://pypi.python.org/pypi?name=base58&:action=display) [![PyPI Downloads][pypi-downloads-image]](https://pypi.python.org/pypi?name=base58&:action=display) [![Build Status][travis-image]](https://travis-ci.org/keis/base58) [![Coverage Status][coveralls-image]](https://coveralls.io/r/keis/base58?branch=master) Base58 and Base58Check implementation compatible with what is used by the bitcoin network. ## Command line usage $ printf "hello world" | base58 StV1DL6CwTryKyV $ printf "hello world" | base58 -c 3vQB7B6MrGQZaxCuFg4oh $ printf "3vQB7B6MrGQZaxCuFg4oh" | base58 -dc hello world $ printf "4vQB7B6MrGQZaxCuFg4oh" | base58 -dc Invalid checksum ## Module usage >>> import base58 >>> base58.b58encode(b'hello world') 'StV1DL6CwTryKyV' >>> base58.b58decode(b'StV1DL6CwTryKyV') b'hello world' >>> base58.b58encode_check(b'hello world') '3vQB7B6MrGQZaxCuFg4oh' >>> base58.b58decode_check(b'3vQB7B6MrGQZaxCuFg4oh') b'hello world' >>> base58.b58decode_check(b'4vQB7B6MrGQZaxCuFg4oh') Traceback (most recent call last): File "", line 1, in File "base58.py", line 89, in b58decode_check raise ValueError("Invalid checksum") ValueError: Invalid checksum [pypi-image]: https://img.shields.io/pypi/v/base58.svg?style=flat [pypi-downloads-image]: https://img.shields.io/pypi/dm/base58.svg?style=flat [travis-image]: https://img.shields.io/travis/keis/base58.svg?style=flat [coveralls-image]: https://img.shields.io/coveralls/keis/base58.svg?style=flat base58-1.0.3/base58.py000066400000000000000000000074611341152222300142460ustar00rootroot00000000000000'''Base58 encoding Implementations of Base58 and Base58Check endcodings that are compatible with the bitcoin network. ''' # This module is based upon base58 snippets found scattered over many bitcoin # tools written in python. From what I gather the original source is from a # forum post by Gavin Andresen, so direct your praise to him. # This module adds shiny packaging and support for python3. from hashlib import sha256 __version__ = '1.0.3' # 58 character alphabet used alphabet = b'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' if bytes == str: # python2 iseq, bseq, buffer = ( lambda s: map(ord, s), lambda s: ''.join(map(chr, s)), lambda s: s, ) else: # python3 iseq, bseq, buffer = ( lambda s: s, bytes, lambda s: s.buffer, ) def scrub_input(v): if isinstance(v, str) and not isinstance(v, bytes): v = v.encode('ascii') if not isinstance(v, bytes): raise TypeError( "a bytes-like object is required (also str), not '%s'" % type(v).__name__) return v def b58encode_int(i, default_one=True): '''Encode an integer using Base58''' if not i and default_one: return alphabet[0:1] string = b"" while i: i, idx = divmod(i, 58) string = alphabet[idx:idx+1] + string return string def b58encode(v): '''Encode a string using Base58''' v = scrub_input(v) nPad = len(v) v = v.lstrip(b'\0') nPad -= len(v) p, acc = 1, 0 for c in iseq(reversed(v)): acc += p * c p = p << 8 result = b58encode_int(acc, default_one=False) return (alphabet[0:1] * nPad + result) def b58decode_int(v): '''Decode a Base58 encoded string as an integer''' v = v.rstrip() v = scrub_input(v) decimal = 0 for char in v: decimal = decimal * 58 + alphabet.index(char) return decimal def b58decode(v): '''Decode a Base58 encoded string''' v = v.rstrip() v = scrub_input(v) origlen = len(v) v = v.lstrip(alphabet[0:1]) newlen = len(v) acc = b58decode_int(v) result = [] while acc > 0: acc, mod = divmod(acc, 256) result.append(mod) return (b'\0' * (origlen - newlen) + bseq(reversed(result))) def b58encode_check(v): '''Encode a string using Base58 with a 4 character checksum''' digest = sha256(sha256(v).digest()).digest() return b58encode(v + digest[:4]) def b58decode_check(v): '''Decode and verify the checksum of a Base58 encoded string''' result = b58decode(v) result, check = result[:-4], result[-4:] digest = sha256(sha256(result).digest()).digest() if check != digest[:4]: raise ValueError("Invalid checksum") return result def main(): '''Base58 encode or decode FILE, or standard input, to standard output.''' import sys import argparse stdout = buffer(sys.stdout) parser = argparse.ArgumentParser(description=main.__doc__) parser.add_argument( 'file', metavar='FILE', nargs='?', type=argparse.FileType('r'), default='-') parser.add_argument( '-d', '--decode', action='store_true', help='decode data') parser.add_argument( '-c', '--check', action='store_true', help='append a checksum before encoding') args = parser.parse_args() fun = { (False, False): b58encode, (False, True): b58encode_check, (True, False): b58decode, (True, True): b58decode_check }[(args.decode, args.check)] data = buffer(args.file).read() try: result = fun(data) except Exception as e: sys.exit(e) if not isinstance(result, bytes): result = result.encode('ascii') stdout.write(result) if __name__ == '__main__': main() base58-1.0.3/setup.cfg000066400000000000000000000001421341152222300144130ustar00rootroot00000000000000[bumpversion] current_version = 1.0.3 [bumpversion:file:setup.py] [bumpversion:file:base58.py] base58-1.0.3/setup.py000066400000000000000000000013421341152222300143070ustar00rootroot00000000000000from setuptools import setup setup( name='base58', py_modules=['base58'], version='1.0.3', description='Base58 and Base58Check implementation', author='David Keijser', author_email='keijser@gmail.com', url='https://github.com/keis/base58', license='MIT', entry_points={ 'console_scripts': [ 'base58 = base58:main' ] }, classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'Natural Language :: English', 'License :: OSI Approved :: MIT License', 'Programming Language :: Python', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 2', ], ) base58-1.0.3/snap/000077500000000000000000000000001341152222300135365ustar00rootroot00000000000000base58-1.0.3/snap/snapcraft.yaml000066400000000000000000000004621341152222300164050ustar00rootroot00000000000000name: base58 version: git summary: Base58 and Base58Check implementation description: | Base58 and Base58Check implementation compatible with what is used by the bitcoin network. grade: stable confinement: strict apps: base58: command: base58 parts: base58: source: . plugin: python base58-1.0.3/test-requirements.txt000066400000000000000000000001201341152222300170270ustar00rootroot00000000000000pytest pytest-pep8 pytest-flakes pytest-cov PyHamcrest mock matchmock coveralls base58-1.0.3/test_base58.py000066400000000000000000000055021341152222300152770ustar00rootroot00000000000000from contextlib import contextmanager from itertools import product from hamcrest import assert_that, equal_to, instance_of from base58 import ( b58encode, b58decode, b58encode_check, b58decode_check, b58encode_int, b58decode_int, alphabet) if bytes == str: bytes_from_char = ( lambda c: c ) else: bytes_from_char = ( lambda c: bytes([c]) ) class RaisesContext(object): pass @contextmanager def assert_raises(matcher=None, message=''): # Short hand for instance_of matcher if isinstance(matcher, (type,)): matcher = instance_of(matcher) context = RaisesContext() try: yield context except Exception as e: context.exception = e assert_that(context.exception, matcher, message) def test_simple_encode(): data = b58encode(b'hello world') assert_that(data, equal_to(b'StV1DL6CwTryKyV')) def test_leadingz_encode(): data = b58encode(b'\0\0hello world') assert_that(data, equal_to(b'11StV1DL6CwTryKyV')) def test_encode_empty(): data = b58encode(b'') assert_that(data, equal_to(b'')) def test_simple_decode(): data = b58decode('StV1DL6CwTryKyV') assert_that(data, equal_to(b'hello world')) def test_simple_decode_bytes(): data = b58decode(b'StV1DL6CwTryKyV') assert_that(data, equal_to(b'hello world')) def test_leadingz_decode(): data = b58decode('11StV1DL6CwTryKyV') assert_that(data, equal_to(b'\0\0hello world')) def test_leadingz_decode_bytes(): data = b58decode(b'11StV1DL6CwTryKyV') assert_that(data, equal_to(b'\0\0hello world')) def test_empty_decode(): data = b58decode('1') assert_that(data, equal_to(b'\0')) def test_empty_decode_bytes(): data = b58decode(b'1') assert_that(data, equal_to(b'\0')) def test_check_identity(): data = b'hello world' out = b58decode_check(b58encode_check(data)) assert_that(out, equal_to(data)) def test_check_failure(): data = '3vQB7B6MrGQZaxCuFg4oH' with assert_raises(ValueError): b58decode_check(data) def test_round_trips(): possible_bytes = [b'\x00', b'\x01', b'\x10', b'\xff'] for length in range(0, 5): for bytes_to_test in product(possible_bytes, repeat=length): bytes_in = b''.join(bytes_to_test) bytes_out = b58decode(b58encode(bytes_in)) assert_that(bytes_in, equal_to(bytes_out)) def test_simple_integers(): for idx, char in enumerate(alphabet): char = bytes_from_char(char) assert_that(b58decode_int(char), equal_to(idx)) assert_that(b58encode_int(idx), equal_to(char)) def test_large_integer(): number = 0x111d38e5fc9071ffcd20b4a763cc9ae4f252bb4e48fd66a835e252ada93ff480d6dd43dc62a641155a5 # noqa assert_that(b58decode_int(alphabet), equal_to(number)) assert_that(b58encode_int(number), equal_to(alphabet[1:])) base58-1.0.3/tox.ini000066400000000000000000000001701341152222300141060ustar00rootroot00000000000000[tox] envlist = py27,py35 [testenv] deps = -rtest-requirements.txt commands = pytest --pep8 --flakes --cov=base58 . []