From e0f728205d59ab54e283be55e6a1346cf75a4d99 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Wed, 11 Aug 2021 10:32:53 +0200 Subject: [PATCH] Split up validating, verifying and storing of recovery code --- .../recoverycode/RecoveryCodeInputFragment.kt | 19 ++++++---- .../ui/recoverycode/RecoveryCodeViewModel.kt | 36 +++++++++++++------ 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeInputFragment.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeInputFragment.kt index fdd8c1e2..8211a015 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeInputFragment.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeInputFragment.kt @@ -30,7 +30,7 @@ import com.stevesoltys.seedvault.ui.LiveEventHandler import org.koin.androidx.viewmodel.ext.android.sharedViewModel import java.util.Locale -internal const val ARG_FOR_NEW_CODE = "forVerifyingNewCode" +internal const val ARG_FOR_NEW_CODE = "forStoringNewCode" class RecoveryCodeInputFragment : Fragment() { @@ -57,7 +57,7 @@ class RecoveryCodeInputFragment : Fragment() { /** * True if this is for verifying a new recovery code, false for verifying an existing one. */ - private var forVerifyingNewCode: Boolean = true + private var forStoringNewCode: Boolean = true override fun onCreateView( inflater: LayoutInflater, @@ -85,7 +85,7 @@ class RecoveryCodeInputFragment : Fragment() { wordList = v.findViewById(R.id.wordList) arguments?.getBoolean(ARG_FOR_NEW_CODE, true)?.let { - forVerifyingNewCode = it + forStoringNewCode = it } return v @@ -116,14 +116,14 @@ class RecoveryCodeInputFragment : Fragment() { editText.setAdapter(adapter) } doneButton.setOnClickListener { done() } - newCodeButton.visibility = if (forVerifyingNewCode) GONE else VISIBLE + newCodeButton.visibility = if (forStoringNewCode) GONE else VISIBLE newCodeButton.setOnClickListener { generateNewCode() } viewModel.existingCodeChecked.observeEvent(viewLifecycleOwner, LiveEventHandler { verified -> onExistingCodeChecked(verified) } ) - if (forVerifyingNewCode && isDebugBuild() && !viewModel.isRestore) debugPreFill() + if (forStoringNewCode && isDebugBuild() && !viewModel.isRestore) debugPreFill() } private fun getInput(): List = ArrayList(WORD_NUM).apply { @@ -134,11 +134,18 @@ class RecoveryCodeInputFragment : Fragment() { val input = getInput() if (!allFilledOut(input)) return try { - viewModel.validateAndContinue(input, forVerifyingNewCode) + viewModel.validateCode(input) } catch (e: ChecksumException) { Toast.makeText(context, R.string.recovery_code_error_checksum_word, LENGTH_LONG).show() + return } catch (e: InvalidWordException) { showWrongWordError(input) + return + } + if (forStoringNewCode) { + viewModel.storeNewCode(input) + } else { + viewModel.verifyExistingCode(input) } } diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeViewModel.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeViewModel.kt index 3eb3329e..d851ea9e 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeViewModel.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeViewModel.kt @@ -57,23 +57,37 @@ internal class RecoveryCodeViewModel( internal var isRestore: Boolean = false @Throws(InvalidWordException::class, ChecksumException::class) - fun validateAndContinue(input: List, forVerifyingNewCode: Boolean) { + fun validateCode(input: List): Mnemonics.MnemonicCode { val code = Mnemonics.MnemonicCode(input.toMnemonicChars()) try { code.validate() } catch (e: WordCountException) { throw AssertionError(e) } - val seed = code.toSeed() - if (forVerifyingNewCode) { - keyManager.storeBackupKey(seed) - keyManager.storeMainKey(seed) - mRecoveryCodeSaved.setEvent(true) - } else { - val verified = crypto.verifyBackupKey(seed) - if (verified && !keyManager.hasMainKey()) keyManager.storeMainKey(seed) - mExistingCodeChecked.setEvent(verified) - } + return code + } + + /** + * Verifies existing recovery code and returns result via [existingCodeChecked]. + */ + fun verifyExistingCode(input: List) { + // we validate the code again, just in case + val seed = validateCode(input).toSeed() + val verified = crypto.verifyBackupKey(seed) + // store main key at this opportunity if it is still missing + if (verified && !keyManager.hasMainKey()) keyManager.storeMainKey(seed) + mExistingCodeChecked.setEvent(verified) + } + + /** + * Stores a new recovery code and returns result via [recoveryCodeSaved]. + */ + fun storeNewCode(input: List) { + // we validate the code again, just in case + val seed = validateCode(input).toSeed() + keyManager.storeBackupKey(seed) + keyManager.storeMainKey(seed) + mRecoveryCodeSaved.setEvent(true) } /**