seed vault xfp collision
This commit is contained in:
parent
bb6fea731e
commit
c9cf5b7db8
@ -934,7 +934,7 @@ async def restore_main_secret(*a):
|
||||
|
||||
escape = None
|
||||
msg = "Restore main wallet and its settings?\n\n"
|
||||
if not in_seed_vault():
|
||||
if not in_seed_vault(pa.tmp_value):
|
||||
msg += (
|
||||
"Press OK to forget current temporary wallet "
|
||||
"settings, or press (1) to save & keep "
|
||||
|
||||
@ -406,17 +406,13 @@ async def new_from_dice(nwords):
|
||||
# send them to home menu, now with a wallet enabled
|
||||
goto_top_menu(first_time=True)
|
||||
|
||||
def in_seed_vault(xfp=None):
|
||||
def in_seed_vault(encoded):
|
||||
# Test if indicated xfp (or currently active XFP) is in the seed vault already.
|
||||
|
||||
if xfp is None:
|
||||
xfp = xfp2str(settings.get("xfp", 0))
|
||||
|
||||
seeds = settings.master_get("seeds", [])
|
||||
|
||||
if seeds and (xfp in [s[0] for s in seeds]):
|
||||
return True
|
||||
|
||||
if seeds:
|
||||
ss = stash.SecretStash.storage_serialize(encoded)
|
||||
if ss in [s[1] for s in seeds]:
|
||||
return True
|
||||
return False
|
||||
|
||||
async def add_seed_to_vault(encoded, meta=None):
|
||||
@ -433,7 +429,7 @@ async def add_seed_to_vault(encoded, meta=None):
|
||||
new_xfp_str = xfp2str(new_xfp)
|
||||
|
||||
# do not offer to store secrets that are already in vault
|
||||
if in_seed_vault(new_xfp_str):
|
||||
if in_seed_vault(encoded):
|
||||
return
|
||||
|
||||
# do not offer to store main seed
|
||||
@ -796,9 +792,8 @@ class SeedVaultMenu(MenuSystem):
|
||||
dis.fullscreen("Applying...")
|
||||
|
||||
xfp, encoded = item.arg
|
||||
raw = pad_raw_secret(encoded)
|
||||
|
||||
await set_ephemeral_seed(raw, is_restore=True)
|
||||
await set_ephemeral_seed(encoded, is_restore=True)
|
||||
|
||||
goto_top_menu()
|
||||
|
||||
@ -838,7 +833,7 @@ class SeedVaultMenu(MenuSystem):
|
||||
else:
|
||||
# in main settings
|
||||
xs = SettingsObject()
|
||||
xs.set_key(pad_raw_secret(encoded))
|
||||
xs.set_key(encoded)
|
||||
xs.load()
|
||||
xs.blank()
|
||||
del xs
|
||||
@ -866,7 +861,7 @@ class SeedVaultMenu(MenuSystem):
|
||||
xfp_str, encoded, name, meta = item.arg
|
||||
|
||||
# - first byte represents type of secret (internal encoding flag)
|
||||
txt = SecretStash.summary(a2b_hex(encoded[0:2])[0])
|
||||
txt = SecretStash.summary(encoded[0])
|
||||
|
||||
detail = "Name:\n%s\n\nMaster XFP:\n%s\n\nOrigin:\n%s\n\nSecret Type:\n%s" \
|
||||
% (name, xfp_str, meta, txt)
|
||||
@ -923,7 +918,8 @@ class SeedVaultMenu(MenuSystem):
|
||||
rv.append(MenuItem("Temporary Seed", menu=make_ephemeral_seed_menu))
|
||||
else:
|
||||
for i, (xfp_str, encoded, name, meta) in enumerate(seeds):
|
||||
is_active = (cur_xfp == xfp_str)
|
||||
encoded = pad_raw_secret(encoded)
|
||||
is_active = (encoded == pa.tmp_value)
|
||||
submenu = [
|
||||
MenuItem(name, f=cls._detail, arg=(xfp_str, encoded, name, meta)),
|
||||
MenuItem('Use This Seed', f=cls._set, arg=(xfp_str, encoded)),
|
||||
|
||||
@ -2,7 +2,8 @@
|
||||
#
|
||||
# Ephemeral Seeds tests
|
||||
#
|
||||
import pytest, time, re, os, shutil, pdb
|
||||
|
||||
import pytest, time, re, os, shutil, pdb, hashlib
|
||||
from constants import simulator_fixed_tpub, simulator_fixed_words, simulator_fixed_xfp, simulator_fixed_xpub
|
||||
from ckcc.protocol import CCProtocolPacker
|
||||
from txn import fake_txn
|
||||
@ -367,18 +368,19 @@ def import_ephemeral_xprv(microsd_path, virtdisk_path, goto_eph_seed_menu,
|
||||
if extended_key is None:
|
||||
node = BIP32Node.from_master_secret(os.urandom(32), netcode=netcode)
|
||||
ek = node.hwif(as_private=True) + '\n'
|
||||
if way == "sd":
|
||||
fpath = microsd_path(fname)
|
||||
elif way == "vdisk":
|
||||
fpath = virtdisk_path(fname)
|
||||
if way != "nfc":
|
||||
with open(fpath, "w") as f:
|
||||
f.write(ek)
|
||||
else:
|
||||
node = BIP32Node.from_wallet_key(extended_key)
|
||||
assert extended_key == node.hwif(as_private=True)
|
||||
ek = extended_key
|
||||
|
||||
if way == "sd":
|
||||
fpath = microsd_path(fname)
|
||||
elif way == "vdisk":
|
||||
fpath = virtdisk_path(fname)
|
||||
if way != "nfc":
|
||||
with open(fpath, "w") as f:
|
||||
f.write(ek)
|
||||
|
||||
if testnet:
|
||||
assert "tprv" in ek
|
||||
else:
|
||||
@ -1117,4 +1119,49 @@ def test_seed_vault_modifications(settings_set, reset_seed_words, pick_menu_item
|
||||
# still in ephemeral
|
||||
assert title == m[0]
|
||||
|
||||
|
||||
def test_xfp_collision(reset_seed_words, settings_set, import_ephemeral_xprv,
|
||||
cap_story, need_keypress, pick_menu_item, cap_menu):
|
||||
node = BIP32Node.from_master_secret(os.urandom(32), netcode="XTN")
|
||||
xfp = node.fingerprint().hex().upper()
|
||||
k0 = node.hwif(as_private=True)
|
||||
|
||||
# change chain code but presevre public key
|
||||
node._chain_code = hashlib.sha256(node._chain_code).digest()
|
||||
k1 = node.hwif(as_private=True)
|
||||
assert k1 != k0
|
||||
|
||||
reset_seed_words()
|
||||
settings_set("seedvault", 1)
|
||||
settings_set("seeds", [])
|
||||
|
||||
import_ephemeral_xprv("sd", extended_key=k0, seed_vault=True, from_main=True)
|
||||
title, story = cap_story()
|
||||
assert "is in effect now" in story
|
||||
need_keypress("y")
|
||||
|
||||
import_ephemeral_xprv("sd", extended_key=k1, seed_vault=True, from_main=False)
|
||||
title, story = cap_story()
|
||||
assert "is in effect now" in story
|
||||
need_keypress("y")
|
||||
|
||||
pick_menu_item("Seed Vault")
|
||||
m = cap_menu()
|
||||
assert len(m) == 3 # two seeds and Restore Master
|
||||
# same master fingerprints
|
||||
assert xfp in m[0]
|
||||
assert xfp in m[1]
|
||||
# but only second is in use
|
||||
pick_menu_item(m[1])
|
||||
time.sleep(.1)
|
||||
sm = cap_menu()
|
||||
assert "Seed In Use" in sm
|
||||
assert "Use This Seed" not in sm
|
||||
need_keypress("x") # go back
|
||||
pick_menu_item(m[0])
|
||||
time.sleep(.1)
|
||||
sm = cap_menu()
|
||||
assert "Seed In Use" not in sm
|
||||
assert "Use This Seed" in sm
|
||||
|
||||
# EOF
|
||||
|
||||
Loading…
Reference in New Issue
Block a user