Esempio n. 1
0
    def __init__(self, *, config: 'SimpleConfig', daemon: 'Daemon',
                 plugins: 'Plugins'):
        BaseElectrumGui.__init__(self,
                                 config=config,
                                 daemon=daemon,
                                 plugins=plugins)
        self.network = daemon.network
        storage = WalletStorage(config.get_wallet_path())
        if not storage.file_exists():
            print("Wallet not found. try 'electrum create'")
            exit()
        if storage.is_encrypted():
            password = getpass.getpass('Password:'******'')
        self.encoding = locale.getpreferredencoding()

        self.stdscr = curses.initscr()
        curses.noecho()
        curses.cbreak()
        curses.start_color()
        curses.use_default_colors()
        curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE)
        curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_CYAN)
        curses.init_pair(3, curses.COLOR_BLACK, curses.COLOR_WHITE)
        self.stdscr.keypad(1)
        self.stdscr.border(0)
        self.maxy, self.maxx = self.stdscr.getmaxyx()
        self.set_cursor(0)
        self.w = curses.newwin(10, 50, 5, 5)

        self.tab = 0
        self.pos = 0
        self.popup_pos = 0

        self.str_recipient = ""
        self.str_description = ""
        self.str_amount = ""
        self.str_fee = ""
        self.history = None
        self.txid = []

        self.register_callbacks()

        self.tab_names = [
            _("History"),
            _("Send"),
            _("Receive"),
            _("Addresses"),
            _("Contacts"),
            _("Banner")
        ]
        self.num_tabs = len(self.tab_names)
    def test_read_dictionary_from_file(self):

        some_dict = {"a": "b", "c": "d"}
        contents = json.dumps(some_dict)
        with open(self.wallet_path, "w") as f:
            contents = f.write(contents)

        storage = WalletStorage(self.wallet_path)
        db = WalletDB(storage.read(), manual_upgrades=True)
        self.assertEqual("b", db.get("a"))
        self.assertEqual("d", db.get("c"))
Esempio n. 3
0
    def run_upgrades(self, storage: WalletStorage, db: 'WalletDB') -> None:
        path = storage.path
        if db.requires_split():
            self.hide()
            msg = _(
                "The wallet '{}' contains multiple accounts, which are no longer supported since Electrum-NMC 2.7.\n\n"
                "Do you want to split your wallet into multiple files?"
            ).format(path)
            if not self.question(msg):
                return
            file_list = db.split_accounts(path)
            msg = _('Your accounts have been moved to') + ':\n' + '\n'.join(
                file_list) + '\n\n' + _(
                    'Do you want to delete the old file') + ':\n' + path
            if self.question(msg):
                os.remove(path)
                self.show_warning(_('The file was removed'))
            # raise now, to avoid having the old storage opened
            raise UserCancelled()

        action = db.get_action()
        if action and db.requires_upgrade():
            raise WalletFileException(
                'Incomplete wallet files cannot be upgraded.')
        if action:
            self.hide()
            msg = _("The file '{}' contains an incompletely created wallet.\n"
                    "Do you want to complete its creation now?").format(path)
            if not self.question(msg):
                if self.question(
                        _("Do you want to delete '{}'?").format(path)):
                    os.remove(path)
                    self.show_warning(_('The file was removed'))
                return
            self.show()
            self.data = json.loads(storage.read())
            self.run(action)
            for k, v in self.data.items():
                db.put(k, v)
            db.write(storage)
            return

        if db.requires_upgrade():
            self.upgrade_db(storage, db)
Esempio n. 4
0
    def test_update_password_with_app_restarts(self):
        wallet_str = '{"addr_history":{"1364Js2VG66BwRdkaoxAaFtdPb1eQgn8Dr":[],"15CyDgLffJsJgQrhcyooFH4gnVDG82pUrA":[],"1Exet2BhHsFxKTwhnfdsBMkPYLGvobxuW6":[]},"addresses":{"change":[],"receiving":["1364Js2VG66BwRdkaoxAaFtdPb1eQgn8Dr","1Exet2BhHsFxKTwhnfdsBMkPYLGvobxuW6","15CyDgLffJsJgQrhcyooFH4gnVDG82pUrA"]},"keystore":{"keypairs":{"0344b1588589958b0bcab03435061539e9bcf54677c104904044e4f8901f4ebdf5":"L2sED74axVXC4H8szBJ4rQJrkfem7UMc6usLCPUoEWxDCFGUaGUM","0389508c13999d08ffae0f434a085f4185922d64765c0bff2f66e36ad7f745cc5f":"L3Gi6EQLvYw8gEEUckmqawkevfj9s8hxoQDFveQJGZHTfyWnbk1U","04575f52b82f159fa649d2a4c353eb7435f30206f0a6cb9674fbd659f45082c37d559ffd19bea9c0d3b7dcc07a7b79f4cffb76026d5d4dff35341efe99056e22d2":"5JyVyXU1LiRXATvRTQvR9Kp8Rx1X84j2x49iGkjSsXipydtByUq"},"type":"imported"},"pruned_txo":{},"seed_version":13,"stored_height":-1,"transactions":{},"tx_fees":{},"txi":{},"txo":{},"use_encryption":false,"verified_tx3":{},"wallet_type":"standard","winpos-qt":[100,100,840,405]}'
        db = WalletDB(wallet_str, manual_upgrades=False)
        storage = WalletStorage(self.wallet_path)
        wallet = Wallet(db, storage, config=self.config)
        wallet.stop()

        storage = WalletStorage(self.wallet_path)
        # if storage.is_encrypted():
        #     storage.decrypt(password)
        db = WalletDB(storage.read(), manual_upgrades=False)
        wallet = Wallet(db, storage, config=self.config)

        wallet.check_password(None)

        wallet.update_password(None, "1234")
        with self.assertRaises(InvalidPassword):
            wallet.check_password(None)
        with self.assertRaises(InvalidPassword):
            wallet.check_password("wrong password")
        wallet.check_password("1234")
Esempio n. 5
0
                print(
                    f"> tested {num_tested} passwords so far... most recently tried: {password!r}"
                )


if __name__ == '__main__':
    if len(sys.argv) < 2:
        print("ERROR. usage: bruteforce_pw.py <path_to_wallet_file>")
        sys.exit(1)
    path = sys.argv[1]

    config = SimpleConfig()
    storage = WalletStorage(path)
    if not storage.file_exists():
        print(f"ERROR. wallet file not found at path: {path}")
        sys.exit(1)
    if storage.is_encrypted():
        test_password = partial(test_password_for_storage_encryption, storage)
        print(f"wallet found: with storage encryption.")
    else:
        db = WalletDB(storage.read(), manual_upgrades=True)
        wallet = Wallet(db, storage, config=config)
        if not wallet.has_password():
            print("wallet found but it is not encrypted.")
            sys.exit(0)
        test_password = partial(test_password_for_keystore_encryption, wallet)
        print(f"wallet found: with keystore encryption.")
    password = bruteforce_loop(test_password)
    print(f"====================")
    print(f"password found: {password}")
Esempio n. 6
0
class QEWalletDB(QObject):
    def __init__(self, parent=None):
        super().__init__(parent)

        from .qeapp import ElectrumQmlApplication
        self.daemon = ElectrumQmlApplication._daemon

        self.reset()

    _logger = get_logger(__name__)

    fileNotFound = pyqtSignal()
    pathChanged = pyqtSignal([bool], arguments=["ready"])
    needsPasswordChanged = pyqtSignal()
    needsHWDeviceChanged = pyqtSignal()
    passwordChanged = pyqtSignal()
    validPasswordChanged = pyqtSignal()
    requiresSplitChanged = pyqtSignal()
    splitFinished = pyqtSignal()
    readyChanged = pyqtSignal()
    createError = pyqtSignal([str], arguments=["error"])
    createSuccess = pyqtSignal()
    invalidPassword = pyqtSignal()

    def reset(self):
        self._path = None
        self._needsPassword = False
        self._needsHWDevice = False
        self._password = ''
        self._requiresSplit = False
        self._validPassword = True

        self._storage = None
        self._db = None

        self._ready = False

    @pyqtProperty('QString', notify=pathChanged)
    def path(self):
        return self._path

    @path.setter
    def path(self, wallet_path):
        if wallet_path == self._path:
            return

        self._logger.info('setting path: ' + wallet_path)
        self.reset()
        self._path = wallet_path

        self.pathChanged.emit(self._ready)

    @pyqtProperty(bool, notify=needsPasswordChanged)
    def needsPassword(self):
        return self._needsPassword

    @needsPassword.setter
    def needsPassword(self, wallet_needs_password):
        if wallet_needs_password == self._needsPassword:
            return

        self._needsPassword = wallet_needs_password
        self.needsPasswordChanged.emit()

    @pyqtProperty(bool, notify=needsHWDeviceChanged)
    def needsHWDevice(self):
        return self._needsHWDevice

    @needsHWDevice.setter
    def needsHWDevice(self, wallet_needs_hw_device):
        if wallet_needs_hw_device == self._needsHWDevice:
            return

        self._needsHWDevice = wallet_needs_hw_device
        self.needsHWDeviceChanged.emit()

    @pyqtProperty('QString', notify=passwordChanged)
    def password(self):
        return ''  # no read access

    @password.setter
    def password(self, wallet_password):
        if wallet_password == self._password:
            return

        self._password = wallet_password
        self.passwordChanged.emit()

    @pyqtProperty(bool, notify=requiresSplitChanged)
    def requiresSplit(self):
        return self._requiresSplit

    @pyqtProperty(bool, notify=validPasswordChanged)
    def validPassword(self):
        return self._validPassword

    @validPassword.setter
    def validPassword(self, validPassword):
        if self._validPassword != validPassword:
            self._validPassword = validPassword
            self.validPasswordChanged.emit()

    @pyqtProperty(bool, notify=readyChanged)
    def ready(self):
        return self._ready

    @pyqtSlot()
    def verify(self):
        self.load_storage()
        if self._storage:
            self.load_db()

    @pyqtSlot()
    def doSplit(self):
        self._logger.warning('doSplit')
        if not self._requiresSplit:
            return

        self._db.split_accounts(self._path)

        self.splitFinished.emit()

    def load_storage(self):
        self._storage = WalletStorage(self._path)
        if not self._storage.file_exists():
            self._logger.warning('file does not exist')
            self.fileNotFound.emit()
            self._storage = None
            return

        if self._storage.is_encrypted():
            self.needsPassword = True

            try:
                self._storage.decrypt(
                    '' if not self._password else self._password)
                self.validPassword = True
            except InvalidPassword as e:
                self.validPassword = False
                self.invalidPassword.emit()

        if not self._storage.is_past_initial_decryption():
            self._storage = None

    def load_db(self):
        # needs storage accessible
        self._db = WalletDB(self._storage.read(), manual_upgrades=True)
        if self._db.requires_split():
            self._logger.warning('wallet requires split')
            self._requiresSplit = True
            self.requiresSplitChanged.emit()
            return
        if self._db.get_action():
            self._logger.warning(
                'action pending. QML version doesn\'t support continuation of wizard'
            )
            return

        if self._db.requires_upgrade():
            self._logger.warning('wallet requires upgrade, upgrading')
            self._db.upgrade()
            self._db.write(self._storage)

        self._ready = True
        self.readyChanged.emit()

    @pyqtSlot('QJSValue', bool, str)
    def create_storage(self, js_data, single_password_enabled,
                       single_password):
        self._logger.info('Creating wallet from wizard data')
        data = js_data.toVariant()
        self._logger.debug(str(data))

        if single_password_enabled and single_password:
            data['encrypt'] = True
            data['password'] = single_password

        try:
            path = os.path.join(
                os.path.dirname(self.daemon.config.get_wallet_path()),
                data['wallet_name'])
            if os.path.exists(path):
                raise Exception('file already exists at path')
            storage = WalletStorage(path)

            if data['seed_type'] in ['old', 'standard',
                                     'segwit']:  #2fa, 2fa-segwit
                self._logger.debug('creating keystore from electrum seed')
                k = keystore.from_seed(data['seed'], data['seed_extra_words'],
                                       data['wallet_type'] == 'multisig')
            elif data['seed_type'] == 'bip39':
                self._logger.debug('creating keystore from bip39 seed')
                root_seed = keystore.bip39_to_seed(data['seed'],
                                                   data['seed_extra_words'])
                derivation = normalize_bip32_derivation(
                    data['derivation_path'])
                script = data['script_type'] if data[
                    'script_type'] != 'p2pkh' else 'standard'
                k = keystore.from_bip43_rootseed(root_seed,
                                                 derivation,
                                                 xtype=script)
            else:
                raise Exception('unsupported/unknown seed_type %s' %
                                data['seed_type'])

            if data['encrypt']:
                if k.may_have_password():
                    k.update_password(None, data['password'])
                storage.set_password(
                    data['password'],
                    enc_version=StorageEncryptionVersion.USER_PASSWORD)

            db = WalletDB('', manual_upgrades=False)
            db.set_keystore_encryption(
                bool(data['password']) and data['encrypt'])

            db.put('wallet_type', data['wallet_type'])
            db.put('seed_type', data['seed_type'])
            db.put('keystore', k.dump())
            if k.can_have_deterministic_lightning_xprv():
                db.put(
                    'lightning_xprv',
                    k.get_lightning_xprv(
                        data['password'] if data['encrypt'] else None))

            db.load_plugins()
            db.write(storage)

            # minimally populate self after create
            self._password = data['password']
            self.path = path

            self.createSuccess.emit()
        except Exception as e:
            self._logger.error(str(e))
            self.createError.emit(str(e))