<p>The code you linked works for me in Python 3.4, so I'll assume you're looking for something for Python 2.7.</p>

<p>This code is straight from <a href="https://github.com/gurnec/btcrecover/blob/5d5432182f95def45929f91f8b9a5daa2ad21ba9/seedrecover.py#L76-L150" rel="nofollow">here on GitHub</a>:</p>

<pre><code>import base64, hashlib, collections, struct

def int_to_bytes(int_rep, min_length = 0):
    """convert an unsigned integer to a string of bytes (in big-endian order)
    :param int_rep: a non-negative integer
    :type int_rep: long or int
    :param min_length: the minimum output length
    :type min_length: int
    :return: the raw bytes, zero-padded (at the beginning) if necessary
    :rtype: str
    """
    assert int_rep &gt;= 0
    hex_rep = "{:X}".format(int_rep)
    if len(hex_rep) % 2 == 1:    # The hex decoder below requires
        hex_rep = "0" + hex_rep  # exactly 2 chars per byte.
    return base64.b16decode(hex_rep).rjust(min_length, "\0")


dec_digit_to_base58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
base58_digit_to_dec = { b58:dec for dec,b58 in enumerate(dec_digit_to_base58) }


def base58check_to_bytes(base58_rep, expected_size):
    """decode a base58check string to its raw bytes
    :param base58_rep: check-code appended base58-encoded string
    :type base58_rep: str
    :param expected_size: the expected number of decoded bytes (excluding the check code)
    :type expected_size: int
    :return: the base58-decoded bytes
    :rtype: str
    """
    base58_stripped = base58_rep.lstrip("1")

    int_rep = 0
    for base58_digit in base58_stripped:
        int_rep *= 58
        int_rep += base58_digit_to_dec[base58_digit]

    # Convert int to raw bytes
    all_bytes  = int_to_bytes(int_rep, expected_size + 4)

    zero_count = next(zeros for zeros,byte in enumerate(all_bytes) if byte != "\0")
    if len(base58_rep) - len(base58_stripped) != zero_count:
        raise ValueError("prepended zeros mismatch")

    if hashlib.sha256(hashlib.sha256(all_bytes[:-4]).digest()).digest()[:4] != all_bytes[-4:]:
        raise ValueError("base58 check code mismatch")

    return all_bytes[:-4]

def base58check_to_hash160(base58_rep):
    """convert from a base58check address to its hash160 form
    :param base58_rep: check-code appended base58-encoded address
    :type base58_rep: str
    :return: the ripemd160(sha256()) hash of the pubkey/redeemScript, then the version byte
    :rtype: (str, str)
    """
    decoded_bytes = base58check_to_bytes(base58_rep, 1 + 20)
    return decoded_bytes[1:], decoded_bytes[0]

BIP32ExtendedKey = collections.namedtuple("BIP32ExtendedKey",
    "version depth fingerprint child_number chaincode key")
#
def base58check_to_bip32(base58_rep):
    """decode a bip32-serialized extended key from its base58check form
    :param base58_rep: check-code appended base58-encoded bip32 extended key
    :type base58_rep: str
    :return: a namedtuple containing: version depth fingerprint child_number chaincode key
    :rtype: BIP32ExtendedKey
    """
    decoded_bytes = base58check_to_bytes(base58_rep, 4 + 1 + 4 + 4 + 32 + 33)
    return BIP32ExtendedKey(decoded_bytes[0:4],  ord(decoded_bytes[ 4:5]), decoded_bytes[ 5:9],
        struct.unpack("&gt;I", decoded_bytes[9:13])[0], decoded_bytes[13:45], decoded_bytes[45:])
</code></pre>

<p>In particular, you'll want to call <code>base58check_to_hash160()</code> to check a "normal" address, or <code>base58check_to_bip32()</code> to check a BIP-32 extended address (an "xpub" or "xprv"). They will either return the results of decoding the address, or raise <code>ValueError</code> if the address is invalid.</p>

<p>It's technically licensed under <a href="http://opensource.org/licenses/gpl-2.0.php" rel="nofollow">GPLv2</a>, but if you'd like me (as the original author) to relicense it under something less restrictive for your project, e.g. <a href="http://opensource.org/licenses/BSD-2-Clause" rel="nofollow">BSD</a> or <a href="http://opensource.org/licenses/MIT" rel="nofollow">MIT</a>, I'd be happy to. Please just let me know in a comment.</p>

CC BY-SA 3.0
2015-05-09T14:21:57.787Z
Thanks so much! No need to relicense your code, the method was all I wanted. Thanks again :)
derrend
CC BY-SA 3.0
2015-05-09T12:47:50.167Z
2015-05-09T12:47:50.167Z
Christopher Gurnee
<p>I'm on the hunt for some python code that will tell me if a string is a valid bip32 xpub key but I'm having trouble finding any.</p>

<p>I also would like to check if a string is a valid bitcoin address.
Here is an example I found for this purpose but it doesnt seem to work - <a href="http://rosettacode.org/wiki/Bitcoin/address_validation#Python" rel="nofollow">http://rosettacode.org/wiki/Bitcoin/address_validation#Python</a></p>

<p>Please help :)</p>

<bitcoind><bip32-hd-wallets><python>
How can I check if a bip32 xpub key is valid using python?
derrend
# How can I check if a bip32 xpub key is valid using python?

(Asked by: username_0 on 2015-05-09)

I'm on the hunt for some python code that will tell me if a string is a valid bip32 xpub key but I'm having trouble finding any.

I also would like to check if a string is a valid bitcoin address.
Here is an example I found for this purpose but it doesnt seem to work - <http://rosettacode.org/wiki/Bitcoin/address_validation#Python>

Please help :)

**Tags:** bitcoind, bip32-hd-wallets, python


---

## 1 answers

### Answer by username_1 on 2015-05-09. Score: 3 | Accepted answer

The code you linked works for me in Python 3.4, so I'll assume you're looking for something for Python 2.7.

This code is straight from [here on GitHub](https://github.com/gurnec/btcrecover/blob/5d5432182f95def45929f91f8b9a5daa2ad21ba9/seedrecover.py#L76-L150):

```
import base64, hashlib, collections, struct

def int_to_bytes(int_rep, min_length = 0):
    """convert an unsigned integer to a string of bytes (in big-endian order)
    :param int_rep: a non-negative integer
    :type int_rep: long or int
    :param min_length: the minimum output length
    :type min_length: int
    :return: the raw bytes, zero-padded (at the beginning) if necessary
    :rtype: str
    """
    assert int_rep >= 0
    hex_rep = "{:X}".format(int_rep)
    if len(hex_rep) % 2 == 1:    # The hex decoder below requires
        hex_rep = "0" + hex_rep  # exactly 2 chars per byte.
    return base64.b16decode(hex_rep).rjust(min_length, "\0")

dec_digit_to_base58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
base58_digit_to_dec = { b58:dec for dec,b58 in enumerate(dec_digit_to_base58) }

def base58check_to_bytes(base58_rep, expected_size):
    """decode a base58check string to its raw bytes
    :param base58_rep: check-code appended base58-encoded string
    :type base58_rep: str
    :param expected_size: the expected number of decoded bytes (excluding the check code)
    :type expected_size: int
    :return: the base58-decoded bytes
    :rtype: str
    """
    base58_stripped = base58_rep.lstrip("1")

    int_rep = 0
    for base58_digit in base58_stripped:
        int_rep *= 58
        int_rep += base58_digit_to_dec[base58_digit]

    # Convert int to raw bytes
    all_bytes  = int_to_bytes(int_rep, expected_size + 4)

    zero_count = next(zeros for zeros,byte in enumerate(all_bytes) if byte != "\0")
    if len(base58_rep) - len(base58_stripped) != zero_count:
        raise ValueError("prepended zeros mismatch")

    if hashlib.sha256(hashlib.sha256(all_bytes[:-4]).digest()).digest()[:4] != all_bytes[-4:]:
        raise ValueError("base58 check code mismatch")

    return all_bytes[:-4]

def base58check_to_hash160(base58_rep):
    """convert from a base58check address to its hash160 form
    :param base58_rep: check-code appended base58-encoded address
    :type base58_rep: str
    :return: the ripemd160(sha256()) hash of the pubkey/redeemScript, then the version byte
    :rtype: (str, str)
    """
    decoded_bytes = base58check_to_bytes(base58_rep, 1 + 20)
    return decoded_bytes[1:], decoded_bytes[0]

BIP32ExtendedKey = collections.namedtuple("BIP32ExtendedKey",
    "version depth fingerprint child_number chaincode key")
#
def base58check_to_bip32(base58_rep):
    """decode a bip32-serialized extended key from its base58check form
    :param base58_rep: check-code appended base58-encoded bip32 extended key
    :type base58_rep: str
    :return: a namedtuple containing: version depth fingerprint child_number chaincode key
    :rtype: BIP32ExtendedKey
    """
    decoded_bytes = base58check_to_bytes(base58_rep, 4 + 1 + 4 + 4 + 32 + 33)
    return BIP32ExtendedKey(decoded_bytes[0:4],  ord(decoded_bytes[ 4:5]), decoded_bytes[ 5:9],
        struct.unpack(">I", decoded_bytes[9:13])[0], decoded_bytes[13:45], decoded_bytes[45:])

```

In particular, you'll want to call `base58check_to_hash160()` to check a "normal" address, or `base58check_to_bip32()` to check a BIP-32 extended address (an "xpub" or "xprv"). They will either return the results of decoding the address, or raise `ValueError` if the address is invalid.

It's technically licensed under [GPLv2](http://opensource.org/licenses/gpl-2.0.php), but if you'd like me (as the original author) to relicense it under something less restrictive for your project, e.g. [BSD](http://opensource.org/licenses/BSD-2-Clause) or [MIT](http://opensource.org/licenses/MIT), I'd be happy to. Please just let me know in a comment.

> **Comments:**
> **username_0**: Thanks so much! No need to relicense your code, the method was all I wanted. Thanks again :)  

---

