tbitcoin.py: base58 address: make sure all public methods test checksum - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 5f6f7da2a1be473a34a125509413d95475011e6a DIR parent 8cf3587aeb0b1fb767aee84792e15f75f90e8f23 HTML Author: SomberNight <somber.night@protonmail.com> Date: Sun, 8 Dec 2019 06:56:19 +0100 bitcoin.py: base58 address: make sure all public methods test checksum Note: the checksum was already being checked in practically all cases, by the caller. Moved the check here, to the lower level (but still public) method for sanity. Diffstat: M electrum/bitcoin.py | 7 +++++-- M electrum/tests/test_bitcoin.py | 10 ++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) --- DIR diff --git a/electrum/bitcoin.py b/electrum/bitcoin.py t@@ -328,7 +328,9 @@ def hash160_to_b58_address(h160: bytes, addrtype: int) -> str: def b58_address_to_hash160(addr: str) -> Tuple[int, bytes]: addr = to_bytes(addr, 'ascii') - _bytes = base_decode(addr, base=58, length=25) + _bytes = DecodeBase58Check(addr) + if len(_bytes) != 21: + raise Exception(f'expected 21 payload bytes in base58 address. got: {len(_bytes)}') return _bytes[0], _bytes[1:21] t@@ -638,12 +640,13 @@ def is_segwit_address(addr: str, *, net=None) -> bool: def is_b58_address(addr: str, *, net=None) -> bool: if net is None: net = constants.net try: + # test length, checksum, encoding: addrtype, h = b58_address_to_hash160(addr) except Exception as e: return False if addrtype not in [net.ADDRTYPE_P2PKH, net.ADDRTYPE_P2SH]: return False - return addr == hash160_to_b58_address(h, addrtype) + return True def is_address(addr: str, *, net=None) -> bool: if net is None: net = constants.net DIR diff --git a/electrum/tests/test_bitcoin.py b/electrum/tests/test_bitcoin.py t@@ -711,6 +711,16 @@ class Test_keyImport(ElectrumTestCase): self.assertFalse(is_address("not an address")) + def test_is_address_bad_checksums(self): + self.assertTrue(is_address('1819s5TxxbBtuRPr3qYskMVC8sb1pqapWx')) + self.assertFalse(is_address('1819s5TxxbBtuRPr3qYskMVC8sb1pqapWw')) + + self.assertTrue(is_address('3LrjLVnngqnaJeo3BQwMBg34iqYsjZjQUe')) + self.assertFalse(is_address('3LrjLVnngqnaJeo3BQwMBg34iqYsjZjQUd')) + + self.assertTrue(is_address('bc1qxq64lrwt02hm7tu25lr3hm9tgzh58snfe67yt6')) + self.assertFalse(is_address('bc1qxq64lrwt02hm7tu25lr3hm9tgzh58snfe67yt5')) + @needs_test_with_all_ecc_implementations def test_is_private_key(self): for priv_details in self.priv_pub_addr: