Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Passphrase Verification for Seed Backup Flow #291

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/seedsigner/gui/screens/seed_screens.py
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,22 @@ def __post_init__(self):



@dataclass
class SeedPassphraseTestPromptScreen(ButtonListScreen):
def __post_init__(self):
self.title = "Verify Passphrase?"
self.show_back_button = False
self.is_bottom_list = True
super().__post_init__()

self.components.append(TextArea(
text="Optionally verify that your passphrase backup is correct.",
screen_y=self.top_nav.height,
is_text_centered=True,
))



@dataclass
class SeedExportXpubCustomDerivationScreen(KeyboardScreen):
def __post_init__(self):
Expand Down
133 changes: 126 additions & 7 deletions src/seedsigner/views/seed_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -958,8 +958,10 @@ def run(self):
****************************************************************************"""
class SeedWordsBackupTestPromptView(View):
def __init__(self, seed_num: int, bip85_data: dict = None):
super().__init__()
self.seed_num = seed_num
self.bip85_data = bip85_data
self.seed = self.controller.get_seed(self.seed_num)


def run(self):
Expand All @@ -978,7 +980,10 @@ def run(self):

elif button_data[selected_menu_num] == SKIP:
if self.seed_num is not None:
return Destination(SeedOptionsView, view_args=dict(seed_num=self.seed_num))
if self.seed.passphrase:
return Destination(SeedPassphraseTestPromptView, view_args=dict(seed_num=self.seed_num))
else:
return Destination(SeedOptionsView, view_args=dict(seed_num=self.seed_num))
else:
return Destination(SeedFinalizeView)

Expand Down Expand Up @@ -1118,6 +1123,115 @@ def run(self):
else:
return Destination(SeedFinalizeView)

"""****************************************************************************
Passphrase Verification Test
****************************************************************************"""

class SeedPassphraseTestPromptView(View):
def __init__(self, seed_num: int, num_attempts: int = 0):
self.seed_num = seed_num
self.num_attempts = num_attempts

def run(self):
VERIFY = "Verify"
SKIP = "Skip"
button_data = [VERIFY, SKIP]

selected_menu_num = seed_screens.SeedPassphraseTestPromptScreen(
button_data=button_data,
).display()

if button_data[selected_menu_num] == VERIFY:
return Destination(
SeedPassphraseInputView,
view_args=dict(
seed_num=self.seed_num,
num_attempts=self.num_attempts,
)
)

elif button_data[selected_menu_num] == SKIP:
return Destination(SeedOptionsView, view_args=dict(seed_num=self.seed_num))



class SeedPassphraseInputView(View):
def __init__(self, seed_num: int, num_attempts: int):
super().__init__()
self.seed_num = seed_num
self.num_attempts = num_attempts
self.seed = self.controller.get_seed(seed_num)

def run(self):
ret = seed_screens.SeedAddPassphraseScreen(passphrase="").display()

if ret == RET_CODE__BACK_BUTTON:
return Destination(BackStackView)
elif ret == self.seed.passphrase:
return Destination(SeedPassphraseTestSuccessView, view_args=dict(seed_num=self.seed_num))
else:
if self.num_attempts <= 10:
return Destination(
SeedPassphraseTestMistakeView,
view_args=dict(
seed_num=self.seed_num,
num_attempts=self.num_attempts+1
)
)
else:
return Destination(NotYetImplementedView)



class SeedPassphraseTestSuccessView(View):
def __init__(self, seed_num):
self.seed_num = seed_num

def run(self):
LargeIconStatusScreen(
title="Passphrase Verified",
show_back_button=False,
status_headline="Success!",
text="The passphrase you entered matches the one used to create this seed.",
button_data=["OK"]
).display()

return Destination(SeedOptionsView, view_args=dict(seed_num=self.seed_num), clear_history=True)



class SeedPassphraseTestMistakeView(View):
def __init__(self, seed_num: int, num_attempts):
super().__init__()
self.seed = self.controller.get_seed(seed_num)
self.seed_num = seed_num
self.num_attempts = num_attempts

def run(self):
RETRY = "Try Again"
SKIP = "Skip Verification"
button_data = [RETRY, SKIP]

selected_menu_num = DireWarningScreen(
title="Verification Error",
show_back_button=False,
status_headline=f"Incorrect Passphrase",
text=f"Incorrect passphrase for this seed.",
button_data=button_data,
).display()

if button_data[selected_menu_num] == RETRY:
return Destination(
SeedPassphraseInputView,
view_args=dict(
seed_num=self.seed_num,
num_attempts=self.num_attempts,
)
)
elif button_data[selected_menu_num] == SKIP:
return Destination(SeedOptionsView, view_args=dict(seed_num=self.seed_num), clear_history=True)
return



"""****************************************************************************
Expand Down Expand Up @@ -1300,8 +1414,8 @@ def __init__(self, seed_num: int):

def run(self):
SCAN = ("Confirm SeedQR", FontAwesomeIconConstants.QRCODE)
DONE = "Done"
button_data = [SCAN, DONE]
SKIP = "Skip"
button_data = [SCAN, SKIP]

selected_menu_option = seed_screens.SeedTranscribeSeedQRConfirmQRPromptScreen(
title="Confirm SeedQR?",
Expand All @@ -1314,8 +1428,11 @@ def run(self):
elif button_data[selected_menu_option] == SCAN:
return Destination(SeedTranscribeSeedQRConfirmScanView, view_args={"seed_num": self.seed_num})

elif button_data[selected_menu_option] == DONE:
return Destination(SeedOptionsView, view_args={"seed_num": self.seed_num}, clear_history=True)
elif button_data[selected_menu_option] == SKIP:
if self.seed.passphrase:
return Destination(SeedPassphraseTestPromptView, view_args=dict(seed_num=self.seed_num))
else:
return Destination(SeedOptionsView, view_args={"seed_num": self.seed_num}, clear_history=True)



Expand Down Expand Up @@ -1357,8 +1474,10 @@ def run(self):
show_back_button=False,
button_data=["OK"],
).display()

return Destination(SeedOptionsView, view_args={"seed_num": self.seed_num})
if self.seed.passphrase:
return Destination(SeedPassphraseTestPromptView, view_args=dict(seed_num=self.seed_num))
else:
return Destination(SeedOptionsView, view_args={"seed_num": self.seed_num})

else:
# Will this case ever happen? Will trigger if a different kind of QR code is scanned
Expand Down