Skip to content

Commit

Permalink
partial impl. of @dipunm's feedback in issue SeedSigner#43
Browse files Browse the repository at this point in the history
* Cannot SeedXOR against a seed's inversion.
* Cannot SeedXOR against a seed w/ passphrase.
  • Loading branch information
Jean Do committed Jan 18, 2023
1 parent c0f64ca commit dd9928a
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 9 deletions.
15 changes: 9 additions & 6 deletions src/seedsigner/models/seed.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,17 @@ def get_xpub(self, wallet_path: str = '/', network: str = SettingsConstants.MAIN
return embit_utils.get_xpub(seed_bytes=self.seed_bytes, derivation_path=wallet_path, embit_network=SettingsConstants.map_network_to_embit(network))

def seed_xor(self, other):
if len(self.mnemonic_list) != len(other.mnemonic_list):
def xor_bytes(a, b):
return bytes(i^j for i, j in zip(a, b))
self_entropy = bip39.mnemonic_to_bytes(self.mnemonic_str)
other_entropy = bip39.mnemonic_to_bytes(other.mnemonic_str)
if len(self_entropy) != len(other_entropy):
raise Exception("XOR requires seeds of similar mnemonic length!")
if self.mnemonic_list == other.mnemonic_list:
if self_entropy == other_entropy:
raise Exception("You may not XOR a seed with itself.")
new_entropy = bytes(i^j for i,j in zip(
bip39.mnemonic_to_bytes(self.mnemonic_str),
bip39.mnemonic_to_bytes(other.mnemonic_str)
))
if self_entropy == xor_bytes(other_entropy, b'\xff'*len(other_entropy)):
raise Exception("You may not XOR a seed with its inversion.")
new_entropy = xor_bytes(self_entropy, other_entropy)
self._mnemonic = bip39.mnemonic_from_bytes(new_entropy).split()
self._generate_seed()

Expand Down
15 changes: 12 additions & 3 deletions src/seedsigner/views/seed_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,10 @@ def run(self):
button_data.append(PASSPHRASE)

if self.settings.get_value(SettingsConstants.SETTING__SEED_XOR) == SettingsConstants.OPTION__ENABLED \
and len([x for x in self.controller.storage.seeds if len(x.mnemonic_list) == len(self.seed.mnemonic_list)]):
and len([x for x in self.controller.storage.seeds # todo: in 3 places, make it just 1
if len(x.mnemonic_list) == len(self.seed.mnemonic_list) \
and x.mnemonic_list != self.seed.mnemonic_list \
and len(x.passphrase) == 0]):
button_data.append(SEED_XOR)

selected_menu_num = seed_screens.SeedFinalizeScreen(
Expand Down Expand Up @@ -309,7 +312,10 @@ def __init__(self):
self.seed = self.controller.storage.get_pending_seed()

def run(self):
seeds = [x for x in self.controller.storage.seeds if len(x.mnemonic_list) == len(self.seed.mnemonic_list)]
seeds = [x for x in self.controller.storage.seeds # todo: in many places, make it just 1
if len(x.mnemonic_list) == len(self.seed.mnemonic_list) \
and x.mnemonic_list != self.seed.mnemonic_list \
and len(x.passphrase) == 0]
title = "Seed XOR"
text = "Select seed to XOR"
button_data = []
Expand Down Expand Up @@ -337,7 +343,10 @@ class SeedXORApplyView(View):
def __init__(self, seed_num: int = None):
super().__init__()
self.seed = self.controller.storage.get_pending_seed()
seeds = [x for x in self.controller.storage.seeds if len(x.mnemonic_list) == len(self.seed.mnemonic_list)]
seeds = [x for x in self.controller.storage.seeds # todo: in many places, make it just 1
if len(x.mnemonic_list) == len(self.seed.mnemonic_list) \
and x.mnemonic_list != self.seed.mnemonic_list \
and len(x.passphrase) == 0]
if seed_num is not None:
self.other = seeds[seed_num]

Expand Down

0 comments on commit dd9928a

Please sign in to comment.