def xkeys_from_seed(self, seed, passphrase):
     t = seed_type(seed)
     if not is_any_2fa_seed_type(t):
         raise Exception(f'unexpected seed type: {t}')
     words = seed.split()
     n = len(words)
     if t == '2fa':
         if n >= 20:  # old scheme
             # note: pre-2.7 2fa seeds were typically 24-25 words, however they
             # could probabilistically be arbitrarily shorter due to a bug. (see #3611)
             # the probability of it being < 20 words is about 2^(-(256+12-19*11)) = 2^(-59)
             if passphrase != '':
                 raise Exception('old 2fa seed cannot have passphrase')
             xprv1, xpub1 = self.get_xkeys(' '.join(words[0:12]), t, '',
                                           "m/")
             xprv2, xpub2 = self.get_xkeys(' '.join(words[12:]), t, '',
                                           "m/")
         elif n == 12:  # new scheme
             xprv1, xpub1 = self.get_xkeys(seed, t, passphrase, "m/0'/")
             xprv2, xpub2 = self.get_xkeys(seed, t, passphrase, "m/1'/")
         else:
             raise Exception(
                 f'unrecognized seed length for "2fa" seed: {n}')
     elif t == '2fa_segwit':
         xprv1, xpub1 = self.get_xkeys(seed, t, passphrase, "m/0'/")
         xprv2, xpub2 = self.get_xkeys(seed, t, passphrase, "m/1'/")
     else:
         raise Exception(f'unexpected seed type: {t}')
     return xprv1, xpub1, xprv2, xpub2
Beispiel #2
0
    def verify_seed(self,
                    seed,
                    bip39=False,
                    slip39=False,
                    wallet_type='standard',
                    language='en'):
        self._logger.debug('bip39 ' + str(bip39))
        self._logger.debug('slip39 ' + str(slip39))

        seed_type = ''
        seed_valid = False
        validation_message = ''

        if not (bip39 or slip39):
            seed_type = mnemonic.seed_type(seed)
            if seed_type != '':
                seed_valid = True
        elif bip39:
            is_checksum, is_wordlist = bip39_is_checksum_valid(seed)
            status = ('checksum: ' + ('ok' if is_checksum else 'failed')
                      ) if is_wordlist else 'unknown wordlist'
            validation_message = 'BIP39 (%s)' % status

            if is_checksum:
                seed_type = 'bip39'
                seed_valid = True

        elif slip39:  # TODO: incomplete impl, this code only validates a single share.
            try:
                share = decode_mnemonic(seed)
                seed_type = 'slip39'
                validation_message = 'SLIP39: share #%d in %dof%d scheme' % (
                    share.group_index, share.group_threshold,
                    share.group_count)
            except Slip39Error as e:
                validation_message = 'SLIP39: %s' % str(e)
            seed_valid = False  # for now

        # cosigning seed
        if wallet_type != 'standard' and seed_type not in [
                'standard', 'segwit'
        ]:
            seed_type = ''
            seed_valid = False

        self.seedType = seed_type
        self.seedTypeChanged.emit()

        if self.validationMessage != validation_message:
            self.validationMessage = validation_message
            self.validationMessageChanged.emit()

        if self.seedValid != seed_valid:
            self.seedValid = seed_valid
            self.seedValidChanged.emit()

        self._logger.debug('seed verified: ' + str(seed_valid))
Beispiel #3
0
    def on_edit(self):
        s = ' '.join(self.get_seed_words())
        b = self.is_seed(s)
        if self.seed_type == 'bip39':
            from electrum.keystore import bip39_is_checksum_valid
            is_checksum, is_wordlist = bip39_is_checksum_valid(s)
            status = ('checksum: ' + ('ok' if is_checksum else 'failed')
                      ) if is_wordlist else 'unknown wordlist'
            label = 'BIP39' + ' (%s)' % status
        elif self.seed_type == 'slip39':
            self.slip39_mnemonics[self.slip39_mnemonic_index] = s
            try:
                slip39.decode_mnemonic(s)
            except slip39.Slip39Error as e:
                share_status = str(e)
                current_mnemonic_invalid = True
            else:
                share_status = _('Valid.')
                current_mnemonic_invalid = False

            label = _('SLIP39 share') + ' #%d: %s' % (
                self.slip39_mnemonic_index + 1, share_status)

            # No need to process mnemonics if the current mnemonic remains invalid after editing.
            if not (self.slip39_current_mnemonic_invalid
                    and current_mnemonic_invalid):
                self.slip39_seed, seed_status = slip39.process_mnemonics(
                    self.slip39_mnemonics)
                self.seed_status.setText(seed_status)
            self.slip39_current_mnemonic_invalid = current_mnemonic_invalid

            b = self.slip39_seed is not None
            self.update_share_buttons()
        else:
            t = seed_type(s)
            label = _('Seed Type') + ': ' + t if t else ''
            if t and not b:  # electrum seed, but does not conform to dialog rules
                msg = ' '.join([
                    '<b>' + _('Warning') + ':</b>  ',
                    _("Looks like you have entered a valid seed of type '{}' but this dialog does not support such seeds."
                      ).format(t),
                    _("If unsure, try restoring as '{}'.").format(
                        _("Standard wallet")),
                ])
                self.seed_warning.setText(msg)
            else:
                self.seed_warning.setText("")

        self.seed_type_label.setText(label)
        self.parent.next_button.setEnabled(b)

        # disable suggestions if user already typed an unknown word
        for word in self.get_seed_words()[:-1]:
            if word not in self.wordlist:
                self.seed_e.disable_suggestions()
                return
        self.seed_e.enable_suggestions()
    def on_edit(self, *, from_click=False):
        s = ' '.join(self.get_seed_words())
        b = self.is_seed(s)

        from electrum.keystore import bip39_is_checksum_valid
        from electrum.mnemonic import Wordlist, filenames

        lang = ''
        for type, file in filenames.items():
            word_list = Wordlist.from_file(file)
            is_checksum, is_wordlist = bip39_is_checksum_valid(s, wordlist=word_list)
            if is_wordlist:
                lang = type
                break

        if self.seed_type == 'bip39':
            status = ('checksum: ' + ('ok' if is_checksum else 'failed')) if is_wordlist else 'unknown wordlist'
            label = 'BIP39 - ' + lang + ' (%s)'%status
            if lang and lang != self.lang:
                if lang == 'en':
                    bip39_english_list = Mnemonic('en').wordlist
                    old_list = old_mnemonic.wordlist
                    only_old_list = set(old_list) - set(bip39_english_list)
                    self.wordlist = list(bip39_english_list) + list(only_old_list)  # concat both lists
                    self.wordlist.sort()
                    self.completer.model().setStringList(self.wordlist)
                    self.lang = 'en'
                else:
                    self.wordlist = list(Mnemonic(lang).wordlist)
                    self.wordlist.sort()
                    self.completer.model().setStringList(self.wordlist)
                    self.lang = lang
            b = is_checksum
        else:
            t = seed_type(s)
            label = _('Seed Type') + ': ' + t if t else ''

            if is_checksum and is_wordlist and not from_click:
                # This is a valid bip39 and this method was called from typing
                # Emulate selecting the bip39 option
                self.clayout.group.buttons()[1].click()
                return

        self.seed_type_label.setText(label)
        self.parent.next_button.setEnabled(b)

        # disable suggestions if user already typed an unknown word
        for word in self.get_seed_words()[:-1]:
            if word not in self.wordlist:
                self.seed_e.disable_suggestions()
                return
        self.seed_e.enable_suggestions()
Beispiel #5
0
 def on_edit(self):
     s = self.get_seed()
     b = self.is_seed(s)
     if not self.is_bip39:
         t = seed_type(s)
         label = _('Seed Type') + ': ' + t if t else ''
     else:
         from electrum.keystore import bip39_is_checksum_valid
         is_checksum, is_wordlist = bip39_is_checksum_valid(s)
         status = ('checksum: ' + ('ok' if is_checksum else 'failed')) if is_wordlist else 'unknown wordlist'
         label = 'BIP39' + ' (%s)'%status
     self.seed_type_label.setText(label)
     self.parent.next_button.setEnabled(b)
Beispiel #6
0
    def on_edit(self):
        s = self.get_seed()
        if self.is_bip39 or self.is_gold_wallet_import:
            b = bip39_is_checksum_valid(s)[0]
        else:
            b = bool(seed_type(s))
        self.parent.next_button.setEnabled(b)

        # disable suggestions if user already typed an unknown word
        for word in self.get_seed().split(" ")[:-1]:
            if word not in self.wordlist:
                self.seed_e.disable_suggestions()
                return
        self.seed_e.enable_suggestions()
Beispiel #7
0
    def on_edit(self):
        s = ' '.join(self.get_seed_words())
        b = self.is_seed(s)
        if self.seed_type == 'bip39':
            from electrum.keystore import bip39_is_checksum_valid
            is_checksum, is_wordlist = bip39_is_checksum_valid(s)
            status = ('checksum: ' + ('ok' if is_checksum else 'failed')
                      ) if is_wordlist else 'unknown wordlist'
            label = 'BIP39' + ' (%s)' % status
        elif self.seed_type == 'slip39':
            self.slip39_mnemonics[self.slip39_mnemonic_index] = s
            try:
                slip39.decode_mnemonic(s)
            except slip39.Slip39Error as e:
                share_status = str(e)
                current_mnemonic_invalid = True
            else:
                share_status = _('Valid.')
                current_mnemonic_invalid = False

            label = _('SLIP39 share') + ' #%d: %s' % (
                self.slip39_mnemonic_index + 1, share_status)

            # No need to process mnemonics if the current mnemonic remains invalid after editing.
            if not (self.slip39_current_mnemonic_invalid
                    and current_mnemonic_invalid):
                self.slip39_seed, seed_status = slip39.process_mnemonics(
                    self.slip39_mnemonics)
                self.seed_status.setText(seed_status)
            self.slip39_current_mnemonic_invalid = current_mnemonic_invalid

            b = self.slip39_seed is not None
            self.update_share_buttons()
        else:
            t = seed_type(s)
            label = _('Seed Type') + ': ' + t if t else ''

        self.seed_type_label.setText(label)
        self.parent.next_button.setEnabled(b)

        # disable suggestions if user already typed an unknown word
        for word in self.get_seed_words()[:-1]:
            if word not in self.wordlist:
                self.seed_e.disable_suggestions()
                return
        self.seed_e.enable_suggestions()
Beispiel #8
0
    def on_edit(self):
        s = self.get_seed()
        b = self.is_seed(s)
        if not self.is_bip39:
            t = seed_type(s)
            label = _('Seed Type') + ': ' + t if t else ''
        else:
            from electrum.keystore import bip39_is_checksum_valid
            is_checksum, is_wordlist = bip39_is_checksum_valid(s)
            status = ('checksum: ' + ('ok' if is_checksum else 'failed')) if is_wordlist else 'unknown wordlist'
            label = 'BIP39' + ' (%s)'%status
        self.seed_type_label.setText(label)
        self.parent.next_button.setEnabled(b)

        # to account for bip39 seeds
        for word in self.get_seed().split(" ")[:-1]:
            if word not in self.wordlist:
                self.seed_e.disable_suggestions()
                return
        self.seed_e.enable_suggestions()
def from_seed(seed, passphrase, is_p2sh=False):
    t = seed_type(seed)
    if t == 'old':
        keystore = Old_KeyStore({})
        keystore.add_seed(seed)
    elif t in ['standard', 'segwit']:
        keystore = BIP32_KeyStore({})
        keystore.add_seed(seed)
        keystore.passphrase = passphrase
        bip32_seed = Mnemonic.mnemonic_to_seed(seed, passphrase)
        if t == 'standard':
            der = "m/"
            xtype = 'standard'
        else:
            der = "m/1'/" if is_p2sh else "m/0'/"
            xtype = 'p2wsh' if is_p2sh else 'p2wpkh'
        keystore.add_xprv_from_seed(bip32_seed, xtype, der)
    else:
        raise BitcoinException('Unexpected seed type {}'.format(repr(t)))
    return keystore
Beispiel #10
0
    def on_edit(self):
        s = self.get_seed()
        b = bip39_is_checksum_valid(s)[0]
        if not self.is_bip39:
            t = seed_type(s)
            label = _('Seed Type') + ': ' + t if t else ''
        else:
            is_checksum, is_wordlist = bip39_is_checksum_valid(s)
            status = ('checksum: ' + ('ok' if is_checksum else 'failed')
                      ) if is_wordlist else 'unknown wordlist'
            label = 'BIP39' + ' (%s)' % status
        self.seed_type_label.setText(label)
        self.parent.next_button.setEnabled(b)

        # disable suggestions if user already typed an unknown word
        for word in self.get_seed().split(" ")[:-1]:
            if word not in self.wordlist:
                self.seed_e.disable_suggestions()
                return
        self.seed_e.enable_suggestions()
    def on_edit(self):
        s = self.get_seed()
        b = self.is_seed(s)
        if not self.is_bip39:
            t = seed_type(s)
            label = _('Seed Type') + ': ' + t if t else ''
        else:
            from electrum.keystore import bip39_is_checksum_valid
            is_checksum, is_wordlist = bip39_is_checksum_valid(s)
            status = ('checksum: ' + ('ok' if is_checksum else 'failed')) if is_wordlist else 'unknown wordlist'
            label = 'BIP39' + ' (%s)'%status
        self.seed_type_label.setText(label)
        self.parent.next_button.setEnabled(b)

        # to account for bip39 seeds
        for word in self.get_seed().split(" ")[:-1]:
            if word not in self.wordlist:
                self.seed_e.disable_suggestions()
                return
        self.seed_e.enable_suggestions()
Beispiel #12
0
 def xkeys_from_seed(self, seed, passphrase):
     t = seed_type(seed)
     if not is_any_2fa_seed_type(t):
         raise Exception(f'unexpected seed type: {t}')
     words = seed.split()
     n = len(words)
     # old version use long seed phrases
     if n >= 20:
         # note: pre-2.7 2fa seeds were typically 24-25 words, however they
         # could probabilistically be arbitrarily shorter due to a bug. (see #3611)
         # the probability of it being < 20 words is about 2^(-(256+12-19*11)) = 2^(-59)
         if passphrase != '':
             raise Exception('old 2fa seed cannot have passphrase')
         xprv1, xpub1 = self.get_xkeys(' '.join(words[0:12]), t, '', "m/")
         xprv2, xpub2 = self.get_xkeys(' '.join(words[12:]), t, '', "m/")
     elif not t == '2fa' or n == 12:
         xprv1, xpub1 = self.get_xkeys(seed, t, passphrase, "m/0'/")
         xprv2, xpub2 = self.get_xkeys(seed, t, passphrase, "m/1'/")
     else:
         raise Exception('unrecognized seed length: {} words'.format(n))
     return xprv1, xpub1, xprv2, xpub2
Beispiel #13
0
 def is_valid_seed(seed):
     t = seed_type(seed)
     return is_any_2fa_seed_type(t)
Beispiel #14
0
 def test_seed_type(self):
     for idx, (seed_words, _type) in enumerate(self.mnemonics):
         with self.subTest(msg=f"seed_type_subcase_{idx}",
                           seed_words=seed_words):
             self.assertEqual(_type, seed_type(seed_words), msg=seed_words)
Beispiel #15
0
 def test_seed_type(self):
     for seed_words, _type in self.mnemonics:
         self.assertEqual(_type, seed_type(seed_words), msg=seed_words)
    def on_edit(self):
        s = ' '.join(self.get_seed_words())
        b = self.is_seed(s)
        if self.seed_type == 'bip39':
            from electrum.keystore import bip39_is_checksum_valid
            from electrum.mnemonic import Wordlist, filenames

            lang = ''
            for type, file in filenames.items():
                word_list = Wordlist.from_file(file)
                is_checksum, is_wordlist = bip39_is_checksum_valid(s, wordlist=word_list)
                if is_wordlist:
                    lang = type
                    break

            status = ('checksum: ' + ('ok' if is_checksum else 'failed')) if is_wordlist else 'unknown wordlist'
            label = 'BIP39 - ' + lang + ' (%s)'%status
            if lang and lang != self.lang:
                if lang == 'en':
                    bip39_english_list = Mnemonic('en').wordlist
                    old_list = old_mnemonic.wordlist
                    only_old_list = set(old_list) - set(bip39_english_list)
                    self.wordlist = list(bip39_english_list) + list(only_old_list)  # concat both lists
                    self.wordlist.sort()
                    self.completer.model().setStringList(self.wordlist)
                    self.lang = 'en'
                else:
                    self.wordlist = list(Mnemonic(lang).wordlist)
                    self.wordlist.sort()
                    self.completer.model().setStringList(self.wordlist)
                    self.lang = lang

        elif self.seed_type == 'slip39':
            self.slip39_mnemonics[self.slip39_mnemonic_index] = s
            try:
                slip39.decode_mnemonic(s)
            except slip39.Slip39Error as e:
                share_status = str(e)
                current_mnemonic_invalid = True
            else:
                share_status = _('Valid.')
                current_mnemonic_invalid = False

            label = _('SLIP39 share') + ' #%d: %s' % (self.slip39_mnemonic_index + 1, share_status)

            # No need to process mnemonics if the current mnemonic remains invalid after editing.
            if not (self.slip39_current_mnemonic_invalid and current_mnemonic_invalid):
                self.slip39_seed, seed_status = slip39.process_mnemonics(self.slip39_mnemonics)
                self.seed_status.setText(seed_status)
            self.slip39_current_mnemonic_invalid = current_mnemonic_invalid

            b = self.slip39_seed is not None
            self.update_share_buttons()
        else:
            t = seed_type(s)
            label = _('Seed Type') + ': ' + t if t else ''

        self.seed_type_label.setText(label)
        self.parent.next_button.setEnabled(b)

        # disable suggestions if user already typed an unknown word
        for word in self.get_seed_words()[:-1]:
            if word not in self.wordlist:
                self.seed_e.disable_suggestions()
                return
        self.seed_e.enable_suggestions()
Beispiel #17
0
 def test_seed_type(self):
     for seed_words, _type in self.mnemonics:
         self.assertEqual(_type, seed_type(seed_words), msg=seed_words)
Beispiel #18
0
 def is_valid_seed(seed):
     t = seed_type(seed)
     return is_any_2fa_seed_type(t)