Beispiel #1
0
    def get_pubkey_at_path(self, path):
        if not check_keypath(path):
            raise BadArgumentError("Invalid keypath")
        path = path[2:]
        path = path.replace("h", "'")
        path = path.replace("H", "'")
        # This call returns raw uncompressed pubkey, chaincode
        pubkey = self.app.getWalletPublicKey(path)
        if path != "":
            parent_path = ""
            for ind in path.split("/")[:-1]:
                parent_path += ind + "/"
            parent_path = parent_path[:-1]

            # Get parent key fingerprint
            parent = self.app.getWalletPublicKey(parent_path)
            fpr = hash160(compress_public_key(parent["publicKey"]))[:4]

            # Compute child info
            childstr = path.split("/")[-1]
            hard = 0
            if childstr[-1] == "'" or childstr[-1] == "h" or childstr[
                    -1] == "H":
                childstr = childstr[:-1]
                hard = 0x80000000
            child = struct.pack(">I", int(childstr) + hard)
        # Special case for m
        else:
            child = bytearray.fromhex("00000000")
            fpr = child

        chainCode = pubkey["chainCode"]
        publicKey = compress_public_key(pubkey["publicKey"])

        depth = len(path.split("/")) if len(path) > 0 else 0
        depth = struct.pack("B", depth)

        if self.is_testnet:
            version = bytearray.fromhex("043587CF")
        else:
            version = bytearray.fromhex("0488B21E")
        extkey = version + depth + fpr + child + chainCode + publicKey
        checksum = hash256(extkey)[:4]

        xpub = base58.encode(extkey + checksum)
        result = {"xpub": xpub}

        if self.expert:
            xpub_obj = ExtendedKey()
            xpub_obj.deserialize(xpub)
            result.update(xpub_obj.get_printable_dict())
        return result
def xpub_test_2_main(xpub: str) -> str:
    data = base58.decode(xpub)
    main_data = b"\x04\x88\xb2\x1e" + data[4:-4]
    checksum = base58.hash256(main_data)[0:4]
    return base58.encode(main_data + checksum)
Beispiel #3
0
def HDWQryXpub(conn, path, hstCred):
    # IN path like : [2147483692, 2147483648, 2147483648]
    Client_log.info('[HDWQryXpub]')
    Client_log.debug('[Path]: %s', path)

    Client_log.info('[1] parser path')
    #------------------------ parser path ------------------------
    # m / purpose' / coin_type' / account' / change / address_index
    purpose = '2c000080'  # purpose' set to 44 following the BIP43
    cointype = ''
    account = ''
    change = ''
    address_i = ''

    if len(path) == 1:
        purpose = path[0].to_bytes(4, 'little').hex()
        childnumber = path[0].to_bytes(4, 'big').hex()
    elif len(path) == 2:
        purpose = path[0].to_bytes(4, 'little').hex()
        cointype = path[1].to_bytes(4, 'little').hex()
        childnumber = path[1].to_bytes(4, 'big').hex()
    elif len(path) == 3:
        purpose = path[0].to_bytes(4, 'little').hex()
        cointype = path[1].to_bytes(4, 'little').hex()
        account = path[2].to_bytes(4, 'little').hex()
        childnumber = path[2].to_bytes(4, 'big').hex()
    elif len(path) == 4:
        purpose = path[0].to_bytes(4, 'little').hex()
        cointype = path[1].to_bytes(4, 'little').hex()
        account = path[2].to_bytes(4, 'little').hex()
        change = path[3].to_bytes(4, 'little').hex()
        childnumber = path[3].to_bytes(4, 'big').hex()
    elif len(path) == 5:
        purpose = path[0].to_bytes(4, 'little').hex()
        cointype = path[1].to_bytes(4, 'little').hex()
        account = path[2].to_bytes(4, 'little').hex()
        change = path[3].to_bytes(4, 'little').hex()
        address_i = path[4].to_bytes(4, 'little').hex()
        childnumber = path[4].to_bytes(4, 'big').hex()
    else:
        raise ValueError('[HDWQryXpub]: error at path')

    Client_log.debug(
        '[Parser Path](m/purpose/coin_type/account/change/address): m/%s/%s/%s/%s/%s',
        purpose, cointype, account, change, address_i)

    Client_log.info('[2] get pubkey')
    #------------------------ get pubkey ------------------------
    ret = conn.se_hdw_qry_xpub(purpose, cointype, account, change, address_i)

    rdata = bytes.fromhex(analysisReData(ret))
    pubk = rdata[:64]  # 64 bytes: public key
    chacode = rdata[64:64 + 32]  # 32 bytes: chain code
    fingerprint = rdata[64 + 32:64 + 32 +
                        4]  # 4 bytes: the fingerprint of the parent's key
    rmac = rdata[64 + 32 + 4:64 + 32 + 4 + 32]  # 32 bytes: retuen MAC

    # get login info
    data = Readkey()
    Regotp = data[1:1 + 6]
    loginChlng = data[1 + 6:1 + 6 + 32]

    Client_log.info('[3] check mac')
    #------------------------ check mac ------------------------
    mac = bind_session_mac(rdata[:64 + 32 + 4], hstCred, Regotp, loginChlng)
    if rmac != mac:
        raise ValueError('[HDWQryXpub]: MAC failed')

    Client_log.info('[4] make ex_pubkey')
    #------------------------ make ex_pubkey ------------------------
    version = '0488B21E'  # 4 bytes: version bytes (mainnet public)
    # CW not support testnet version
    ''' 
    if testnet:
        version = '043587CF'            # 4 bytes: version bytes (testnet public)
    '''
    depth = "{:0>2d}".format(len(path))  # 1 byte: depth

    #childnumber = '80000000'           # 4 bytes: child number (hardened addresses)

    pubkey_x = pubk[:32]  # 32 bytes: public key x coordinate
    if int(pubk[32:].hex(), 16) % 2 == 0:
        prefix = '02'  # 1 byte: public key y coordinate is even
    else:
        prefix = '03'  # 1 byte: public key y coordinate is odd

    tmp = version \
        + depth \
        + fingerprint.hex() \
        + childnumber \
        + chacode.hex() \
        + prefix \
        + pubkey_x.hex()

    # double sha256
    sha256 = hashlib.sha256()
    sha256.update(bytes.fromhex(tmp))
    checksum_tmp = sha256.digest()
    sha256 = hashlib.sha256()
    sha256.update(checksum_tmp)
    checksum = sha256.digest()

    ex_pubkey = version \
              + depth \
              + fingerprint.hex() \
              + childnumber \
              + chacode.hex() \
              + prefix \
              + pubkey_x.hex() \
              + checksum[:4].hex()

    return encode(bytes.fromhex(ex_pubkey))
Beispiel #4
0
    def test_encoding(self):
        """Test base58 encoding"""

        for pair in TEST_VECTORS:
            encoded: str = base58.encode(unhexlify(pair[0]))
            self.assertEqual(encoded, pair[1])