Exemplo n.º 1
0
 def check_password(self, password):
     xprv = pw_decode(self.xprv, password)
     try:
         assert (bip32_key_from_string(xprv).derivation().chain_code
                 == bip32_key_from_string(self.xpub).derivation().chain_code)
     except (ValueError, AssertionError):
         raise InvalidPassword()
Exemplo n.º 2
0
 def check_password(self, password: Optional[str]) -> None:
     assert self.xprv is not None
     xprv = pw_decode(self.xprv, password)
     try:
         assert (bip32_key_from_string(xprv).derivation().chain_code ==
                 bip32_key_from_string(self.xpub).derivation().chain_code)
     except (ValueError, AssertionError, Base58Error):
         raise InvalidPassword()
Exemplo n.º 3
0
 def get_private_key(self, derivation_path: Sequence[int],
                     password: str) -> Tuple[bytes, bool]:
     xprv = self.get_master_private_key(password)
     privkey = bip32_key_from_string(xprv)
     for n in derivation_path:
         privkey = privkey.child_safe(n)
     return privkey.to_bytes(), True
Exemplo n.º 4
0
 def derive_pubkey(self, for_change, n):
     xpub = self.xpub_change if for_change else self.xpub_receive
     if xpub is None:
         xpub = bip32_key_from_string(self.xpub)
         xpub = xpub.child(1 if for_change else 0).to_extended_key_string()
         if for_change:
             self.xpub_change = xpub
         else:
             self.xpub_receive = xpub
     return self.get_pubkey_from_xpub(xpub, (n,))
Exemplo n.º 5
0
 def derive_pubkey(self, derivation_path: Sequence[int]) -> PublicKey:
     parent_path = derivation_path[:-1]
     xpub = self._child_xpubs.get(parent_path)
     if xpub is None:
         xpubkey = bip32_key_from_string(self.xpub)
         for n in parent_path:
             xpubkey = xpubkey.child_safe(n)
         xpub = xpubkey.to_extended_key_string()
         self._child_xpubs[parent_path] = xpub
     return self.get_pubkey_from_xpub(xpub, derivation_path[-1:])
Exemplo n.º 6
0
 def _make_node_path(self, xpub, address_n):
     pubkey = bip32_key_from_string(xpub)
     derivation = pubkey.derivation()
     node = HDNodeType(
         depth=derivation.depth,
         fingerprint=be_bytes_to_int(pubkey.fingerprint()),
         child_num=derivation.n,
         chain_code=derivation.chain_code,
         public_key=pubkey.to_bytes(),
     )
     return HDNodePathType(node=node, address_n=address_n)
Exemplo n.º 7
0
def from_master_key(text: str) -> Union[BIP32_KeyStore, Old_KeyStore]:
    if is_xprv(text):
        k = BIP32_KeyStore({})
        k.add_xprv(bip32_key_from_string(text))
    elif Old_KeyStore.is_hex_mpk(text):
        k = Old_KeyStore.from_mpk(text)
    elif is_xpub(text):
        k = from_xpub(text)
    else:
        raise Exception('Invalid key')
    return k
Exemplo n.º 8
0
 def window_opened(self, window):
     wallet = window.wallet
     if cosigner_pool.is_enabled() and type(wallet) == Multisig_Wallet:
         items = []
         for key, keystore in wallet.keystores.items():
             xpub = keystore.get_master_public_key()
             pubkey = bip32_key_from_string(xpub)
             K = pubkey.to_bytes()
             K_hash = bh2u(sha256d(K))
             items.append(
                 CosignerItem(window, xpub, K, K_hash,
                              keystore.is_watching_only()))
         # Presumably atomic
         self.items.extend(items)
Exemplo n.º 9
0
    def on_receive(self, keyhash, message):
        logger.debug("signal arrived for '%s'", keyhash)
        for item in self.items:
            if item.hash == keyhash and not item.watching_only:
                window = item.window
                break
        else:
            logger.error("keyhash not found")
            return

        parent_wallet = window.parent_wallet
        wallet = parent_wallet.get_default_wallet()
        if isinstance(wallet.get_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.'
                  ))
            self.listener.clear(keyhash)
            return

        if parent_wallet.has_password():
            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

        self.listener.clear(keyhash)

        xprv = wallet.get_keystore().get_master_private_key(password)
        if not xprv:
            return
        privkey = bip32_key_from_string(xprv)
        try:
            message = bh2u(privkey.decrypt_message(message))
        except Exception as e:
            logger.exception("")
            window.show_error(_('Error decrypting message') + ':\n' + str(e))
            return

        tx = Transaction.from_hex(message)
        window.show_transaction(tx, prompt_if_unsaved=True)
Exemplo n.º 10
0
    def test_bip32_extended_keys(self, raw_hex, path, coin):
        # see test_keystore.py
        xpub = ('xpub661MyMwAqRbcH1RHYeZc1zgwYLJ1dNozE8npCe81pnNYtN6e5KsF6cmt17Fv8w'
                'GvJrRiv6Kewm8ggBG6N3XajhoioH3stUmLRi53tk46CiA')
        root_key = bip32_key_from_string(xpub)
        True_10_public_key = root_key.child(path[0]).child(path[1])

        x_pubkey = XPublicKey.from_bytes(bytes.fromhex(raw_hex))
        # assert x_pubkey.to_bytes() == bytes.fromhex(raw_hex)
        # assert x_pubkey.to_hex() == raw_hex
        assert x_pubkey.is_bip32_key()
        assert x_pubkey.bip32_extended_key_and_path() == (xpub, path)
        assert x_pubkey.to_public_key() == True_10_public_key
        assert x_pubkey.to_address() == True_10_public_key.to_address(coin=coin)
        assert x_pubkey.to_address().coin() is coin
Exemplo n.º 11
0
    def _event_text_changed(self) -> None:
        if self._key_edit.isReadOnly():
            return

        text = self._key_edit.toPlainText()
        try:
            key = bip32_key_from_string(text)
        except ValueError:
            return
        else:
            if not isinstance(key, BIP32PublicKey):
                return

        password = None
        keystore = instantiate_keystore_from_text(
            KeystoreTextType.EXTENDED_PUBLIC_KEY, text, password)
        self._update_keystore(keystore)
Exemplo n.º 12
0
    def _on_receive(self, item: CosignerItem, message: str) -> None:
        logger.debug("signal arrived for '%s'", item.keyhash_hex)
        window = item.window
        account = window._wallet.get_account(item.account_id)

        for keystore in account.get_keystores():
            if keystore.get_master_public_key() == item.xpub:
                break
        else:
            window.show_error(
                _('Message for non-existent non-watching cosigner'))
            return

        if isinstance(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 incompatible with the current design of cosigner pool.'
                  ))
            self._listener.clear(item.keyhash_hex)
            return

        password = window.password_dialog(
            _('An encrypted transaction was retrieved from cosigning pool.') +
            '\n' + _('Please enter your password to decrypt it.'))
        if not password:
            return

        self._listener.clear(item.keyhash_hex)

        xprv = keystore.get_master_private_key(password)
        if not xprv:
            return
        privkey = bip32_key_from_string(xprv)
        try:
            message = privkey.decrypt_message(message).decode()
        except Exception as e:
            logger.exception("")
            window.show_error(_('Error decrypting message') + ':\n' + str(e))
            return

        txdict = json.loads(message)
        tx = Transaction.from_dict(txdict)
        window.show_transaction(account, tx, prompt_if_unsaved=True)
Exemplo n.º 13
0
    def _window_opened(self, window: 'ElectrumWindow') -> None:
        if not cosigner_pool.is_enabled():
            return

        for account in window._wallet.get_accounts():
            if type(account) is not MultisigAccount:
                continue

            account_id = account.get_id()
            items = []
            for keystore in account.get_keystores():
                xpub = keystore.get_master_public_key()
                pubkey = bip32_key_from_string(xpub)
                pubkey_bytes = pubkey.to_bytes()
                keyhash_hex = sha256d(pubkey_bytes).hex()
                items.append(CosignerItem(window, account_id, xpub, pubkey_bytes,
                    keyhash_hex, keystore.is_watching_only()))
            self._items.extend(items)
Exemplo n.º 14
0
 def to_public_key(self) -> Union[BIP32PublicKey, PublicKey]:
     '''Returns a PublicKey instance or an Address instance.'''
     kind = self.kind()
     if self._pubkey_bytes is not None:
         return PublicKey.from_bytes(self._pubkey_bytes)
     elif self._bip32_xpub is not None:
         assert self._derivation_path is not None
         result = bip32_key_from_string(self._bip32_xpub)
         for n in self._derivation_path:
             result = result.child(n)
         return result
     elif self._old_mpk is not None:
         assert self._derivation_path is not None
         path = self._derivation_path
         pubkey = PublicKey.from_bytes(pack_byte(4) + self._old_mpk)
         # pylint: disable=unsubscriptable-object
         delta = double_sha256(f'{path[1]}:{path[0]}:'.encode() + self._old_mpk)
         return pubkey.add(delta)
     raise ValueError("invalid key data")
Exemplo n.º 15
0
 def get_pubkey_from_xpub(self, xpub, sequence):
     pubkey = bip32_key_from_string(xpub)
     for n in sequence:
         pubkey = pubkey.child_safe(n)
     return pubkey.to_hex()
Exemplo n.º 16
0
def is_xpub(text):
    try:
        key = bip32_key_from_string(text)
        return isinstance(key, BIP32PublicKey)
    except Exception:
        return False
Exemplo n.º 17
0
 def get_pubkey_from_xpub(self, xpub: str,
                          sequence: Sequence[int]) -> PublicKey:
     pubkey = bip32_key_from_string(xpub)
     for n in sequence:
         pubkey = pubkey.child_safe(n)
     return pubkey
Exemplo n.º 18
0
    def __init__(self, main_window: ElectrumWindow, parent: QWidget,
                 keystore: KeyStore, password: str) -> None:
        super().__init__(parent)

        self._main_window = main_window

        self.setWindowTitle(_("Secured Account Data"))
        self.setMinimumSize(500, 200)

        vbox = QVBoxLayout()
        self._form = form = FormSectionWidget(minimum_label_width=120)

        assert keystore.derivation_type in (DerivationType.BIP32,
                                            DerivationType.ELECTRUM_OLD)

        self._seed_edit = None
        if keystore.seed is not None:
            seed_text = keystore.get_seed(password)

            seed_type_text = _("Unknown")
            if keystore.derivation_type == DerivationType.BIP32:
                if is_new_seed(seed_text):
                    seed_type_text = _("Electrum")
                is_checksum_valid, is_wordlist_valid = bip39_is_checksum_valid(
                    seed_text)
                if is_checksum_valid and is_wordlist_valid:
                    seed_type_text = _("BIP39")
            elif keystore.derivation_type == DerivationType.ELECTRUM_OLD:
                seed_type_text = _("Old-style Electrum")
            form.add_row(_("Seed type"), QLabel(seed_type_text))

            seed_edit = ShowQRTextEdit(self)
            seed_edit.setFixedHeight(80)
            seed_edit.addCopyButton(self._main_window.app)
            seed_edit.setText(seed_text)
            form.add_row(_("Seed phrase"), seed_edit, True)
            self._seed_edit = seed_edit

        # Ambiguous if empty string or None.
        passphrase_widget: QWidget
        if keystore.passphrase:
            passphrase_text = keystore.get_passphrase(password)

            passphrase_edit = ShowQRTextEdit(self)
            passphrase_edit.setFixedHeight(80)
            passphrase_edit.addCopyButton(self._main_window.app)
            passphrase_edit.setText(passphrase_text)
            passphrase_widget = passphrase_edit
        else:
            passphrase_widget = QLabel(_("None"))
        form.add_row(_("Passphrase"), passphrase_widget, True)

        if keystore.derivation_type == DerivationType.BIP32:
            if keystore.xprv is not None:
                xprv_text = keystore.get_master_private_key(password)
                private_key = bip32_key_from_string(xprv_text)

                xprv_edit = ShowQRTextEdit(self)
                xprv_edit.setFixedHeight(80)
                xprv_edit.addCopyButton(self._main_window.app)
                xprv_edit.setText(private_key.to_extended_key_string())
                form.add_row(_("Master private key"), xprv_edit, True)

        vbox.addWidget(form)
        vbox.addStretch(1)
        vbox.addLayout(Buttons(CloseButton(self)))
        self.setLayout(vbox)
Exemplo n.º 19
0
 def get_fingerprint(self) -> bytes:
     return bip32_key_from_string(self.xpub).fingerprint()
Exemplo n.º 20
0
def instantiate_keystore_from_text(text_type: KeystoreTextType,
                                   text_match: Union[str, List[str]],
                                   password: Optional[str],
                                   derivation_text: Optional[str] = None,
                                   passphrase: Optional[str] = None,
                                   watch_only: bool = False) -> KeyStore:
    derivation_type: Optional[DerivationType] = None
    data: Dict[str, Any] = {}
    if text_type == KeystoreTextType.EXTENDED_PUBLIC_KEY:
        derivation_type = DerivationType.BIP32
        assert isinstance(text_match, str)
        assert passphrase is None
        # `watch_only` is ignored.
        data['xpub'] = text_match
    elif text_type == KeystoreTextType.EXTENDED_PRIVATE_KEY:
        derivation_type = DerivationType.BIP32
        assert isinstance(text_match, str)
        assert passphrase is None
        if not watch_only:
            assert password is not None
            data['xprv'] = pw_encode(text_match, password)
        private_key = bip32_key_from_string(text_match)
        data['xpub'] = private_key.public_key.to_extended_key_string()
    elif text_type == KeystoreTextType.PRIVATE_KEYS:
        derivation_type = DerivationType.IMPORTED
        # watch_only?
    elif text_type == KeystoreTextType.ADDRESSES:
        derivation_type = DerivationType.IMPORTED
        # All address types have to be the same.
        pass
    elif text_type == KeystoreTextType.BIP39_SEED_WORDS:
        derivation_type = DerivationType.BIP32
        if derivation_text is None:
            derivation_text = bip44_derivation_cointype(0, 0)
        assert isinstance(text_match, str)
        bip32_seed = bip39_to_seed(text_match, passphrase)
        xprv = BIP32PrivateKey.from_seed(bip32_seed, Net.COIN)
        for n in bip32_decompose_chain_string(derivation_text):
            xprv = xprv.child_safe(n)
        if not watch_only:
            assert password is not None
            data['xprv'] = pw_encode(xprv.to_extended_key_string(), password)
            data['seed'] = pw_encode(text_match, password)
            if passphrase is not None:
                data['passphrase'] = pw_encode(passphrase, password)
        data['derivation'] = derivation_text
        data['xpub'] = xprv.public_key.to_extended_key_string()
    elif text_type == KeystoreTextType.ELECTRUM_SEED_WORDS:
        derivation_type = DerivationType.BIP32
        assert isinstance(text_match, str)
        bip32_seed = Mnemonic.mnemonic_to_seed(text_match, passphrase or '')
        derivation_text = "m"
        xprv = BIP32PrivateKey.from_seed(bip32_seed, Net.COIN)
        for n in bip32_decompose_chain_string(derivation_text):
            xprv = private_key.child_safe(n)
        if not watch_only:
            assert password is not None
            data['xprv'] = pw_encode(xprv.to_extended_key_string(), password)
            data['seed'] = pw_encode(text_match, password)
            if passphrase is not None:
                data['passphrase'] = pw_encode(passphrase, password)
        data['derivation'] = derivation_text
        data['xpub'] = xprv.public_key.to_extended_key_string()
    elif text_type == KeystoreTextType.ELECTRUM_OLD_SEED_WORDS:
        derivation_type = DerivationType.ELECTRUM_OLD
        assert isinstance(text_match, str)
        assert passphrase is None
        # `watch_only` is ignored.
        hex_seed = Old_KeyStore._seed_to_hex(text_match)
        assert password is not None
        data['seed'] = pw_encode(hex_seed, password)
        data['mpk'] = Old_KeyStore._mpk_from_hex_seed(hex_seed)
    else:
        raise NotImplementedError("Unsupported text match type", text_type)

    return instantiate_keystore(derivation_type, data)
Exemplo n.º 21
0
def is_xprv(text: str) -> bool:
    try:
        key = bip32_key_from_string(text)
        return isinstance(key, BIP32PrivateKey)
    except Exception:
        return False
Exemplo n.º 22
0
 def get_master_public_key(self, bip32_path):
     reply = self._get_xpub(bip32_path)
     if reply:
         return bip32_key_from_string(reply['xpub'])
     else:
         raise Exception('no reply')
Exemplo n.º 23
0
 def get_private_key(self, sequence, password):
     xprv = self.get_master_private_key(password)
     privkey = bip32_key_from_string(xprv)
     for n in sequence:
         privkey = privkey.child_safe(n)
     return privkey.to_bytes(), True
Exemplo n.º 24
0
 def _bip32_public_key(self):
     extended_key, path = self.bip32_extended_key_and_path()
     result = bip32_key_from_string(extended_key)
     for n in path:
         result = result.child(n)
     return result
Exemplo n.º 25
0
from typing import Sequence

from bitcoinx import bip32_key_from_string, BIP32PublicKey, PublicKey

from .constants import XPUB_TEST


XPUB_INDEX = 0
XPUB_OBJ = bip32_key_from_string(XPUB_TEST)

def derive_pubkey(xpub: BIP32PublicKey, sequence: Sequence[int]) -> PublicKey:
    pubkey = xpub
    for n in sequence:
        pubkey = pubkey.child_safe(n)
    return pubkey

def get_next_script() -> bytes:
    global XPUB_INDEX
    derivation = (0, XPUB_INDEX)
    XPUB_INDEX += 1

    pubkey = derive_pubkey(XPUB_OBJ, derivation)
    return pubkey.P2PKH_script().to_bytes()