Example #1
0
def test_encode_base58():
    assert encode_base58(
        "000002030405060708090a0b0c0d0e0f") == "11ju1bKJX8HGdT7YmKLi"
    assert encode_base58("") == ""
    assert encode_base58("00759d5f2b6d12712fef6f0f24c56804193e1aeac176c1faae") == \
           "1Bitapsw1aT8hkLXFtXwZQfHgNwNJEyJJ1"
    assert encode_base58("00759d5f2b6d12712fef6f0f24c56804193e1aeac1", checksum=True) == \
           "1Bitapsw1aT8hkLXFtXwZQfHgNwNJEyJJ1"
Example #2
0
def hash_to_address(address_hash,
                    testnet=False,
                    script_hash=False,
                    witness_version=0):
    """
    Get address from public key/script hash. In case PUBKEY, P2PKH, P2PKH public key/script hash is SHA256+RIPEMD160,
    P2WSH script hash is SHA256.


    :param address_hash: public key hash or script hash in HEX or bytes string format.
    :param testnet: (optional) flag for testnet network, by default is False.
    :param script_hash: (optional) flag for script hash (P2SH address), by default is False.
    :param witness_version: (optional) witness program version, by default is 0, for legacy
                            address format use None.
    :return: address in base58 or bech32 format.
    """
    if isinstance(address_hash, str):
        address_hash = bytes_from_hex(address_hash)
    if not isinstance(address_hash, bytes):
        raise TypeError("address hash must be HEX encoded string or bytes")

    if not script_hash:
        if witness_version is None:
            if len(address_hash) != 20:
                raise ValueError("address hash length incorrect")
            if testnet:
                prefix = TESTNET_ADDRESS_BYTE_PREFIX
            else:
                prefix = MAINNET_ADDRESS_BYTE_PREFIX
            address_hash = b"%s%s" % (prefix, address_hash)
            address_hash += double_sha256(address_hash)[:4]
            return encode_base58(address_hash)
        else:
            if len(address_hash) not in (20, 32):
                raise ValueError("address hash length incorrect")

    if witness_version is None:
        if testnet:
            prefix = TESTNET_SCRIPT_ADDRESS_BYTE_PREFIX
        else:
            prefix = MAINNET_SCRIPT_ADDRESS_BYTE_PREFIX
        address_hash = b"%s%s" % (prefix, address_hash)
        address_hash += double_sha256(address_hash)[:4]
        return encode_base58(address_hash)

    if testnet:
        prefix = TESTNET_SEGWIT_ADDRESS_BYTE_PREFIX
        hrp = TESTNET_SEGWIT_ADDRESS_PREFIX
    else:
        prefix = MAINNET_SEGWIT_ADDRESS_BYTE_PREFIX
        hrp = MAINNET_SEGWIT_ADDRESS_PREFIX

    address_hash = b"%s%s" % (witness_version.to_bytes(
        1, "big"), rebase_8_to_5(address_hash))
    checksum = bech32_polymod(b"%s%s%s" % (prefix, address_hash, b"\x00" * 6))
    checksum = rebase_8_to_5(checksum.to_bytes(5, "big"))[2:]
    return "%s1%s" % (hrp, rebase_5_to_32(address_hash + checksum).decode())
Example #3
0
def test_derive_child_xpublic_key():
    xpub = "xpub661MyMwAqRbcFgWfEhiJneL1x2YcwTqMMvpx54rbY3oXsPvMLJnUZo8tsxpGFsUrFW" \
            "9zMFKAGzaDDy1pR2uoohh1CW24Se1vkSnXRMqPV9R"
    assert "xpub68weA6at5vJ4Mzrpr7a6ZUvSkusBWEQLnFpgXMY1EWHNNpHgkSnX6HJwwSjN7z" \
           "9PFrgTLK6gtWZ37o3b2ZAQSc4V9GdxdjVTjymSVit5Sai"  == \
           encode_base58(derive_child_xpublic_key(decode_base58(xpub, checksum=True), 0), checksum=True)


    assert "xpub68weA6at5vJ5fuUhS2bUgtse4cswz9VpU3UJAY93oUwpP8P4oDhTtGKizXsosJH99RWnnyD9txQ" \
           "XBAcyAEiykRDAoyHLCcpW2vkrnsSymDQ"   == \
           encode_base58(derive_child_xpublic_key(decode_base58(xpub, checksum=True), 30), checksum=True)

    with pytest.raises(ValueError):
        derive_child_xpublic_key(decode_base58(xpub, checksum=True),
                                 30 | 0x80000000)
Example #4
0
def create_master_xprivate_key(seed, testnet=False, base58=True, hex=False):
    """
    Create extended private key from seed

    :param str,bytes key: seed HEX or bytes string. 
    :param boolean base58: (optional) return result as base58 encoded string, by default True.
    :param boolean hex: (optional) return result as HEX encoded string, by default False.
                        In case True base58 flag value will be ignored.
    :return: extended private key  in base58, HEX or bytes string format.
    """
    if isinstance(seed, str):
        seed = bytes.fromhex(seed)
    if not isinstance(seed, bytes):
        raise TypeError("seed should be bytes or hex encoded string")
    i = hmac_sha512(b"Bitcoin seed", seed)
    m, c = i[:32], i[32:]
    m_int = int.from_bytes(m, byteorder="big")

    if m_int <= 0 or m_int > ECDSA_SEC256K1_ORDER:
        return None
    prefix = TESTNET_XPRIVATE_KEY_PREFIX if testnet else MAINNET_XPRIVATE_KEY_PREFIX
    key = b''.join(
        [prefix, b'\x00\x00\x00\x00\x00\x00\x00\x00\x00', c, b'\x00', m])
    if base58:
        key = b"".join([key, double_sha256(key)[:4]])
        return encode_base58(key)
    else:
        return key
Example #5
0
def create_master_xprivate_key(seed, testnet=False, base58=None, hex=None):
    """
    Create extended private key from seed

    :param str,bytes key: seed HEX or bytes string. 
    :param boolean base58: (optional) return result as base58 encoded string, by default True.
    :param boolean hex: (optional) return result as HEX encoded string, by default False.
                        In case True base58 flag value will be ignored.
    :return: extended private key  in base58, HEX or bytes string format.
    """
    seed = get_bytes(seed)
    i = hmac_sha512(b"Bitcoin seed", seed)
    m, c = i[:32], i[32:]
    m_int = int.from_bytes(m, byteorder="big")

    if m_int <= 0 or m_int > ECDSA_SEC256K1_ORDER:  # pragma: no cover
        return None
    prefix = TESTNET_XPRIVATE_KEY_PREFIX if testnet else MAINNET_XPRIVATE_KEY_PREFIX
    key = b''.join(
        [prefix, b'\x00\x00\x00\x00\x00\x00\x00\x00\x00', c, b'\x00', m])
    if base58 is None and hex is None:
        base58 = True
    if base58:
        key = b"".join([key, double_sha256(key)[:4]])
        return encode_base58(key)
    else:
        if hex is None:
            hex = False
        return key if not hex else key.hex()
Example #6
0
def bip32_xkey_to_path_xkey(key, path_type, base58=True, hex=False):
    if path_type not in ("BIP44", "BIP49", "BIP84"):
        raise ValueError("unsupported path type %s" % path_type)

    if isinstance(key, str):
        try:
            key = decode_base58(key, verify_checksum=True)
        except:
            try:
                key = bytes.fromhex(key)
            except:
                pass
    if not isinstance(key, bytes) or len(key) != 78:
        raise ValueError("invalid key")

    if key[:4] == TESTNET_XPRIVATE_KEY_PREFIX:
        if path_type == "BIP44":
            key = TESTNET_M44_XPRIVATE_KEY_PREFIX + key[4:]
        elif path_type == "BIP49":
            key = TESTNET_M49_XPRIVATE_KEY_PREFIX + key[4:]
        else:
            key = TESTNET_M84_XPRIVATE_KEY_PREFIX + key[4:]

    elif key[:4] == MAINNET_XPRIVATE_KEY_PREFIX:
        if path_type == "BIP44":
            key = MAINNET_M44_XPRIVATE_KEY_PREFIX + key[4:]
        elif path_type == "BIP49":
            key = MAINNET_M49_XPRIVATE_KEY_PREFIX + key[4:]
        else:
            key = MAINNET_M84_XPRIVATE_KEY_PREFIX + key[4:]

    elif key[:4] == TESTNET_XPUBLIC_KEY_PREFIX:
        if path_type == "BIP44":
            key = TESTNET_M44_XPUBLIC_KEY_PREFIX + key[4:]
        elif path_type == "BIP49":
            key = TESTNET_M49_XPUBLIC_KEY_PREFIX + key[4:]
        else:
            key = TESTNET_M84_XPUBLIC_KEY_PREFIX + key[4:]

    elif key[:4] == MAINNET_XPUBLIC_KEY_PREFIX:
        if path_type == "BIP44":
            key = MAINNET_M44_XPUBLIC_KEY_PREFIX + key[4:]
        elif path_type == "BIP49":
            key = MAINNET_M49_XPUBLIC_KEY_PREFIX + key[4:]
        else:
            key = MAINNET_M84_XPUBLIC_KEY_PREFIX + key[4:]
    else:
        raise ValueError("invalid extended key")

    if hex:

        return key.hex()
    elif base58:
        return encode_base58(key, checksum=True)
    else:
        return key
Example #7
0
def test_derive_child_xprivate_key():
    xpriv = "xprv9s21ZrQH143K3CSC8gBJRWPHPzi8Y17VzhuMGgSyyiGYzbbCnmUE1zpR2iQCz" \
            "VGPGAQBy2m7LTEtPAvfB6p2ECoQBAWtQYgYHpn1UFQv6Mi"
    assert "xprv9uxHkb3zFYjmC9AshDxocSv8SWphDkWq7VpNauF8hhGNMuqK2o4AKhhhuFADy1H5pVVAdZJCnyDmjZBZm" \
           "gUR8aciXXELWfU6tCF4BCrhz5m" == \
           encode_base58(derive_child_xprivate_key(decode_base58(xpriv, checksum=True), 1), checksum=True)


    assert "xprv9uxHkb3zFYjm9WnMk636CLyiCt2h6mgVR2u5iy8PgAkPW1xYCuUGYUzU6A4HWS7hDhKVQufiymoj9oYjqg" \
           "1h7331YjwVTfSBN97gSo65DiV"  == \
           encode_base58(derive_child_xprivate_key(decode_base58(xpriv, checksum=True), 0), checksum=True)

    assert "xprv9uxHkb3zFYzv3TK97XAQ5YykGBuFgMo5mKzjvQKuzbPf3FBeVgTC2ozTtspLBU2X4HWWFDocpB1sHjSX" \
           "Jby89m6cKhLhWUdhUWdF4o39kw4"  == \
           encode_base58(derive_child_xprivate_key(decode_base58(xpriv, checksum=True), 20000), checksum=True)

    assert "xprv9uxHkb3zFzs4rMGo9d25NcHCyePGswYHY6fMk76DzbZ5iCucy7VtdjYa1o4n28bnnGLW4ComhMjNiUKx" \
           "bgq6p6vc9zwHfHb1fvdhAvsURty" == \
           encode_base58(derive_child_xprivate_key(decode_base58(xpriv, checksum=True), 2000000), checksum=True)
Example #8
0
def xprivate_to_xpublic_key(xprivate_key, base58=True, hex=False):
    """
    Get extended public key from extended private key using ECDSA secp256k1

    :param str,bytes key: extended private key in base58, HEX or bytes string. 
    :param boolean base58: (optional) return result as base58 encoded string, by default True.
    :param boolean hex: (optional) return result as HEX encoded string, by default False.
                        In case True base58 flag value will be ignored.
    :return: extended public key  in base58, HEX or bytes string format.
    """
    if isinstance(xprivate_key, str):
        try:
            if len(xprivate_key) == 156:
                xprivate_key = bytes.fromhex(xprivate_key)
            else:
                xprivate_key = decode_base58(xprivate_key, checksum=True)
        except:
            raise ValueError("invalid extended private key")
    if not isinstance(xprivate_key, bytes):
        raise TypeError(
            "extended private key should be base58 string or bytes")
    if xprivate_key[:4] == TESTNET_XPRIVATE_KEY_PREFIX:
        prefix = TESTNET_XPUBLIC_KEY_PREFIX
    elif xprivate_key[:4] == MAINNET_XPRIVATE_KEY_PREFIX:
        prefix = MAINNET_XPUBLIC_KEY_PREFIX
    elif xprivate_key[:4] == MAINNET_M49_XPRIVATE_KEY_PREFIX:
        prefix = MAINNET_M49_XPUBLIC_KEY_PREFIX
    elif xprivate_key[:4] == TESTNET_M49_XPRIVATE_KEY_PREFIX:
        prefix = TESTNET_M49_XPUBLIC_KEY_PREFIX
    elif xprivate_key[:4] == MAINNET_M84_XPRIVATE_KEY_PREFIX:
        prefix = MAINNET_M84_XPUBLIC_KEY_PREFIX
    elif xprivate_key[:4] == TESTNET_M84_XPRIVATE_KEY_PREFIX:
        prefix = TESTNET_M84_XPUBLIC_KEY_PREFIX
    else:
        raise ValueError("invalid extended private key")

    key = b"".join([
        prefix, xprivate_key[4:45],
        private_to_public_key(xprivate_key[46:], hex=False)
    ])
    if hex:
        return key.hex()
    elif base58:
        key = b"".join([key, double_sha256(key)[:4]])
        return encode_base58(key)
    else:
        return key
Example #9
0
def private_key_to_wif(h, compressed=True, testnet=False):
    """
    Encode private key in HEX or RAW bytes format to WIF format.

    :param h: private key 32 byte string or HEX encoded string.
    :param compressed: (optional) flag of public key compressed format, by default set to True.  
    :param testnet: (optional) flag for testnet network, by default is False.
    :return: Private key in WIF format.
    """
    # uncompressed: 0x80 + [32-byte secret] + [4 bytes of Hash() of previous 33 bytes], base58 encoded.
    # compressed: 0x80 + [32-byte secret] + 0x01 + [4 bytes of Hash() previous 34 bytes], base58 encoded.
    if isinstance(h, str):
        h = bytes_from_hex(h)
    if len(h) != 32 and isinstance(h, bytes):
        raise TypeError("private key must be a 32 bytes or hex encoded string")
    if testnet:
        h = TESTNET_PRIVATE_KEY_BYTE_PREFIX + h
    else:
        h = MAINNET_PRIVATE_KEY_BYTE_PREFIX + h
    if compressed:
        h += b'\x01'
    h += double_sha256(h)[:4]
    return encode_base58(h)
Example #10
0
def path_xkey_to_bip32_xkey(key, base58=True, hex=False):
    if isinstance(key, str):
        try:
            key = decode_base58(key, verify_checksum=True)
        except:
            try:
                key = bytes.fromhex(key)
            except:
                pass

    if not isinstance(key, bytes) or len(key) != 78:
        raise ValueError("invalid extended key")

    if key[:4] in (MAINNET_XPUBLIC_KEY_PREFIX, TESTNET_XPUBLIC_KEY_PREFIX,
                   MAINNET_XPRIVATE_KEY_PREFIX, TESTNET_XPRIVATE_KEY_PREFIX):
        pass
    elif key[:4] in (MAINNET_M49_XPUBLIC_KEY_PREFIX,
                     MAINNET_M84_XPUBLIC_KEY_PREFIX):
        key = MAINNET_XPUBLIC_KEY_PREFIX + key[4:]
    elif key[:4] in (TESTNET_M49_XPUBLIC_KEY_PREFIX,
                     TESTNET_M84_XPUBLIC_KEY_PREFIX):
        key = TESTNET_XPUBLIC_KEY_PREFIX + key[4:]
    elif key[:4] in (MAINNET_M49_XPRIVATE_KEY_PREFIX,
                     MAINNET_M84_XPRIVATE_KEY_PREFIX):
        key = MAINNET_XPRIVATE_KEY_PREFIX + key[4:]
    elif key[:4] in (TESTNET_M49_XPRIVATE_KEY_PREFIX,
                     TESTNET_M84_XPRIVATE_KEY_PREFIX):
        key = TESTNET_XPRIVATE_KEY_PREFIX + key[4:]
    else:
        raise ValueError("invalid extended key")

    if hex:
        return key.hex()
    elif base58:
        return encode_base58(key, checksum=True)
    else:
        return key
Example #11
0
def derive_xkey(xkey, path, base58=None, hex=None, sub_path=False):
    """
    Child Key derivation for extended private/public keys
    
    :param bytes xkey: extended private/public in base58, HEX or bytes string format.
    :param list path_level: list of derivation path levels. For hardened derivation use HARDENED_KEY flag.
    :param boolean base58: (optional) return result as base58 encoded string, by default True.
    :param boolean hex: (optional) return result as HEX encoded string, by default False.
                        In case True base58 flag value will be ignored.
    :return: extended child private/public key  in base58, HEX or bytes string format.
    """
    if isinstance(path, str):
        path = decode_path(path, sub_path=sub_path)
    if isinstance(xkey, str):
        xkey = decode_base58(xkey, checksum=True)
    key_type = xkey_type(xkey)

    if key_type == 'private':
        for i in path:
            xkey = derive_child_xprivate_key(xkey, i)

    elif key_type == 'public':
        for i in path:
            xkey = derive_child_xpublic_key(xkey, i)
    else:
        raise ValueError("invalid extended key")

    if base58 is None and hex is None:
        base58 = True
        hex = False

    if hex:
        return xkey.hex()
    elif base58:
        return encode_base58(xkey, checksum=True)
    else:
        return xkey