def get_xpub(self, bip32_path, xtype): assert xtype in ColdcardPlugin.SUPPORTED_XTYPES _logger.info('Derive xtype = %r' % xtype) xpub = self.dev.send_recv(CCProtocolPacker.get_xpub(bip32_path), timeout=5000) # TODO handle timeout? # change type of xpub to the requested type try: node = BIP32Node.from_xkey(xpub) except InvalidMasterKeyVersionBytes: raise UserFacingException( _('Invalid xpub magic. Make sure your {} device is set to the correct chain.' ).format(self.device)) from None if xtype != 'standard': xpub = node._replace(xtype=xtype).to_xpub() return xpub
def on_receive(self, keyhash, message): self.logger.info(f"signal arrived for {keyhash}") for key, _hash, window in self.keys: if _hash == keyhash: break else: self.logger.info("keyhash not found") return wallet = window.wallet if isinstance(wallet.keystore, keystore.Hardware_KeyStore): window.show_warning( _('An encrypted transaction was retrieved from cosigning pool.' ) + '\n' + _('However, hardware wallets do not support message decryption, ' 'which makes them not compatible with the current design of cosigner pool.' )) return elif wallet.has_keystore_encryption(): password = window.password_dialog( _('An encrypted transaction was retrieved from cosigning pool.' ) + '\n' + _('Please enter your password to decrypt it.')) if not password: return else: password = None if not window.question( _("An encrypted transaction was retrieved from cosigning pool." ) + '\n' + _("Do you want to open it now?")): return xprv = wallet.keystore.get_master_private_key(password) if not xprv: return try: privkey = BIP32Node.from_xkey(xprv).eckey message = privkey.decrypt_message(message) except Exception as e: self.logger.exception('') window.show_error(_('Error decrypting message') + ':\n' + repr(e)) return self.listener.clear(keyhash) tx = tx_from_any(message) show_transaction(tx, parent=window, prompt_if_unsaved=True)
def get_xpub(self, bip32_path, xtype): self.checkDevice() # bip32_path is of the form 44'/0'/1' # S-L-O-W - we don't handle the fingerprint directly, so compute # it manually from the previous node # This only happens once so it's bearable #self.get_client() # prompt for the PIN before displaying the dialog if necessary #self.handler.show_message("Computing master public key") if xtype in ['p2wpkh', 'p2wsh'] and not self.supports_native_segwit(): raise UserFacingException(MSG_NEEDS_FW_UPDATE_SEGWIT) if xtype in ['p2wpkh-p2sh', 'p2wsh-p2sh' ] and not self.supports_segwit(): raise UserFacingException(MSG_NEEDS_FW_UPDATE_SEGWIT) splitPath = bip32_path.split('/') if splitPath[0] == 'm': splitPath = splitPath[1:] bip32_path = bip32_path[2:] fingerprint = 0 if len(splitPath) > 1: prevPath = "/".join(splitPath[0:len(splitPath) - 1]) nodeData = self.dongleObject.getWalletPublicKey(prevPath) publicKey = compress_public_key(nodeData['publicKey']) h = hashlib.new('ripemd160') h.update(hashlib.sha256(publicKey).digest()) fingerprint = unpack(">I", h.digest()[0:4])[0] nodeData = self.dongleObject.getWalletPublicKey(bip32_path) publicKey = compress_public_key(nodeData['publicKey']) depth = len(splitPath) lastChild = splitPath[len(splitPath) - 1].split('\'') childnum = int(lastChild[0]) if len( lastChild) == 1 else 0x80000000 | int(lastChild[0]) return BIP32Node(xtype=xtype, eckey=ecc.ECPubkey(publicKey), chaincode=nodeData['chainCode'], depth=depth, fingerprint=self.i4b(fingerprint), child_number=self.i4b(childnum)).to_xpub()
def get_xpub(self, bip32_path, xtype): self.checkDevice() # bip32_path is of the form 44'/0'/1' # S-L-O-W - we don't handle the fingerprint directly, so compute # it manually from the previous node # This only happens once so it's bearable #self.get_client() # prompt for the PIN before displaying the dialog if necessary #self.handler.show_message("Computing master public key") if xtype in ['p2wpkh', 'p2wsh'] and not self.supports_native_segwit(): raise UserFacingException(MSG_NEEDS_FW_UPDATE_SEGWIT) if xtype in ['p2wpkh-p2sh', 'p2wsh-p2sh' ] and not self.supports_segwit(): raise UserFacingException(MSG_NEEDS_FW_UPDATE_SEGWIT) bip32_path = bip32.normalize_bip32_derivation(bip32_path) bip32_intpath = bip32.convert_bip32_path_to_list_of_uint32(bip32_path) bip32_path = bip32_path[2:] # cut off "m/" if len(bip32_intpath) >= 1: prevPath = bip32.convert_bip32_intpath_to_strpath( bip32_intpath[:-1])[2:] nodeData = self.dongleObject.getWalletPublicKey(prevPath) publicKey = compress_public_key(nodeData['publicKey']) fingerprint_bytes = hash_160(publicKey)[0:4] childnum_bytes = bip32_intpath[-1].to_bytes(length=4, byteorder="big") else: fingerprint_bytes = bytes(4) childnum_bytes = bytes(4) nodeData = self.dongleObject.getWalletPublicKey(bip32_path) publicKey = compress_public_key(nodeData['publicKey']) depth = len(bip32_intpath) return BIP32Node(xtype=xtype, eckey=ecc.ECPubkey(publicKey), chaincode=nodeData['chainCode'], depth=depth, fingerprint=fingerprint_bytes, child_number=childnum_bytes).to_xpub()
def request_root_fingerprint_from_device(self) -> str: # digitalbitbox (at least) does not reveal xpubs corresponding to unhardened paths # so ask for a direct child, and read out fingerprint from that: child_of_root_xpub = self.get_xpub("m/0'", xtype='standard') root_fingerprint = BIP32Node.from_xkey(child_of_root_xpub).fingerprint.hex().lower() return root_fingerprint
def get_account_xpub(account_path): root_seed = bip39_to_seed(mnemonic, passphrase) root_node = BIP32Node.from_rootseed(root_seed, xtype="standard") account_node = root_node.subkey_at_private_derivation(account_path) account_xpub = account_node.to_xpub() return account_xpub