electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 567130f4a37e55769b1b8f8f22348b25affa230b
parent 4bda6f5e61da3df0f2cd678c542fffd49045ee9c
Author: ThomasV <thomasv@electrum.org>
Date:   Thu, 10 Dec 2020 14:43:29 +0100

Merge pull request #6838 from SomberNight/202012_seed_type_old_2fa

mnemonic: tighten seed_type check for old "2fa" type seeds
Diffstat:
Melectrum/mnemonic.py | 8++++++--
Melectrum/plugins/trustedcoin/trustedcoin.py | 27++++++++++++++++-----------
2 files changed, 22 insertions(+), 13 deletions(-)

diff --git a/electrum/mnemonic.py b/electrum/mnemonic.py @@ -241,13 +241,17 @@ def is_old_seed(seed: str) -> bool: def seed_type(x: str) -> str: + num_words = len(x.split()) if is_old_seed(x): return 'old' - elif is_new_seed(x): + elif is_new_seed(x, version.SEED_PREFIX): return 'standard' elif is_new_seed(x, version.SEED_PREFIX_SW): return 'segwit' - elif is_new_seed(x, version.SEED_PREFIX_2FA): + elif is_new_seed(x, version.SEED_PREFIX_2FA) and (num_words == 12 or num_words >= 20): + # Note: in Electrum 2.7, there was a breaking change in key derivation + # for this seed type. Unfortunately the seed version/prefix was reused, + # and now we can only distinguish them based on number of words. :( return '2fa' elif is_new_seed(x, version.SEED_PREFIX_2FA_SW): return '2fa_segwit' diff --git a/electrum/plugins/trustedcoin/trustedcoin.py b/electrum/plugins/trustedcoin/trustedcoin.py @@ -575,20 +575,25 @@ class TrustedCoinPlugin(BasePlugin): 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: + 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('unrecognized seed length: {} words'.format(n)) + raise Exception(f'unexpected seed type: {t}') return xprv1, xpub1, xprv2, xpub2 def create_keystore(self, wizard, seed, passphrase):