Exemplo n.º 1
0
def derive_xkey(xkey, path, base58=None, hex=None):
    """
    Child Key derivation for extended private/public keys
    
    :param xkey: extended private/public in base58, HEX or bytes string format.
    :param path: list of derivation path levels. For hardened derivation use HARDENED_KEY flag.
    :param base58: (optional) return result as base58 encoded string, by default is True.
    :param hex: (optional) return result as HEX encoded string, by default is 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)
    if isinstance(xkey, str):
        xkey = decode_base58(xkey, checksum=True)
    if xkey[:4] in [MAINNET_XPRIVATE_KEY_PREFIX, TESTNET_XPRIVATE_KEY_PREFIX]:
        for i in path:
            xkey = derive_child_xprivate_key(xkey, i)

    elif xkey[:4] in [MAINNET_XPUBLIC_KEY_PREFIX, TESTNET_XPUBLIC_KEY_PREFIX]:
        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
Exemplo n.º 2
0
def is_xpublic_key_valid(key):
    """
    Check the extended private key is valid according to BIP-0032.

    :param key: extended private key in BASE58, HEX or bytes string format.
    :return: boolean.
    """
    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:
        return False

    if key[:4] not in [
            MAINNET_XPUBLIC_KEY_PREFIX, TESTNET_XPUBLIC_KEY_PREFIX,
            MAINNET_M49_XPUBLIC_KEY_PREFIX, TESTNET_M49_XPUBLIC_KEY_PREFIX,
            MAINNET_M84_XPUBLIC_KEY_PREFIX, TESTNET_M84_XPUBLIC_KEY_PREFIX
    ]:
        return False
    return True
Exemplo n.º 3
0
def is_wif_valid(wif):
    """
    Check is private key in WIF format string is valid.

    :param wif: private key in WIF format string.
    :return: boolean.
    """
    if not isinstance(wif, str):
        return False
    if wif[0] not in PRIVATE_KEY_PREFIX_LIST:
        return False
    try:
        h = decode_base58(wif)
    except:
        return False
    checksum = h[-4:]
    if wif[0] in (MAINNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX,
                  TESTNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX):
        if len(h) != 37:
            return False
    elif len(h) != 38:
        return False
    if double_sha256(h[:-4])[:4] != checksum:
        return False
    return True
Exemplo n.º 4
0
def private_to_public_key(private_key, compressed=True, hex=True):
    """
    Get public key from private key using ECDSA secp256k1

    :param private_key: private key in WIF, HEX or bytes.
    :param compressed: (optional) flag of public key compressed format, by default is True.
                       In case private_key in WIF format, this flag is set in accordance with 
                       the key format specified in WIF string.
    :param hex:  (optional) if set to True return key in HEX format, by default is True.
    :return: 33/65 bytes public key in HEX or bytes string.
    """
    if not isinstance(private_key, bytes):
        if isinstance(private_key, bytearray):
            private_key = bytes(private_key)
        elif isinstance(private_key, str):
            try:
                if private_key[0] in (MAINNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX,
                                      TESTNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX):
                    compressed = False
                h = decode_base58(private_key)
                if double_sha256(h[:-4])[:4] != h[-4:]:
                    raise Exception()
                private_key = h[1:33]
            except:
                try:
                    private_key = bytes_from_hex(private_key)
                except:
                    raise ValueError("private key HEX or WIF invalid")
        else:
            raise ValueError(
                "private key must be a bytes or WIF or hex encoded string")
        if len(private_key) != 32:
            raise ValueError("private key length invalid")
    pub = __secp256k1_ec_pubkey_create__(private_key, bool(compressed))
    return pub.hex() if hex else pub
Exemplo n.º 5
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 key")

    if hex:

        return key.hex()
    elif base58:
        return encode_base58(key, checksum=True)
    else:
        return key
Exemplo n.º 6
0
def wif_to_private_key(h, hex=True):
    """
    Decode WIF private key to bytes string or HEX encoded string

    :param h:  private key in WIF format string.
    :param hex:  (optional) if set to True return key in HEX format, by default is True.
    :return: Private key HEX encoded string or raw bytes string.
    """
    h = decode_base58(h)
    if double_sha256(h[:-4])[:4] != h[-4:]:
        raise TypeError("invalid wif key")
    return h[1:33].hex() if hex else h[1:33]
Exemplo n.º 7
0
def address_to_hash(address, hex=True):
    """
    Get address hash from base58 or bech32 address format.

    :param address: address in base58 or bech32 format.
    :param hex:  (optional) If set to True return key in HEX format, by default is True.
    :return: script in HEX or bytes string.
    """
    if address[0] in ADDRESS_PREFIX_LIST:
        h = decode_base58(address)[1:-4]
    elif address.split("1")[0] in (MAINNET_SEGWIT_ADDRESS_PREFIX,
                         TESTNET_SEGWIT_ADDRESS_PREFIX, REGTEST_SEGWIT_ADDRESS_PREFIX):
        address = address.split("1")[1]
        h = rebase_5_to_8(rebase_32_to_5(address)[1:-6], False)
    else:
        return None
    return h.hex() if hex else h
Exemplo n.º 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 xprivate_key: extended private key in base58, HEX or bytes string.
    :param base58: (optional) return result as base58 encoded string, by default is True.
    :param hex: (optional) return result as HEX encoded string, by default is 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
    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
Exemplo n.º 9
0
def public_from_xpublic_key(xpublic_key, hex=True):
    """
    Get public key from extended public key

    :param xpublic_key: extended public in base58, HEX or bytes string format.
    :param base58: (optional) return result as base58 encoded string, by default is True.
    :param hex: (optional) return result as HEX encoded string, by default is False.
                        In case True base58 flag value will be ignored.
    :return: public key  in HEX or bytes string format.
    """
    if isinstance(xpublic_key, str):
        if len(xpublic_key) == 156:
            xpublic_key = bytes.fromhex(xpublic_key)
        else:
            xpublic_key = decode_base58(xpublic_key, checksum=True)
    if not isinstance(xpublic_key, bytes):
        raise TypeError("xpublic_key should be HEX, Base58 or bytes string")
    if xpublic_key[:4] not in [
            MAINNET_XPUBLIC_KEY_PREFIX, TESTNET_XPUBLIC_KEY_PREFIX
    ]:
        raise ValueError("invalid extended public key")

    return xpublic_key[45:].hex() if hex else xpublic_key[45:]
Exemplo n.º 10
0
def private_from_xprivate_key(xprivate_key, wif=True, hex=False):
    """
    Get private key from extended private key

    :param xprivate_key: extended private in base58, HEX or bytes string format.
    :param wif: (optional) return result as WIF format, by default is True.
    :param hex: (optional) return result as HEX encoded string, by default is False.
                        In case True WIF flag value will be ignored.
    :return: private key  in HEX or bytes string format.
    """
    if isinstance(xprivate_key, str):
        if len(xprivate_key) == 156:
            xprivate_key = bytes.fromhex(xprivate_key)
        else:
            xprivate_key = decode_base58(xprivate_key, checksum=True)
    if not isinstance(xprivate_key, bytes):
        raise TypeError("xprivate_key should be HEX, Base58 or bytes string")

    prefix = xprivate_key[:4]

    if prefix in (MAINNET_XPRIVATE_KEY_PREFIX, MAINNET_M44_XPRIVATE_KEY_PREFIX,
                  MAINNET_M49_XPRIVATE_KEY_PREFIX,
                  MAINNET_M84_XPRIVATE_KEY_PREFIX):
        testnet = False
    elif prefix in (TESTNET_XPRIVATE_KEY_PREFIX,
                    TESTNET_M44_XPRIVATE_KEY_PREFIX,
                    TESTNET_M49_XPRIVATE_KEY_PREFIX,
                    TESTNET_M84_XPRIVATE_KEY_PREFIX):
        testnet = True
    else:
        raise ValueError("invalid extended private key")

    if hex:
        return xprivate_key[46:].hex()
    elif wif:
        return private_key_to_wif(xprivate_key[46:], testnet=testnet)
    return xprivate_key[46:].hex() if hex else xprivate_key[46:]
Exemplo n.º 11
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
Exemplo n.º 12
0
def is_address_valid(address, testnet=False, regtest=False):
    """
    Check is address valid.

    :param address: address in base58 or bech32 format.
    :param testnet: (optional) flag for testnet network, by default is False.
    :return: boolean.
    """
    print("addr",address)
    if not address or type(address) != str:
        return False
    if address[0] in (MAINNET_ADDRESS_PREFIX,
                      MAINNET_SCRIPT_ADDRESS_PREFIX,
                      TESTNET_ADDRESS_PREFIX,
                      TESTNET_ADDRESS_PREFIX_2,
                      TESTNET_SCRIPT_ADDRESS_PREFIX):
        if testnet:
            if address[0] not in (TESTNET_ADDRESS_PREFIX,
                                  TESTNET_ADDRESS_PREFIX_2,
                                  TESTNET_SCRIPT_ADDRESS_PREFIX):
                return False
        else:
            if address[0] not in (MAINNET_ADDRESS_PREFIX,
                                  MAINNET_SCRIPT_ADDRESS_PREFIX):
                return False
        h = decode_base58(address)
        if len(h) != 25:
            return False
        checksum = h[-4:]
        if sha3_256(h[:-4])[:4] != checksum:
            return False
        return True
    elif (address[:3] == MAINNET_SEGWIT_ADDRESS_PREFIX) \
             or (address[:4] == TESTNET_SEGWIT_ADDRESS_PREFIX) or (address[:4] == REGTEST_SEGWIT_ADDRESS_PREFIX):
        if len(address) not in (43,44, 63, 64):
            return False
        try:
            prefix, payload = address.split('1')
        except:
            return False
        upp = True if prefix[0].isupper() else False
        for i in payload[1:]:
            if upp:
                if not i.isupper() or i not in base32charset_upcase:
                    return False
            else:
                if i.isupper() or i not in base32charset:
                    return False

        payload = payload.lower()
        prefix = prefix.lower()
        if testnet:
            if prefix != TESTNET_SEGWIT_ADDRESS_PREFIX and prefix != REGTEST_SEGWIT_ADDRESS_PREFIX:
                return False
            stripped_prefix = TESTNET_SEGWIT_ADDRESS_BYTE_PREFIX
            if regtest:
                stripped_prefix = REGTEST_SEGWIT_ADDRESS_BYTE_PREFIX
        else:
            if prefix != MAINNET_SEGWIT_ADDRESS_PREFIX:
                return False
            stripped_prefix = MAINNET_SEGWIT_ADDRESS_BYTE_PREFIX
        d = rebase_32_to_5(payload)

        address_hash = d[:-6]
        checksum = d[-6:]
        print("checksum", checksum)
        print("checksum_back", rebase_5_to_32(checksum))
        checksum2 = bech32_polymod(b"%s%s%s" % (stripped_prefix, address_hash, b"\x00" * 6))
        checksum2 = rebase_8_to_5(checksum2.to_bytes(5, "big"))[2:]
        print("checksum2",checksum2)
        print("checksum2_back", rebase_5_to_32(checksum2))
        if checksum != checksum2:
            return False
        print("checksum2", checksum2)
        return True
    return False