645 lines
22 KiB
Python
645 lines
22 KiB
Python
# (c) Copyright 2023 by Coinkite Inc. This file is covered by license found in COPYING-CC.
|
|
#
|
|
# Testing backups.
|
|
#
|
|
import pytest, time, json, os, shutil, re
|
|
from constants import simulator_fixed_words, simulator_fixed_tprv
|
|
from charcodes import KEY_QR
|
|
from bip32 import BIP32Node
|
|
from mnemonic import Mnemonic
|
|
|
|
|
|
@pytest.fixture
|
|
def override_bkpw(goto_home, pick_menu_item, cap_story, need_keypress, seed_story_to_words,
|
|
cap_menu, press_select, press_cancel, enter_complex, is_q1):
|
|
|
|
def purge_current(exit=False):
|
|
time.sleep(.1)
|
|
title, story = cap_story()
|
|
if "(1) to forget current" in story:
|
|
need_keypress("1")
|
|
time.sleep(.1)
|
|
title, story = cap_story()
|
|
assert "Delete current stored password?" in story
|
|
press_select()
|
|
time.sleep(.1)
|
|
title, story = cap_story()
|
|
assert "(1) to forget current" not in story
|
|
if exit:
|
|
press_cancel()
|
|
|
|
def doit(password=None, old_password=None):
|
|
goto_home()
|
|
pick_menu_item("Advanced/Tools")
|
|
pick_menu_item("Danger Zone")
|
|
pick_menu_item("I Am Developer.")
|
|
pick_menu_item("BKPW Override")
|
|
time.sleep(.1)
|
|
title, story = cap_story()
|
|
current_bkpw = None
|
|
if "(2) to show current active backup password" in story:
|
|
need_keypress("2")
|
|
time.sleep(.1)
|
|
title, story = cap_story()
|
|
assert 'Anyone with knowledge of the password will be able to decrypt your backups.' in story
|
|
press_select()
|
|
time.sleep(.1)
|
|
title, current_bkpw = cap_story()
|
|
current_bkpw = current_bkpw.strip()
|
|
press_select()
|
|
|
|
if old_password:
|
|
assert current_bkpw == old_password, "old_password mismatch"
|
|
|
|
if password is None:
|
|
# purge current bkpw
|
|
purge_current(exit=True)
|
|
return
|
|
|
|
# purge what was there from before
|
|
purge_current()
|
|
|
|
need_keypress("0")
|
|
enter_complex(password, apply=False, b39pass=False)
|
|
|
|
time.sleep(.1)
|
|
title, story = cap_story()
|
|
assert "(2) to show current active backup password" in story
|
|
need_keypress("2")
|
|
press_select() # are you sure?
|
|
time.sleep(.1)
|
|
title, story = cap_story()
|
|
new_current_bkpw = story.strip()
|
|
press_select()
|
|
|
|
time.sleep(.1)
|
|
title, story = cap_story()
|
|
if ((3*" ") in password) and not is_q1:
|
|
assert password.replace(" ", " ") == new_current_bkpw
|
|
else:
|
|
assert new_current_bkpw == password
|
|
|
|
assert "(1) to forget current password" in story
|
|
assert "(0) to change" in story
|
|
|
|
return doit
|
|
|
|
@pytest.fixture
|
|
def backup_system(settings_set, settings_remove, goto_home, pick_menu_item,
|
|
cap_story, need_keypress, cap_screen_qr, pass_word_quiz,
|
|
get_setting, seed_story_to_words, press_cancel, is_q1,
|
|
press_select, is_headless):
|
|
def doit(reuse_pw=None, save_pw=False, st=None, ct=False):
|
|
# st -> seed type
|
|
# ct -> cleartext backup
|
|
if reuse_pw:
|
|
if isinstance(reuse_pw, list):
|
|
assert len(reuse_pw) == 12
|
|
else:
|
|
assert reuse_pw is True # default
|
|
reuse_pw = ['zoo' for _ in range(12)]
|
|
|
|
settings_set('bkpw', ' '.join(reuse_pw))
|
|
else:
|
|
settings_remove('bkpw')
|
|
|
|
goto_home()
|
|
pick_menu_item('Advanced/Tools')
|
|
pick_menu_item('Backup')
|
|
pick_menu_item('Backup System')
|
|
|
|
title, body = cap_story()
|
|
if st:
|
|
if st == "b39pass":
|
|
assert "BIP39 passphrase is in effect" in body
|
|
assert "ignores passphrases and produces backup of main seed" in body
|
|
assert "(2) to back-up BIP39 passphrase wallet" in body
|
|
if st == "eph":
|
|
assert "A temporary seed is in effect" in body
|
|
assert "so backup will be of that seed" in body
|
|
|
|
press_select()
|
|
time.sleep(.1)
|
|
title, body = cap_story()
|
|
|
|
if ct:
|
|
# cleartext backup
|
|
if ' 1: zoo' in body:
|
|
press_cancel()
|
|
|
|
need_keypress("6")
|
|
time.sleep(.1)
|
|
_, story = cap_story()
|
|
assert "Are you SURE ?!?" in story
|
|
assert "**NOT** be encrypted" in story
|
|
press_select()
|
|
return # nothing more to be done
|
|
|
|
if reuse_pw:
|
|
assert (' 1: %s' % reuse_pw[0]) in body
|
|
assert ('12: %s' % reuse_pw[-1]) in body
|
|
press_select()
|
|
words = ['zoo'] * 12
|
|
else:
|
|
assert title == 'NO-TITLE'
|
|
assert 'Record this (12 word)' in body
|
|
assert 'password:' in body
|
|
|
|
words = seed_story_to_words(body)
|
|
|
|
assert len(words) == 12
|
|
|
|
print("Passphrase: %s" % ' '.join(words))
|
|
|
|
if 'QR Code' in body and not is_headless:
|
|
need_keypress(KEY_QR if is_q1 else '1')
|
|
got_qr = cap_screen_qr().decode('ascii').lower().split()
|
|
assert [w[0:4] for w in words] == got_qr
|
|
press_select()
|
|
|
|
# pass the quiz!
|
|
count, title, body = pass_word_quiz(words)
|
|
assert count >= 4
|
|
assert "same words next time" in body
|
|
assert "Press (1) to save" in body
|
|
if save_pw:
|
|
need_keypress('1')
|
|
time.sleep(.1)
|
|
|
|
assert get_setting('bkpw') == ' '.join(words)
|
|
else:
|
|
press_cancel()
|
|
time.sleep(.01)
|
|
assert get_setting('bkpw', 'xxx') == 'xxx'
|
|
|
|
return words
|
|
|
|
return doit
|
|
|
|
@pytest.fixture
|
|
def make_big_notes(settings_set, sim_exec):
|
|
def doit(count=9):
|
|
print(">>> Making huge backup file")
|
|
|
|
# - to bypass USB msg limit, append as we go
|
|
notes = []
|
|
settings_set('notes', [])
|
|
for n in range(count):
|
|
v = { fld:('a'*30) if fld != 'misc' else 'b'*1800
|
|
for fld in ['user', 'password', 'site', 'misc'] }
|
|
v['title'] = f'Note {n+1}'
|
|
notes.append(v)
|
|
rv = sim_exec(cmd := f'settings.current["notes"].append({v!r})')
|
|
assert 'error' not in rv.lower()
|
|
|
|
rv = sim_exec('settings.changed()')
|
|
assert 'error' not in rv.lower()
|
|
|
|
assert len(notes) == count
|
|
|
|
return notes
|
|
|
|
return doit
|
|
|
|
|
|
@pytest.mark.qrcode
|
|
@pytest.mark.parametrize('multisig', [False, 'multisig'])
|
|
@pytest.mark.parametrize('st', ["b39pass", "eph", None])
|
|
@pytest.mark.parametrize('reuse_pw', [True, False])
|
|
@pytest.mark.parametrize('save_pw', [False, True])
|
|
@pytest.mark.parametrize('seedvault', [False, True])
|
|
@pytest.mark.parametrize('pass_way', ["qr", None])
|
|
def test_make_backup(multisig, goto_home, pick_menu_item, cap_story, need_keypress, st,
|
|
open_microsd, microsd_path, unit_test, cap_menu, word_menu_entry,
|
|
pass_word_quiz, reset_seed_words, import_ms_wallet, get_setting,
|
|
reuse_pw, save_pw, settings_set, settings_remove, press_select,
|
|
generate_ephemeral_words, set_bip39_pw, verify_backup_file,
|
|
check_and_decrypt_backup, restore_backup_cs, clear_ms, seedvault,
|
|
restore_main_seed, import_ephemeral_xprv, backup_system,
|
|
press_cancel, sim_exec, pass_way, garbage_collector, make_big_notes):
|
|
# Make an encrypted 7z backup, verify it, and even restore it!
|
|
clear_ms()
|
|
reset_seed_words()
|
|
settings_set("seedvault", int(seedvault))
|
|
settings_set("seeds", [] if seedvault else None)
|
|
|
|
# test larger backup files > 10,000 bytes
|
|
if multisig == False and st == None and not reuse_pw and not save_pw and not seedvault:
|
|
# pick just one test case.
|
|
notes = make_big_notes()
|
|
else:
|
|
notes = None
|
|
|
|
# need to make multisig in my main wallet
|
|
if multisig and st != "eph":
|
|
import_ms_wallet(15, 15)
|
|
press_select()
|
|
time.sleep(.1)
|
|
assert len(get_setting('multisig')) == 1
|
|
|
|
if not reuse_pw:
|
|
# drop saved bkpw before we get to ephemeral settings
|
|
settings_remove("bkpw")
|
|
|
|
if st == "b39pass":
|
|
xfp_pass = set_bip39_pw("coinkite", reset=False, seed_vault=seedvault)
|
|
assert not get_setting('multisig', None)
|
|
elif st == "eph":
|
|
eph_seed = generate_ephemeral_words(num_words=24, dice=False, from_main=True,
|
|
seed_vault=seedvault)
|
|
if multisig:
|
|
# make multisig in ephemeral wallet
|
|
import_ms_wallet(15, 15, dev_key=True, common="605'/0'/0'")
|
|
press_select()
|
|
time.sleep(.1)
|
|
assert len(get_setting('multisig')) == 1
|
|
else:
|
|
# create ephemeral seed - add to seed vault if necessary
|
|
# and restore master (just so we have something in setting.seeds)
|
|
node = import_ephemeral_xprv("sd", from_main=True, seed_vault=seedvault)
|
|
restore_main_seed(seed_vault=seedvault, preserve_settings=True)
|
|
|
|
words = backup_system(reuse_pw=reuse_pw, save_pw=save_pw, st=st)
|
|
|
|
time.sleep(.1)
|
|
title, body = cap_story()
|
|
|
|
if st == "b39pass" and multisig:
|
|
# correct settings switch back?
|
|
# multisig is only in main wallet
|
|
# must not be copied from main to b39pass
|
|
# must not be available after backup done
|
|
assert not get_setting('multisig', None)
|
|
|
|
if notes:
|
|
# verify large notes survived
|
|
rb_notes = get_setting('notes')
|
|
assert rb_notes == notes
|
|
|
|
files = []
|
|
for copy in range(2):
|
|
if copy == 1:
|
|
title, body = cap_story()
|
|
assert 'written:' in body
|
|
|
|
fn = [ln.strip() for ln in body.split('\n') if ln.endswith('.7z')][0]
|
|
|
|
print("filename %d: %s" % (copy, fn))
|
|
|
|
files.append(fn)
|
|
garbage_collector.append(microsd_path(fn))
|
|
|
|
# write extra copy.
|
|
if not copy:
|
|
need_keypress('2')
|
|
|
|
time.sleep(.01)
|
|
|
|
bk_a = open_microsd(files[0]).read()
|
|
bk_b = open_microsd(files[1]).read()
|
|
|
|
assert bk_a == bk_b, "contents mismatch"
|
|
|
|
press_cancel()
|
|
time.sleep(.01)
|
|
|
|
verify_backup_file(fn)
|
|
decrypted = check_and_decrypt_backup(fn, words)
|
|
avail_settings = []
|
|
if seedvault and (st in [None, "b39pass"]):
|
|
assert "seedvault" in decrypted
|
|
assert "seeds" in decrypted
|
|
avail_settings.append("seeds")
|
|
avail_settings.append("seedvault")
|
|
else:
|
|
assert "seedvault" not in decrypted
|
|
assert "seeds" not in decrypted
|
|
|
|
for i in range(10):
|
|
press_cancel()
|
|
time.sleep(.01)
|
|
|
|
# test verify on device (CRC check)
|
|
if multisig:
|
|
avail_settings.append("multisig")
|
|
|
|
restore_backup_cs(files[0], words, avail_settings=avail_settings,
|
|
pass_way=pass_way)
|
|
|
|
|
|
@pytest.mark.parametrize("stype", ["words12", "words24", "xprv"])
|
|
def test_backup_ephemeral_wallet(stype, pick_menu_item, press_select, goto_home,
|
|
cap_story, pass_word_quiz, get_setting,
|
|
verify_backup_file, microsd_path, check_and_decrypt_backup,
|
|
sim_execfile, unit_test, word_menu_entry, cap_menu,
|
|
restore_backup_cs, generate_ephemeral_words, press_cancel,
|
|
import_ephemeral_xprv, reset_seed_words, seed_story_to_words):
|
|
reset_seed_words()
|
|
goto_home()
|
|
if "words" in stype:
|
|
num_words = int(stype.replace("words", ""))
|
|
sec = generate_ephemeral_words(num_words, from_main=True, seed_vault=False)
|
|
else:
|
|
sec = import_ephemeral_xprv("sd", from_main=True, seed_vault=False)
|
|
|
|
target = sim_execfile('devtest/get-secrets.py')
|
|
assert 'Error' not in target
|
|
pick_menu_item("Advanced/Tools")
|
|
pick_menu_item("Backup")
|
|
pick_menu_item("Backup System")
|
|
time.sleep(.1)
|
|
title, story = cap_story()
|
|
assert "A temporary seed is in effect" in story
|
|
assert "so backup will be of that seed" in story
|
|
press_select()
|
|
time.sleep(.1)
|
|
title, story = cap_story()
|
|
if "Use same backup file password as last time?" in story:
|
|
press_cancel()
|
|
time.sleep(.1)
|
|
title, story = cap_story()
|
|
assert title == 'NO-TITLE'
|
|
assert 'Record this' in story
|
|
assert 'password:' in story
|
|
|
|
words = seed_story_to_words(story)
|
|
|
|
assert len(words) == 12
|
|
# pass the quiz!
|
|
count, title, body = pass_word_quiz(words)
|
|
assert count >= 4
|
|
assert "same words next time" in body
|
|
assert "Press (1) to save" in body
|
|
press_cancel()
|
|
time.sleep(.01)
|
|
assert get_setting('bkpw', 'xxx') == 'xxx'
|
|
title, story = cap_story()
|
|
assert "Backup file written:" in story
|
|
fn = story.split("\n\n")[1]
|
|
assert fn.endswith(".7z")
|
|
verify_backup_file(fn)
|
|
contents = check_and_decrypt_backup(fn, words)
|
|
if "words" in stype:
|
|
assert "mnemonic" in contents
|
|
else:
|
|
assert "mnemonic" not in contents
|
|
assert simulator_fixed_words not in contents
|
|
assert simulator_fixed_tprv not in contents
|
|
# assert target == contents
|
|
if "words" in stype:
|
|
words_str = " ".join(sec)
|
|
assert words_str in contents
|
|
seed = Mnemonic.to_seed(words_str)
|
|
expect = BIP32Node.from_master_secret(seed, netcode="XTN")
|
|
else:
|
|
expect = sec
|
|
|
|
target_esk = None
|
|
target_epk = None
|
|
esk = expect.hwif(as_private=True)
|
|
epk = expect.hwif(as_private=False)
|
|
for line in contents.split("\n"):
|
|
if line.startswith("xprv ="):
|
|
target_esk = line.split("=")[-1].strip().replace('"', '')
|
|
if line.startswith("xpub ="):
|
|
target_epk = line.split("=")[-1].strip().replace('"', '')
|
|
assert target_epk == epk
|
|
assert target_esk == esk
|
|
|
|
restore_backup_cs(fn, words)
|
|
|
|
|
|
@pytest.mark.parametrize('seedvault', [False, True])
|
|
@pytest.mark.parametrize("passphrase", ["@coinkite rulez!!", "!@#!@", "AAAAAAAAAAA"])
|
|
def test_backup_bip39_wallet(passphrase, set_bip39_pw, pick_menu_item, need_keypress,
|
|
goto_home, cap_story, pass_word_quiz, get_setting,
|
|
verify_backup_file, microsd_path, check_and_decrypt_backup,
|
|
sim_execfile, unit_test, word_menu_entry, cap_menu,
|
|
restore_backup_cs, seedvault, settings_set, reset_seed_words,
|
|
seed_story_to_words, press_cancel):
|
|
reset_seed_words()
|
|
goto_home()
|
|
settings_set("seedvault", int(seedvault))
|
|
settings_set("seeds", [] if seedvault else None)
|
|
set_bip39_pw(passphrase, seed_vault=True)
|
|
target = sim_execfile('devtest/get-secrets.py')
|
|
assert 'Error' not in target
|
|
pick_menu_item("Advanced/Tools")
|
|
pick_menu_item("Backup")
|
|
pick_menu_item("Backup System")
|
|
time.sleep(.1)
|
|
title, story = cap_story()
|
|
assert "BIP39 passphrase is in effect" in story
|
|
assert "ignores passphrases and produces backup of main seed" in story
|
|
assert "(2) to back-up BIP39 passphrase wallet" in story
|
|
need_keypress("2")
|
|
time.sleep(.1)
|
|
title, story = cap_story()
|
|
if "Use same backup file password as last time?" in story:
|
|
press_cancel()
|
|
time.sleep(.1)
|
|
title, story = cap_story()
|
|
assert title == 'NO-TITLE'
|
|
assert 'Record this' in story
|
|
assert 'password:' in story
|
|
words = seed_story_to_words(story)
|
|
assert len(words) == 12
|
|
# pass the quiz!
|
|
count, title, body = pass_word_quiz(words)
|
|
assert count >= 4
|
|
assert "same words next time" in body
|
|
assert "Press (1) to save" in body
|
|
press_cancel()
|
|
time.sleep(.01)
|
|
assert get_setting('bkpw', 'xxx') == 'xxx'
|
|
title, story = cap_story()
|
|
assert "Backup file written:" in story
|
|
fn = story.split("\n\n")[1]
|
|
assert fn.endswith(".7z")
|
|
verify_backup_file(fn)
|
|
contents = check_and_decrypt_backup(fn, words)
|
|
assert "mnemonic" not in contents
|
|
assert "seedvault" not in contents
|
|
assert "seeds" not in contents
|
|
assert simulator_fixed_words not in contents
|
|
assert simulator_fixed_tprv not in contents
|
|
assert target == contents
|
|
seed = Mnemonic.to_seed(simulator_fixed_words, passphrase=passphrase)
|
|
expect = BIP32Node.from_master_secret(seed, netcode="XTN")
|
|
esk = expect.hwif(as_private=True)
|
|
epk = expect.hwif(as_private=False)
|
|
target_esk = None
|
|
target_epk = None
|
|
for line in contents.split("\n"):
|
|
if line.startswith("xprv ="):
|
|
target_esk = line.split("=")[-1].strip().replace('"', '')
|
|
if line.startswith("xpub ="):
|
|
target_epk = line.split("=")[-1].strip().replace('"', '')
|
|
assert target_epk == epk
|
|
assert target_esk == esk
|
|
|
|
restore_backup_cs(fn, words)
|
|
|
|
|
|
def test_seed_vault_backup(settings_set, reset_seed_words, generate_ephemeral_words,
|
|
import_ephemeral_xprv, restore_main_seed, settings_get,
|
|
repl, pick_menu_item, press_cancel, cap_story, get_setting,
|
|
pass_word_quiz, verify_backup_file, check_and_decrypt_backup,
|
|
restore_backup_cs, cap_menu, verify_ephemeral_secret_ui,
|
|
seed_story_to_words):
|
|
reset_seed_words()
|
|
settings_set("seedvault", 1)
|
|
settings_set("seeds", [])
|
|
expect_count = 0
|
|
ui_xfps = []
|
|
for num_words in [12, 24]:
|
|
mnemonic = generate_ephemeral_words(num_words=num_words, seed_vault=True)
|
|
xfp = verify_ephemeral_secret_ui(mnemonic=mnemonic, seed_vault=True)
|
|
ui_xfps.append(xfp)
|
|
expect_count += 1
|
|
|
|
# Ephemeral seeds - extended keys
|
|
node = import_ephemeral_xprv("sd", seed_vault=True)
|
|
xfp = verify_ephemeral_secret_ui(xpub=node.hwif(), seed_vault=True)
|
|
ui_xfps.append(xfp)
|
|
expect_count += 1
|
|
restore_main_seed(seed_vault=True)
|
|
assert expect_count == 3
|
|
assert len(ui_xfps) == expect_count
|
|
# check all saved okay
|
|
seeds = settings_get('seeds')
|
|
assert len(seeds) == expect_count
|
|
|
|
bk = repl.exec('import backups; RV.write(backups.render_backup_contents())', raw=1)
|
|
assert 'Coldcard backup file' in bk
|
|
|
|
pick_menu_item("Advanced/Tools")
|
|
pick_menu_item("Backup")
|
|
pick_menu_item("Backup System")
|
|
|
|
time.sleep(.1)
|
|
title, story = cap_story()
|
|
if "Use same backup file password as last time?" in story:
|
|
press_cancel()
|
|
time.sleep(.1)
|
|
title, story = cap_story()
|
|
assert title == 'NO-TITLE'
|
|
assert 'Record this' in story
|
|
assert 'password:' in story
|
|
words = seed_story_to_words(story)
|
|
assert len(words) == 12
|
|
# pass the quiz!
|
|
count, title, body = pass_word_quiz(words)
|
|
assert count >= 4
|
|
assert "same words next time" in body
|
|
assert "Press (1) to save" in body
|
|
press_cancel()
|
|
time.sleep(.01)
|
|
title, story = cap_story()
|
|
assert "Backup file written:" in story
|
|
fn = story.split("\n\n")[1]
|
|
assert fn.endswith(".7z")
|
|
verify_backup_file(fn)
|
|
contents = check_and_decrypt_backup(fn, words)
|
|
assert "mnemonic" in contents
|
|
assert simulator_fixed_words in contents
|
|
assert simulator_fixed_tprv in contents
|
|
assert "setting.seedvault = 1" in contents
|
|
assert "setting.seeds" in contents
|
|
|
|
restore_backup_cs(fn, words)
|
|
time.sleep(.2)
|
|
m = cap_menu()
|
|
assert "Seed Vault" in m
|
|
pick_menu_item('Seed Vault')
|
|
m = cap_menu()
|
|
assert len(m) == expect_count
|
|
sv_xfp_menu = [i.split(" ")[-1][1:-1] for i in m]
|
|
for xfp_ui in ui_xfps:
|
|
assert xfp_ui in sv_xfp_menu
|
|
|
|
|
|
def test_seed_vault_backup_frozen(reset_seed_words, settings_set, repl, build_test_seed_vault):
|
|
reset_seed_words()
|
|
settings_set("seedvault", 1)
|
|
sv = build_test_seed_vault()
|
|
settings_set("seeds", sv)
|
|
bk = repl.exec('import backups; RV.write(backups.render_backup_contents())', raw=1)
|
|
assert 'Coldcard backup file' in bk
|
|
target = json.dumps(sv)
|
|
assert target in bk
|
|
|
|
|
|
def test_clone_start(reset_seed_words, pick_menu_item, cap_story, goto_home, src_root_dir,
|
|
sim_root_dir):
|
|
sd_dir = f"{sim_root_dir}/MicroSD"
|
|
num_7z = len([i for i in os.listdir(sd_dir) if i.endswith(".7z")])
|
|
fname = "ccbk-start.json"
|
|
reset_seed_words()
|
|
goto_home()
|
|
shutil.copy(f"{src_root_dir}/testing/data/{fname}", sd_dir)
|
|
pick_menu_item("Advanced/Tools")
|
|
pick_menu_item("Backup")
|
|
pick_menu_item("Clone Coldcard")
|
|
time.sleep(1)
|
|
title, story = cap_story()
|
|
assert "Done" in story
|
|
assert "Take this MicroSD card back to other Coldcard" in story
|
|
goto_home()
|
|
assert len([i for i in os.listdir(sd_dir) if i.endswith(".7z")]) > num_7z
|
|
os.remove(f"{sd_dir}/{fname}")
|
|
|
|
# TODO check file made is a good backup, with correct password
|
|
|
|
|
|
def test_bkpw_override(reset_seed_words, override_bkpw, goto_home, pick_menu_item,
|
|
cap_story, press_select, garbage_collector, microsd_path,
|
|
restore_backup_cs, is_q1):
|
|
reset_seed_words() # clean slate
|
|
old_pw = None
|
|
test_cases = [
|
|
32 * "a",
|
|
(26 * "?") + "!@#$%^&*()",
|
|
]
|
|
if is_q1:
|
|
# not needed on mk4 - even tho works (takes too much time)
|
|
# Mk4 display is not suitable for these type of passwords anyways
|
|
test_cases += [
|
|
"arm prob slot merc hub fiel wing aver tale undo diar boos army cabl mous teac drif risk frow achi poet ecol boss grit",
|
|
" ".join(12 * ["elevator"]),
|
|
" ".join(12 * ["fever"]),
|
|
64 * "Q",
|
|
]
|
|
|
|
fnames = []
|
|
for pw in test_cases:
|
|
override_bkpw(pw, old_pw)
|
|
|
|
goto_home()
|
|
pick_menu_item("Advanced/Tools")
|
|
pick_menu_item("Backup")
|
|
pick_menu_item("Backup System")
|
|
time.sleep(1)
|
|
title, story = cap_story()
|
|
split_pw = pw.split(" ")
|
|
if len(split_pw) == 12:
|
|
assert (' 1: %s' % split_pw[0]) in story
|
|
assert ('12: %s' % split_pw[-1]) in story
|
|
else:
|
|
# not words of len 12
|
|
assert ("%s...%s" % (pw[0], pw[-1])) in story
|
|
|
|
press_select()
|
|
time.sleep(1)
|
|
title, story = cap_story()
|
|
assert "Backup file written" in story
|
|
fname = story.split("\n\n")[1]
|
|
garbage_collector.append(microsd_path(fname))
|
|
fnames.append(fname)
|
|
press_select()
|
|
|
|
for pw, fn in zip(test_cases, fnames):
|
|
restore_backup_cs(fn, pw, custom_bkpw=True)
|
|
|
|
# EOF
|